python - ValueError:发现样本数量不一致的输入变量:[6, 80]
问题描述
我无法在管道中处理以下代码(它是管道imblearn
)
features = training_data.loc[:, training_data.columns[:-1]]
labels = training_data.loc[:, training_data.columns[-1:]]
X_train, X_test, y_train, y_test = train_test_split(features, labels, test_size=0.2)
print(X_train.shape, y_train.shape)
形状的打印输出是:(80, 6) (80, 1)
algorithms = [
svm.LinearSVC(),
ensemble.RandomForestClassifier(),
]
def train(algorithm, X_train, y_train):
model = Pipeline([
('vect', TfidfVectorizer()),
('smote', SMOTETomek()),
('chi', SelectKBest(chi2, k=1000)),
('classifier', algorithm)
])
model.fit(X_train, y_train)
return model
score_dict = {}
algorithm_to_model_dict = {}
for algorithm in algorithms:
model = train(algorithm, X_train, y_train)
score = model.score(X_test, y_test)
score_dict[algorithm] = int(score * 100)
algorithm_to_model_dict[algorithm] = model
特征和标签都是文本(我正在做文本分析)。
正在从fit
调用中引发异常
我究竟做错了什么?
解决方案
发生这种情况是因为您的管道中有一个文本转换器对象。这种方法的问题是管道会将整个数据帧传递给TfidfVectorizer
. 但是,文本转换器需要scikit-learn
一维输入。
传递 2d 数据框会TfidfVectorizer
导致一些奇怪的处理,它会将列名误认为是文档。您可以使用这个简单的示例进行检查:
X = pd.DataFrame({
'f1': ['This is doc1', 'This is doc2',
'This is doc3', 'This is doc4', 'This is doc5'],
'f2': [0, 1, 1, 0, 0]
})
vec = TfidfVectorizer()
print(vec.fit(X).get_feature_names())
>>> ['f1', 'f2']
这解释了为什么错误消息指出样本数量不一致:TfidfVectorizer
认为数据框中的 6 列是样本,它们的名称是特征。
如果要TfidfVectorizer
在管道中使用,则必须确保仅将带有文本文档的列传递给它。您可以通过将其包装在 a 中来实现ColumnTransformer
:
# if only one column needs to be transformed
transformer = ColumnTransformer(
[('vec', TfidfVectorizer(), column)], # column should be a string or int
remainder='passthrough'
)
# if more than one column needs to be transformed (discouraged, see Note below)
transformer = ColumnTransformer(
[('vec', TfidfVectorizer(), col_1), # col_1 should be a string or int
...
('vec', TfidfVectorizer(), col_n)], # col_n should be a string or int
remainder='passthrough'
)
column
用索引或必须转换的列的名称替换上面的TfidfVectorizer
内容,它只会处理这个特定的列。这remainder='passthrough'
将确保其他列保持原样并与结果连接。然后,您可以像这样在管道中使用它:
model = Pipeline([
('vect', transformer),
('smote', SMOTETomek()),
('chi', SelectKBest(chi2, k=1000)),
('classifier', algorithm)
])
笔记
如果您必须使用文本转换多个列,您应该考虑将列条目合并到一个单独的组合文档中,并且只转换这个组合文档。否则,每一列都将被处理一个新的词汇表,尽管这些词汇表可能在某种程度上重叠,你最终可能会得到一个非常高的维度/很多特征。
推荐阅读
- node.js - react-dropzone-uploader AVI 文件停留在“准备中”状态
- python - 使用 Python GTK+ 3 将对话框按钮居中对齐
- mysql - 发出套接字,但数据未显示在高图表中
- angular - 角度 matDatepicker 没有 mat-form-field
- google-cast - 如何测试多个版本的投射接收器应用程序
- javascript - 如何通过字符串中“单词”的升序对字符串数组进行排序?javascript
- android - 如何选择性地观察 Android Room 数据库 INSERT、DELETE 和 UPDATE 事件?
- c++ - g++ 不会在模板代码中发出 -Wsign-compare
- javascript - 如何让我的函数上限(x)在命令提示符下生成一个数字?
- javascript - 为什么在尝试搜索二叉树时出现无限循环?