如何在 scikit-learn 管道中的 CountVectorizer 之前包含

我有一个DataFrame包含一列文本的熊猫,我想使用 scikit-learn对文本进行矢量化CountVectorizer。但是,文本包含缺失值,因此我想在矢量化之前估算一个常数值。


我最初的想法是创建一个PipelineofSimpleImputer和CountVectorizer:


import pandas as pd

import numpy as np

df = pd.DataFrame({'text':['abc def', 'abc ghi', np.nan]})


from sklearn.impute import SimpleImputer

imp = SimpleImputer(strategy='constant')


from sklearn.feature_extraction.text import CountVectorizer

vect = CountVectorizer()


from sklearn.pipeline import make_pipeline

pipe = make_pipeline(imp, vect)


pipe.fit_transform(df[['text']]).toarray()

但是,fit_transform错误是因为SimpleImputeroutputs a 2D array and CountVectorizerrequires 1D input。这是错误消息:


AttributeError: 'numpy.ndarray' object has no attribute 'lower'

问题:我如何修改它Pipeline才能使其正常工作?


注意:我知道我可以估算熊猫中的缺失值。但是,我想在 scikit-learn 中完成所有预处理,以便可以使用Pipeline.


杨__羊羊
浏览 174回答 3
3回答

一只斗牛犬

我发现的最佳解决方案是将自定义转换器插入到 中Pipeline,在将输出SimpleImputer从 2D 传递到 1D 之前将其重塑CountVectorizer。这是完整的代码:import pandas as pdimport numpy as npdf = pd.DataFrame({'text':['abc def', 'abc ghi', np.nan]})from sklearn.impute import SimpleImputerimp = SimpleImputer(strategy='constant')from sklearn.feature_extraction.text import CountVectorizervect = CountVectorizer()# CREATE TRANSFORMERfrom sklearn.preprocessing import FunctionTransformerone_dim = FunctionTransformer(np.reshape, kw_args={'newshape':-1})# INCLUDE TRANSFORMER IN PIPELINEfrom sklearn.pipeline import make_pipelinepipe = make_pipeline(imp, one_dim, vect)pipe.fit_transform(df[['text']]).toarray()GitHub上已经提出只要CountVectorizer第二个维度为1(意思是:单列数据)就应该允许2D输入。那个修改CountVectorizer将是这个问题的一个很好的解决方案!

慕尼黑的夜晚无繁华

一种解决方案是创建一个 SimpleImputer 类并覆盖其transform()方法:import pandas as pdimport numpy as npfrom sklearn.impute import SimpleImputerclass ModifiedSimpleImputer(SimpleImputer):    def transform(self, X):        return super().transform(X).flatten()df = pd.DataFrame({'text':['abc def', 'abc ghi', np.nan]})imp = ModifiedSimpleImputer(strategy='constant')from sklearn.feature_extraction.text import CountVectorizervect = CountVectorizer()from sklearn.pipeline import make_pipelinepipe = make_pipeline(imp, vect)pipe.fit_transform(df[['text']]).toarray()

手掌心

当我有一维数据时,我将这个一维包装器用于 sklearn Transformer。我认为,在您的情况下,此包装器可用于包装一维数据(具有字符串值的 pandas 系列)的 simpleImputer。class OneDWrapper:    """One dimensional wrapper for sklearn Transformers"""    def __init__(self, transformer):        self.transformer = transformer    def fit(self, X, y=None):        self.transformer.fit(np.array(X).reshape(-1, 1))        return self    def transform(self, X, y=None):        return self.transformer.transform(            np.array(X).reshape(-1, 1)).ravel()    def inverse_transform(self, X, y=None):        return self.transformer.inverse_transform(            np.expand_dims(X, axis=1)).ravel()现在,您不需要管道中的额外步骤。one_d_imputer = OneDWrapper(SimpleImputer(strategy='constant'))pipe = make_pipeline(one_d_imputer, vect)pipe.fit_transform(df['text']).toarray() # note we are feeding a pd.Series here!
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python