python - Sklearn Pipeline 连接轴的所有输入数组维度必须完全匹配
问题描述
import pandas as pd
from sklearn.feature_extraction.text import CountVectorizer, TfidfTransformer
from sklearn.pipeline import Pipeline
from sklearn.svm import LinearSVC
from sklearn.preprocessing import MinMaxScaler
from sklearn.compose import ColumnTransformer
data = [[1, 3, 4, 'text', 'pos'], [9, 3, 6, 'text more', 'neg']]
data = pd.DataFrame(data, columns=['Num1', 'Num2', 'Num3', 'Text field', 'Class'])
tweet_text_transformer = Pipeline(steps=[
('count_vectoriser', CountVectorizer()),
('tfidf', TfidfTransformer())
])
numeric_transformer = Pipeline(steps=[
('scaler', MinMaxScaler())
])
preprocessor = ColumnTransformer(transformers=[
# (name, transformer, column(s))
('tweet', tweet_text_transformer, ['Text field']),
('numeric', numeric_transformer, ['Num1', 'Num2', 'Num3'])
])
pipeline = Pipeline(steps=[
('preprocessor', preprocessor),
('classifier', LinearSVC())
])
X_train = data.loc[:, 'Num1':'Text field']
y_train = data['Class']
pipeline.fit(X_train, y_train)
我不明白这个错误来自哪里:
ValueError:连接轴的所有输入数组维度必须完全匹配,但沿维度 0,索引 0 处的数组大小为 1,索引 1 处的数组大小为 2
解决方案
原因
问题出在preprocessor
管道中,该管道的工作方式是水平堆叠的输出tweet_text_transformer
和输出numeric_transformer
,为了成功实现这一点,输出(tweet_text_transformer 和 numeric_transformer)必须具有相同的行数(即:元素数在轴 0 或维度 0 中)
但是当执行上述管道时tweet_text_processor
,尽管我们希望它实际上给出具有 4 个元素的 2 * 2 矩阵,因为 CountVectorizer 将输出存储为稀疏矩阵,它会删除矩阵中的任何零(以节省内存)这会将数组减少到 2 *2 矩阵,但其中只有 3 个元素,当它与 numeric_transformer 的输出堆叠时,它不满足上述条件(因为数字转换器将在轴 0 中有两个元素,而 twwet_text_processor 不会)
解决方案
- 创建一个自定义转换器,将此稀疏矩阵转换为 numpy 数组
- 此外,由于只有一列,因此压缩 Pandas 数据框以将其转换为 Panadas 系列
import pandas as pd
from sklearn.feature_extraction.text import CountVectorizer, TfidfTransformer
from sklearn.pipeline import Pipeline
from sklearn.svm import LinearSVC
from sklearn.preprocessing import MinMaxScaler
from sklearn.compose import ColumnTransformer
data = [[1, 3, 4, 'text', 'pos'], [9, 3, 6, 'text more', 'neg']]
data = pd.DataFrame(data, columns=['Num1', 'Num2', 'Num3', 'Text field', 'Class'])
class TweetTextProcessor(BaseEstimator, TransformerMixin):
def __init__(self):
self.tweet_text_transformer = Pipeline(steps=[
('count_vectoriser', CountVectorizer()),
('tfidf', TfidfTransformer()) ])
def fit(self, X, y=None):
return self
def transform(self, X, y=None):
return self.tweet_text_transformer.fit_transform(X.squeeze()).toarray()
numeric_transformer = Pipeline(steps=[
('scaler', MinMaxScaler())
])
preprocessor = ColumnTransformer(transformers=[
('tweet', TweetTextProcessor(), ['Text field']),
('numeric', numeric_transformer, ['Num1', 'Num2', 'Num3'])
])
pipeline = Pipeline(steps=[
('preprocessor', preprocessor),
('classifier', LinearSVC())
])
X_train = data.loc[:, 'Num1':'Text field']
y_train = data['Class']
pipeline.fit(X_train, y_train)
上面的代码应该可以工作,否则请告诉我或者解释不清楚(希望是这样)
推荐阅读
- project-reactor - 在“嵌套”`Mono`的情况下`flatMap`和`block`之间有什么区别吗
- python - python中有没有办法使用 __init_subclass__ 生成的子类属性作为类型提示
- nas - 在 Webviz 中从 NAS 流式传输 rosbag
- tensorflow - ValueError:一个操作对梯度有“无”
- snowflake-cloud-data-platform - 如何使用 Snowflake-SQL 执行同期群分析?
- git - 在主存储库中包含子模块的内容
- swiftui - iOS 15 中的 ListStyle 怪异
- javascript - Tableau JS API:提取为 SQLProxy 而不是值的数据列
- vue.js - 在vuejs中单击列表中的名称时切换页面?
- r - R 错误:期望单个字符串值:[type=character; 范围=5]