【问题标题】:use Featureunion in scikit-learn to combine two pandas columns for tfidf在 scikit-learn 中使用 Featureunion 为 tfidf 组合两个 pandas 列
【发布时间】:2016-04-15 02:20:41
【问题描述】:

在使用this 作为垃圾邮件分类模型的同时,我想添加主题加正文的附加功能。

我的所有功能都在 pandas 数据框中。例如,主题为 df['Subject'],正文为 df['body_text'],垃圾邮件/火腿标签为 df['ham/spam']

我收到以下错误: TypeError: 'FeatureUnion' 对象不可迭代

如何在通过管道函数运行 df['Subject'] 和 df['body_text'] 作为特征?

from sklearn.pipeline import FeatureUnion
features = df[['Subject', 'body_text']].values
combined_2 = FeatureUnion(list(features))

pipeline = Pipeline([
('count_vectorizer',  CountVectorizer(ngram_range=(1, 2))),
('tfidf_transformer',  TfidfTransformer()),
('classifier',  MultinomialNB())])

pipeline.fit(combined_2, df['ham/spam'])

k_fold = KFold(n=len(df), n_folds=6)
scores = []
confusion = numpy.array([[0, 0], [0, 0]])
for train_indices, test_indices in k_fold:
    train_text = combined_2.iloc[train_indices]
    train_y = df.iloc[test_indices]['ham/spam'].values

    test_text = combined_2.iloc[test_indices]
    test_y = df.iloc[test_indices]['ham/spam'].values

    pipeline.fit(train_text, train_y)
    predictions = pipeline.predict(test_text)
    prediction_prob = pipeline.predict_proba(test_text)

    confusion += confusion_matrix(test_y, predictions)
    score = f1_score(test_y, predictions, pos_label='spam')
    scores.append(score)

【问题讨论】:

    标签: pandas scikit-learn sklearn-pandas


    【解决方案1】:

    FeatureUnion 不应该以这种方式使用。相反,它需要两个特征提取器/矢量化器并将它们应用于输入。它不会按照显示的方式在构造函数中获取数据。

    CountVectorizer 需要一个字符串序列。提供它的最简单方法是将字符串连接在一起。这会将两列中的文本都传递给相同的CountVectorizer

    combined_2 = df['Subject'] + ' '  + df['body_text']
    

    另一种方法是在每列上单独运行 CountVectorizer 和可选的 TfidfTransformer,然后将结果堆叠起来。

    import scipy.sparse as sp
    
    subject_vectorizer = CountVectorizer(...)
    subject_vectors = subject_vectorizer.fit_transform(df['Subject'])
    
    body_vectorizer = CountVectorizer(...)
    body_vectors = body_vectorizer.fit_transform(df['body_text'])
    
    combined_2 = sp.hstack([subject_vectors, body_vectors], format='csr')
    

    第三种选择是实现您自己的转换器来提取数据框列。

    class DataFrameColumnExtracter(TransformerMixin):
    
        def __init__(self, column):
            self.column = column
    
        def fit(self, X, y=None):
            return self
    
        def transform(self, X, y=None):
            return X[self.column]
    

    在这种情况下,您可以在两个管道上使用 FeatureUnion,每个管道都包含您的自定义转换器,然后是 CountVectorizer

    subj_pipe = make_pipeline(
           DataFrameColumnExtracter('Subject'), 
           CountVectorizer()
    )
    
    body_pipe = make_pipeline(
           DataFrameColumnExtracter('body_text'), 
           CountVectorizer()
    )
    
    feature_union = make_union(subj_pipe, body_pipe)
    

    管道的此功能联合将采用数据帧,并且每个管道将处理其列。它将从给定的两列中生成术语计数矩阵的连接。

     sparse_matrix_of_counts = feature_union.fit_transform(df)
    

    此功能联合也可以作为更大管道中的第一步添加。

    【讨论】:

    • 我觉得这也是一个很好的参考。 FeatureUnion
    • 正是我一直在寻找的。我想知道这是否应该是 sklearn 开箱即用的一部分。
    • @David 我已经尝试了你的第三个选项,但它返回一个“ValueError: Expected 2D array, got 1D array instead”
    猜你喜欢
    • 2019-01-12
    • 2016-02-01
    • 2016-04-08
    • 2015-01-31
    • 2014-11-05
    • 2013-10-30
    • 2020-11-05
    • 2017-06-12
    相关资源
    最近更新 更多