SkLearn:具有字典和文本数据的特征联盟

SkLearn: Feature Union with a dictionary and text data

我有一个像这样的 DataFrame:

     text_data                worker_dicts                  outcomes

0    "Some string"           {"Sector":"Finance",             0
                              "State: NJ"}                   
1    "Another string"        {"Sector":"Programming",         1
                              "State: NY"}                             

它既有文本信息,又有一列是字典。 (真正的 worker_dicts 有更多的字段)。我对二进制结果列感兴趣。

我最初尝试做的是合并 text_dataworker_dict,粗略地连接两列,然后 运行 多项式 NB:

    df['stacked_features']=df['text_data'].astype(str)+'_'+df['worker_dicts']
    stacked_features = np.array(df['stacked_features'])
    outcomes = np.array(df['outcomes'])
    text_clf = Pipeline([('vect', TfidfVectorizer(stop_words='english'), ngram_range = (1,3)), 
   ('clf', MultinomialNB())])
    text_clf = text_clf.fit(stacked_features, outcomes)

但我的准确性非常差,而且我认为拟合两个独立模型比在两种类型的特征上拟合一个模型(就像我对堆叠所做的那样)会更好地利用数据。

我将如何使用 Feature Union? worker_dicts 有点奇怪,因为它是一本字典,所以我对如何解析它感到很困惑。

如果你的字典条目是分类的,就像它们在你的示例中那样,那么我会在进行额外处理之前从字典条目创建不同的列。

new_features = pd.DataFrame(df['worker_dicts'].values.tolist())

然后 new_features 将是它自己的数据框,包含 SectorState 列,除了 TFIDF 或其他特征提取之外,您还可以根据需要对这些进行热编码 text_data 列。为了在管道中使用它,您需要创建一个新的转换器 class,所以我可能建议分别应用字典解析和 TFIDF,然后堆叠结果,并添加 OneHotEncoding to your pipeline as that allows you to specify columns to apply the transformer to. (As the categories you want to encode are strings you may want to use LabelBinarizer class 而不是 OneHotEncoder class 进行编码转换。)

如果您只想通过管道对所有列单独使用 TFIDF,则需要使用嵌套管道和 FeatureUnion 设置来提取列,如 所述。

如果您在数据帧 X1 和 X2 中有一个热编码特征,如下所述,并且在 X3 中有文本特征,您可以执行如下操作来创建管道。 (还有很多其他的选择,这只是一种方式)

X = pd.concat([X1, X2, X3], axis=1)

def select_text_data(X):
    return X['text_data']

def select_remaining_data(X):
    return X.drop('text_data', axis=1)


# pipeline to get all tfidf and word count for first column
text_pipeline = Pipeline([
    ('column_selection', FunctionTransformer(select_text_data, validate=False)),
    ('tfidf', TfidfVectorizer())
])


final_pipeline = Pipeline([('feature-union', FeatureUnion([('text-features', text_pipeline), 
                               ('other-features', FunctionTransformer(select_remaining_data))
                              ])),
                          ('clf', LogisticRegression())
                          ])

(MultinomialNB 不会在管道中工作,因为它没有 fitfit_transform 方法)