如何使用 FeatureUnion 和 Pipeline 正确构建包含文本和数值数据的 SGDClassifier?
How to properly build a SGDClassifier with both text and numerical data using FeatureUnion and Pipeline?
我有一个功能 DF 看起来像
文字
人数
文本 1
0
文字2
1
...
...
其中 number
列是二进制的,text
列包含每行约 2k 个字符的文本。目标 DF 包含三个 类.
def get_numeric_data(x):
return [x.number.values]
def get_text_data(x):
return [record for record in x.text.values]
transfomer_numeric = FunctionTransformer(get_numeric_data)
transformer_text = FunctionTransformer(get_text_data)
当尝试适应下面的代码时,我收到错误 File "C:\fakepath\scipy\sparse\construct.py", line 588, in bmat raise ValueError(msg) ValueError: blocks[0,:] has incompatible row dimensions. Got blocks[0,1].shape[0] == 98, expected 1.
。我尝试以不同的方式构建函数 get_text_data
和 get_numerical_data
,但 none 有所帮助。
combined_clf = Pipeline([
('features', FeatureUnion([
('numeric_features', Pipeline([
('selector', transfomer_numeric)
])),
('text_features', Pipeline([
('selector', transformer_text),
('vect', vect),
('tfidf', tfidf),
('scaler', scl),
]))
])),
('clf', SGDClassifier(random_state=42,
max_iter=int(10 ** 6 / len(X_train)), shuffle=True))
])
gs_clf = GridSearchCV(combined_clf, parameters, cv=5,n_jobs=-1)
gs_clf.fit(X_train, y_train)
主要问题是您return计算数值的方式。 x.number.values
将 return 一个形状为 (n_samples,)
的数组,FeatureUnion
对象稍后将尝试将其与文本特征转换的结果相结合。在您的情况下,转换后的文本特征的维度是 (n_samples, 98)
,它不能与您为数字特征获得的向量相结合。
一个简单的解决方法是将向量重塑为维度为 (n_samples, 1)
的二维数组,如下所示:
def get_numeric_data(x):
return x.number.values.reshape(-1, 1)
请注意,我删除了表达式周围的方括号,因为它们不必要地将结果包装在列表中。
虽然以上内容会使您的代码 运行,但您的代码中仍有一些地方效率不高,可以改进。
首先是多余的表达式 [record for record in x.text.values]
,因为 x.text.values
已经足够了。唯一的区别是前者是 list
对象,而后者是通常首选的 numpy ndarray
。
其次是 Ben Reiniger 在他的评论中已经说过的内容。 FeatureUnion
意味着对相同的数据执行多个转换并将结果组合到一个对象中。但是,您似乎只想将文本特征与数字特征分开转换。在这种情况下,ColumnTransformer
提供了一种更简单和规范的方法:
combined_clf = Pipeline([
('transformer', ColumnTransformer([
('vectorizer', Pipeline([
('vect', vect),
('tfidf', tfidf),
('scaler', scl)
]), 'text')
], remainder='passthrough')),
('clf', SGDClassifier(random_state=42, max_iter=int(10 ** 6 / len(X_train)), shuffle=True))
])
上面发生的事情是 ColumnTransformer
仅选择文本列并将其传递到转换管道,最终将其与刚刚传递的数字列合并。请注意,定义您自己的选择器已经过时,因为 ColumnTransformer
将通过指定每个转换器要转换的列来解决这个问题。有关详细信息,请参阅 documentation。
我有一个功能 DF 看起来像
文字 | 人数 |
---|---|
文本 1 | 0 |
文字2 | 1 |
... | ... |
其中 number
列是二进制的,text
列包含每行约 2k 个字符的文本。目标 DF 包含三个 类.
def get_numeric_data(x):
return [x.number.values]
def get_text_data(x):
return [record for record in x.text.values]
transfomer_numeric = FunctionTransformer(get_numeric_data)
transformer_text = FunctionTransformer(get_text_data)
当尝试适应下面的代码时,我收到错误 File "C:\fakepath\scipy\sparse\construct.py", line 588, in bmat raise ValueError(msg) ValueError: blocks[0,:] has incompatible row dimensions. Got blocks[0,1].shape[0] == 98, expected 1.
。我尝试以不同的方式构建函数 get_text_data
和 get_numerical_data
,但 none 有所帮助。
combined_clf = Pipeline([
('features', FeatureUnion([
('numeric_features', Pipeline([
('selector', transfomer_numeric)
])),
('text_features', Pipeline([
('selector', transformer_text),
('vect', vect),
('tfidf', tfidf),
('scaler', scl),
]))
])),
('clf', SGDClassifier(random_state=42,
max_iter=int(10 ** 6 / len(X_train)), shuffle=True))
])
gs_clf = GridSearchCV(combined_clf, parameters, cv=5,n_jobs=-1)
gs_clf.fit(X_train, y_train)
主要问题是您return计算数值的方式。 x.number.values
将 return 一个形状为 (n_samples,)
的数组,FeatureUnion
对象稍后将尝试将其与文本特征转换的结果相结合。在您的情况下,转换后的文本特征的维度是 (n_samples, 98)
,它不能与您为数字特征获得的向量相结合。
一个简单的解决方法是将向量重塑为维度为 (n_samples, 1)
的二维数组,如下所示:
def get_numeric_data(x):
return x.number.values.reshape(-1, 1)
请注意,我删除了表达式周围的方括号,因为它们不必要地将结果包装在列表中。
虽然以上内容会使您的代码 运行,但您的代码中仍有一些地方效率不高,可以改进。
首先是多余的表达式 [record for record in x.text.values]
,因为 x.text.values
已经足够了。唯一的区别是前者是 list
对象,而后者是通常首选的 numpy ndarray
。
其次是 Ben Reiniger 在他的评论中已经说过的内容。 FeatureUnion
意味着对相同的数据执行多个转换并将结果组合到一个对象中。但是,您似乎只想将文本特征与数字特征分开转换。在这种情况下,ColumnTransformer
提供了一种更简单和规范的方法:
combined_clf = Pipeline([
('transformer', ColumnTransformer([
('vectorizer', Pipeline([
('vect', vect),
('tfidf', tfidf),
('scaler', scl)
]), 'text')
], remainder='passthrough')),
('clf', SGDClassifier(random_state=42, max_iter=int(10 ** 6 / len(X_train)), shuffle=True))
])
上面发生的事情是 ColumnTransformer
仅选择文本列并将其传递到转换管道,最终将其与刚刚传递的数字列合并。请注意,定义您自己的选择器已经过时,因为 ColumnTransformer
将通过指定每个转换器要转换的列来解决这个问题。有关详细信息,请参阅 documentation。