SelectFromModel scikit-learn:训练和测试阶段生成的特征矩阵维度
Posted
技术标签:
【中文标题】SelectFromModel scikit-learn:训练和测试阶段生成的特征矩阵维度【英文标题】:SelectFromModel scikit-learn: Resulting Feature Matrix Dimensions During Training and Testing Stages 【发布时间】:2017-12-10 18:59:28 【问题描述】:我刚开始在我的数据集上使用特征选择,我遇到了SelectFromModel
模块,它自动将原始的n x m
特征矩阵转换为n x k
,其中k << m
。但是,k
是先验未知的。
我想知道我应该如何使用它来训练模型,然后使用现有模型来预测新数据。众所周知,训练数据实例和测试数据实例必须用相同维度的特征向量表示。
但是这个维度会依赖于数据,不能用SelectFromModel
控制。
我编写了如下代码:
X_train = ... # feature matrix
print("BEFORE FEATURE SELECTION, FEATURE MATRIX shape=".format(X_train.shape))
# output of this line is 24771, 11680
select = SelectFromModel(LogisticRegression(class_weight='balanced',penalty="l1",C=0.01))
X_train = select.fit_transform(X_train, y_train)
print("AFTER FEATURE SELECTION, FEATURE MATRIX shape=".format(M.shape))
# output of this line is 24771, 170
测试时,加载预训练好的模型,新的数据实例需要用相同的特征向量表示:
X_test = ... # feature matrix
# the next line maps test set features to the feature vectors observed on training data, using corresponding vocabularies
X_test=map_test_to_train_featurevectors(X_test, X_train)
print("BEFORE FEATURE SELECTION, FEATURE MATRIX shape=".format(X_test.shape))
# output of this line is 550, 11680, so test instances has same vector dimension as training instances
select = SelectFromModel(LogisticRegression(class_weight='balanced',penalty="l1",C=0.01))
X_test = select.fit_transform(X_test, y_test)
print("AFTER FEATURE SELECTION, FEATURE MATRIX shape=".format(M.shape))
# output of this line is 550, 5, but the pre-trained model will expect 170
best_estimator = util.load_classifier_model(model_file)
prediction_dev = best_estimator.predict_proba(X_test)
最后一行显然会产生如下错误,因为训练和测试时特征选择后得到的特征矩阵是不同的维度:
ValueError: X has 5 features per sample; expecting 169
是不是就不能这样使用 SelectFromModel 了?只能用于训练和评估吗?
【问题讨论】:
【参考方案1】:您不能以这种方式使用SelectFromModel()
模块。它并没有简单地降低维度复杂性。相比之下,PCA().fit_transform(**data)
会按照您想要的方式工作。 SelectFromModel()
上的文档说明如下:
用于根据重要性权重选择特征的元转换器。
话虽如此,您将所需的模型传递给SelectFromModel()
并将其与输入数据相匹配。完成此操作后,它会根据模型权重的重要性提取最可行的特征。与这种方法相比,PCA()
处理数据的解释方差,并努力尽可能多地保存数据,同时降低数据维度的复杂性。这非常方便,因为您可以手动将解释方差比设置为原始输入数据。
但是,您尝试通过实现LogisticRegression()
的另一个拟合来转换(即减少)测试数据的维度。它将为这个集合计算自己的权重,因为它与训练阶段的集合完全不同。因此,它根据与测试集相关的权重的重要性来选择最重要的特征,而不是训练集。
您可能会遇到以下两种方法:
观察select.fit_transform(X_train, y_train)
之后使用了哪些170个特征,并创建一个与X_test
相同特征的新变量。因此,您将避免指向不同大小的错误。
实现降维方法,如PCA或SVD
希望对你有帮助!
【讨论】:
以上是关于SelectFromModel scikit-learn:训练和测试阶段生成的特征矩阵维度的主要内容,如果未能解决你的问题,请参考以下文章
如何确定 SelectFromModel() 中选择特征的阈值?
ValueError:使用 GridSearchCV 时估计器 SelectFromModel 的参数 C 无效
来自 sklearn 的 SelectFromModel 在随机森林和梯度提升分类器上提供了显着不同的特征