文字分类器,包含单词和sklearn中的附加情感功能

时间:2016-02-07 14:11:42

标签: python scikit-learn text-classification

我正在尝试构建一个分类器,除了词语之外还使用了诸如情感或主题(LDA结果)之类的功能。我有一个带有文本和标签的pandas DataFrame,并希望添加一个情绪值(数字在-5和5之间)和LDA分析的结果(带有句子主题的字符串)。

我有一个单词分类器的工作包,它使用sklearn中的CountVectorizer并使用MultinomialNaiveBayes执行分类。

df = pd.DataFrame.from_records(data=data, columns=names)
train, test = train_test_split(
    df,
    train_size=train_ratio,
    random_state=1337
)
train_df = pd.DataFrame(train, columns=names)
test_df = pd.DataFrame(test, columns=names)
vectorizer = CountVectorizer()
train_matrix = vectorizer.fit_transform(train_df['text'])
test_matrix = vectorizer.transform(test_df['text'])
positive_cases_train = (train_df['label'] == 'decision')
positive_cases_test = (test_df['label'] == 'decision')
classifier = MultinomialNB()
classifier.fit(train_matrix, positive_cases_train)

现在的问题是。除了单词技巧外,我怎样才能将其他功能介绍给我的分类器?

提前致谢,如果您需要更多信息,我很乐意提供这些信息。

编辑:添加@Guiem建议的行后,有关新功能重量的新问题。此编辑添加了这个新问题:

我的火车矩阵的形状是(2554, 5286)。但奇怪的是,这个形状是否添加了情感列(也许没有正确添加行?)

如果我打印Matrix,我会得到以下输出:

  (0, 322)  0.0917594575712
  (0, 544)  0.196910480455
  (0, 556)  0.235630958238
  (0, 706)  0.137241420774
  (0, 1080) 0.211125349374
  (0, 1404) 0.216326271935
  (0, 1412) 0.191757369869
  (0, 2175) 0.128800602511
  (0, 2176) 0.271268708356
  (0, 2371) 0.123979845513
  (0, 2523) 0.406583720526
  (0, 3328) 0.278476810585
  (0, 3752) 0.203741786877
  (0, 3847) 0.301505063552
  (0, 4098) 0.213653538407
  (0, 4664) 0.0753937554096
  (0, 4676) 0.164498844366
  (0, 4738) 0.0844966331512
  (0, 4814) 0.251572721805
  (0, 5013) 0.201686066537
  (0, 5128) 0.21174469759
  (0, 5135) 0.187485844479
  (1, 291)  0.227264696182
  (1, 322)  0.0718526940442
  (1, 398)  0.118905396285
  : :
  (2553, 3165)  0.0985290985889
  (2553, 3172)  0.134514497354
  (2553, 3217)  0.0716087169489
  (2553, 3241)  0.172404983302
  (2553, 3342)  0.145912701013
  (2553, 3498)  0.149172538211
  (2553, 3772)  0.140598133976
  (2553, 4308)  0.0704700896603
  (2553, 4323)  0.0800039075449
  (2553, 4505)  0.163830579067
  (2553, 4663)  0.0513678549359
  (2553, 4664)  0.0681930862174
  (2553, 4738)  0.114639856277
  (2553, 4855)  0.140598133976
  (2553, 4942)  0.138370066422
  (2553, 4967)  0.143088901589
  (2553, 5001)  0.185244190321
  (2553, 5008)  0.0876615764151
  (2553, 5010)  0.108531807984
  (2553, 5053)  0.136354534152
  (2553, 5104)  0.0928665728295
  (2553, 5148)  0.171292088292
  (2553, 5152)  0.172404983302
  (2553, 5191)  0.104762377866
  (2553, 5265)  0.123712025565

我希望这有点帮助,或者你想要一些其他信息吗?

2 个答案:

答案 0 :(得分:3)

一种选择是将这两个新功能添加到您的CountVectorizer矩阵中

由于您没有执行任何tf-idf,您的计数矩阵将填充整数,因此您可以将新列编码为int值。

您可能需要尝试多种编码,但您可以从以下内容开始:

  • 情感[-5,...,5]转换为[0,...,10]
  • 句子主题的字符串。只需将整数分配给不同的主题({'unicorns':0, 'batman':1, ...}),您可以保留字典结构以指定整数并避免重复主题。

以防万一你不知道如何在train_matrix中添加列:

dense_matrix = train_matrix.todense() # countvectorizer returns a sparse matrix
np.insert(dense_matrix,dense_matrix.shape[1],[val1,...,valN],axis=1)

请注意,列[val1,...,valN]需要与num具有相同的长度。你正在使用的样品

即使它不再是一个严格的词袋(因为并非所有列都代表词频),只需添加这两列就会添加您想要包含的额外信息。朴素的贝叶斯分类器认为每个特征都独立于概率,所以我们在这里没问题。

  

更新:最好使用一个热门的'编码器编码分类功能(http://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.OneHotEncoder.html)。通过这种方式,您可以通过为新特征分配整数值来防止奇怪的行为(也许您仍然可以通过情绪来做到这一点,因为在0到10的情绪范围内,您认为9情绪更接近具有情绪10的样本而不是另一个情绪0)。但是使用分类功能,您最好使用单热编码。   所以,让我们说你有3个主题,然后你可以使用相同的添加列的技术只有现在你必须添加3而不是一个[topic1,topic2,topic3]。这样,如果您有一个属于topic1的样本,您将其编码为[1,0,0],如果该主题为3,则您的表示为[0,0,1](您标记为1对应于主题的列)

答案 1 :(得分:0)

一种比较简单的方法是使用scikit-learn的FeatureUnion并将文本嵌入基本上串联到表格数据嵌入中。

查看其他两个SO问题的答案:

然后,您将FeatureUnion的输出作为管道的一部分传递到分类器中。