带有 TfidfVectorizer 的列转换器产生"empty vocabulary"错误



我正在使用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>

这样的原因可能是什么原因以及如何纠正?

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

应使用标量字符串或int在变压器期望x为1D数组(向量)的地方,否则将传递给变压器2D数组。

现在, TfidfVectorizer需要一个单元的迭代器进行输入(因此是1-d的字符串阵列)。但是,由于您在ColumnTransformer中发送了列名的列表(即使该列表仅包含一个列),它将是将传递给TfidfVectorizer的2-D数组。因此错误。

将其更改为:

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

为了获得更多的理解,请尝试使用上述内容从PANDAS数据框架中选择数据。当您执行时,检查返回数据的格式(dtype,形状):

dataset['a']
vs 
dataset[['a']]

update :@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")

我们可以创建一个自定义的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 vectorizer,然后创建一个用键为列名和值作为拟合vectorizer的字典。该词典可以在相应列的转换过程中使用

最新更新