如何对文档进行分类

如果我们要对文档进行分类,有两个重要的阶段:

  1. 基于分词的数据准备,包括分词、单词权重计算、去掉停用词;
  2. 应用朴素贝叶斯分类进行分类,首先通过训练集得到朴素贝叶斯分类器,然后将分类器应用于测试集,并与实际结果做对比,最终得到测试集的分类准确率。

下面,我分别对这些模块进行介绍。

模块1:对文档进行分词

在准备阶段里,最重要的就是分词。那么如果给文档进行分词呢?英文文档和中文文档所使用的分词工具不同。

在英文文档中,最常用的是NTLK包。NTLK包中包含了英文的停用词stop words、分词和标注方法。

1
2
3
import nltk
word_list = nltk.word_tokenize(text) #分词
nltk.pos_tag(word_list) #标注单词的词性

在中文文档中,最常用的是jieba包。jieba包中包含了中文的停用词stop words和分词方法。

1
2
import jieba
word_list = jieba.cut (text) #中文分词

模块2:加载停用词表

我们需要自己读取停用词表文件,从网上可以找到中文常用的停用词保存在stop_words.txt,然后利用Python的文件读取函数读取文件,保存在stop_words数组中。

1
stop_words = [line.strip().decode('utf-8') for line in io.open('stop_words.txt').readlines()]

模块3:计算单词的权重

这里我们用到sklearn里的TfidfVectorizer类,上面我们介绍过它使用的方法。

直接创建TfidfVectorizer类,然后使用fit_transform方法进行拟合,得到TF-IDF特征空间features,你可以理解为选出来的分词就是特征。我们计算这些特征在文档上的特征向量,得到特征空间features。

1
2
tf = TfidfVectorizer(stop_words=stop_words, max_df=0.5)
features = tf.fit_transform(train_contents)

这里max_df参数用来描述单词在文档中的最高出现率。假设max_df=0.5,代表一个单词在50%的文档中都出现过了,那么它只携带了非常少的信息,因此就不作为分词统计。

一般很少设置min_df,因为min_df通常都会很小。

模块4:生成朴素贝叶斯分类器

我们将特征训练集的特征空间train_features,以及训练集对应的分类train_labels传递给贝叶斯分类器clf,它会自动生成一个符合特征空间和对应分类的分类器。

这里我们采用的是多项式贝叶斯分类器,其中alpha为平滑参数。为什么要使用平滑呢?因为如果一个单词在训练样本中没有出现,这个单词的概率就会被计算为0。但训练集样本只是整体的抽样情况,我们不能因为一个事件没有观察到,就认为整个事件的概率为0。为了解决这个问题,我们需要做平滑处理。

当alpha=1时,使用的是Laplace平滑。Laplace平滑就是采用加1的方式,来统计没有出现过的单词的概率。这样当训练样本很大的时候,加1得到的概率变化可以忽略不计,也同时避免了零概率的问题。

当0<alpha<1时,使用的是Lidstone平滑。对于Lidstone平滑来说,alpha 越小,迭代次数越多,精度越高。我们可以设置alpha为0.001。

1
2
3
# 多项式贝叶斯分类器
from sklearn.naive_bayes import MultinomialNB
clf = MultinomialNB(alpha=0.001).fit(train_features, train_labels)

模块5:使用生成的分类器做预测

首先我们需要得到测试集的特征矩阵。

方法是用训练集的分词创建一个TfidfVectorizer类,使用同样的stop_words和max_df,然后用这个TfidfVectorizer类对测试集的内容进行fit_transform拟合,得到测试集的特征矩阵test_features

1
2
test_tf = TfidfVectorizer(stop_words=stop_words, max_df=0.5, vocabulary=train_vocabulary)
test_features=test_tf.fit_transform(test_contents)

然后我们用训练好的分类器对新数据做预测。

方法是使用predict函数,传入测试集的特征矩阵test_features,得到分类结果predicted_labels。predict函数做的工作就是求解所有后验概率并找出最大的那个。

1
predicted_labels=clf.predict(test_features)

模块6:计算准确率

计算准确率实际上是对分类模型的评估。我们可以调用sklearn中的metrics包,在metrics中提供了accuracy_score函数,方便我们对实际结果和预测的结果做对比,给出模型的准确率。

使用方法如下:

1
2
from sklearn import metrics
print metrics.accuracy_score(test_labels, predicted_labels)

数据挖掘神器sklearn

从数据挖掘的流程来看,一般包括了获取数据、数据清洗、模型训练、模型评估和模型部署这几个过程。

sklearn中包含了大量的数据挖掘算法,比如三种朴素贝叶斯算法,我们只需要了解不同算法的适用条件,以及创建时所需的参数,就可以用模型帮我们进行训练。在模型评估中,sklearn提供了metrics包,帮我们对预测结果与实际结果进行评估。

在文档分类的项目中,我们针对文档的特点,给出了基于分词的准备流程。一般来说NTLK包适用于英文文档,而jieba适用于中文文档。我们可以根据文档选择不同的包,对文档提取分词。这些分词就是贝叶斯分类中最重要的特征属性。基于这些分词,我们得到分词的权重,即特征矩阵。

通过特征矩阵与分类结果,我们就可以创建出朴素贝叶斯分类器,然后用分类器进行预测,最后预测结果与实际结果做对比即可以得到分类器在测试集上的准确率。