带有TfidfVectorizer的ColumnTransformer产生“空词汇”错误

时间:2019-02-14 16:27:47

标签: python scikit-learn

我正在使用ColumnTransformer进行一个非常简单的实验,目的是转换列数组,在此示例中为[“ a”]:

from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.compose import ColumnTransformer
dataset = pd.DataFrame({"a":["word gone wild","gone with wind"],"c":[1,2]})
tfidf = TfidfVectorizer(min_df=0)
clmn = ColumnTransformer([("tfidf", tfidf, ["a"])],remainder="passthrough")
clmn.fit_transform(dataset)

哪个给我:

ValueError: empty vocabulary; perhaps the documents only contain stop words

很明显,TfidfVectorizer可以自己完成fit_transform()

tfidf.fit_transform(dataset.a)
<2x5 sparse matrix of type '<class 'numpy.float64'>'
    with 6 stored elements in Compressed Sparse Row format>

这种错误的原因可能是什么,以及如何纠正该错误?

2 个答案:

答案 0 :(得分:1)

那是因为您要提供["a"]中的"a"而不是ColumnTransformer。根据文档:

  

如果转换器期望X为一维数组(矢量),则应使用标量字符串或整数,否则会将二维数组传递给转换器。

现在,TfidfVectorizer需要使用单个字符串迭代器进行输入(因此是一维字符串数组)。但是由于您正在发送ColumnTransformer中的列名列表(即使该列表仅包含单个列),所以它将是二维数组,并将传递给TfidfVectorizer。因此是错误。

将其更改为:

clmn = ColumnTransformer([("tfidf", tfidf, "a")],
                         remainder="passthrough")

为进一步了解,请尝试使用以上内容从pandas DataFrame中选择数据。在执行以下操作时,请检查返回数据的格式(dtype,形状):

dataset['a']

vs 

dataset[['a']]

更新:@SergeyBushmanov,关于您对其他答案的评论,我认为您在误解文档。如果要在两列上执行tfidf,则需要传递两个转换器。像这样:

tfidf_1 = TfidfVectorizer(min_df=0)
tfidf_2 = TfidfVectorizer(min_df=0)
clmn = ColumnTransformer([("tfidf_1", tfidf_1, "a"), 
                          ("tfidf_2", tfidf_2, "b")
                         ],
                         remainder="passthrough")

答案 1 :(得分:0)

我们可以创建一个自定义的tfidf转换器,该转换器可以采用一组列,然后在应用.fit().transform()之前将它们连接起来。

尝试一下!

from sklearn.base import BaseEstimator,TransformerMixin

class custom_tfidf(BaseEstimator,TransformerMixin):
    def __init__(self,tfidf):
        self.tfidf = tfidf

    def fit(self, X, y=None):
        joined_X = X.apply(lambda x: ' '.join(x), axis=1)
        self.tfidf.fit(joined_X)        
        return self

    def transform(self, X):
        joined_X = X.apply(lambda x: ' '.join(x), axis=1)

        return self.tfidf.transform(joined_X)        

import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.compose import ColumnTransformer
dataset = pd.DataFrame({"a":["word gone wild","word gone with wind"],
                        "b":[" gone fhgf wild","gone with wind"],
                        "c":[1,2]})
tfidf = TfidfVectorizer(min_df=0)

clmn = ColumnTransformer([("tfidf", custom_tfidf(tfidf), ['a','b'])],remainder="passthrough")
clmn.fit_transform(dataset)

#
array([[0.36439074, 0.51853403, 0.72878149, 0.        , 0.        ,
        0.25926702, 1.        ],
       [0.        , 0.438501  , 0.        , 0.61629785, 0.61629785,
        0.2192505 , 2.        ]])

P.S。 :可能是您可能想为每列创建一个tfidf矢量化器,然后创建一个字典,键为列名,值作为拟合的矢量化器。该字典可用于相应列的转换