我目前正在开发一种用于工单分类的机器学习算法,该算法将标题、描述和客户名称组合在一起,以预测工单应分配给哪个团队,但在过去几天一直被困住。
标题和描述都是自由文本,因此我通过 TfidfVectorizer 传递它们。客户名称是一个类别,为此我使用 OneHotEncoder。我希望它们在管道中工作,因此将它们与列转换器连接起来,我可以在其中传递整个数据帧并对其进行处理。
file = "train_data.csv"
train_data= pd.read_csv(train_file)
string_features = ['Title', 'Description']
string_transformer = Pipeline(steps=[('tfidf', TfidfVectorizer()))
categorical_features = ['Customer']
categorical_transformer = Pipeline(steps=[('OHE', preprocessing.OneHotEncoder()))
preprocessor = ColumnTransformer(transformers = [('str', string_transformer, string_features), ('cat', categorical_transformer, categorical_features)])
clf = Pipeline(steps=[('preprocessor', preprocessor),('clf', SGDClassifier())]
X_train = train_data.drop('Team', axis=1)
y_train = train_data['Team']
clf.fit(X_train, y_train)
但是我收到错误:除串联轴之外的所有输入数组维度都必须完全匹配。
查看后,print(OneHotEncoder().fit_transform(X_train['Customer']))
本身返回一个错误:预期的 2d 数组取而代之的是 1d 数组。
我相信 OneHotEncoder 失败了,因为它需要一个数组数组(一个 pandas 数据帧),每个数组的长度都包含客户名称。但只是得到一个 Pandas 系列。通过使用 .to_frame() 将系列转换为数据帧,打印输出现在似乎与 TfidfVectorizer 输出的内容匹配,并且尺寸也应该匹配。
有没有办法可以修改管道中的 OneHotEncoder,以便它接受一维输入?或者我可以在管道中添加一些东西,在将其传递到 OneHotEncoder 之前对其进行转换?我是否正确,这就是错误的原因?
谢谢。
最佳答案
我认为问题在于您向 TfIdfVectorizer
提供了两列(因此转换为 DataFrame
)。这是行不通的:TfIdfVectorizer
需要一个字符串列表。因此,一个直接的解决方案(因此检查这是否确实是问题的根源)是将这一行更改为:string_features = 'Description'
。请注意,这不是一个列表,它只是一个字符串。因此,Series
被传递到 TfIdfVectorizer
,而不是 DataFrame
。
如果您想合并两个字符串列,您可以
连接字符串,这样您就可以保留一列(这是最简单的),或者
适合两个不同的
TfIdfVectorizers
,这更复杂,但可能性能更好。例如,参见Computing separate tfidf scores for two different columns using sklearn
如果这不能解决您的问题,我建议您分享一些示例数据,以便我们可以实际测试正在发生的情况。
我相信您感知到的错误与实际管道之间的差异在于您给它 X_train['Customer']
(又是一个 Series
) ,但在实际管道中,您要为其提供 X_train[['Customer']]
(DataFrame
)。
关于python - Scikit Learn - 组合 TfidfVectorizer 和 OneHotEncoder 的输出 - 维度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54824449/