下面是设计分类器,用训练集训练,用测试集测试。在做这些工作之前,一定要记住,首先要把测试数据也映射到上面这个TF-IDF词向量空间中,也就是说,测试集和训练集处在同一个词向量空间(vocabulary相同),只不过测试集有自己的tdm,与训练集(train_word_bag/tfdifspace.dat)中的tdm不同而已。
最常见的文本分类方法有KNN最邻近算法、朴素贝叶斯算法和支持向量机算法。一般而言,KNN最邻近算法的原理最简单,分类精度尚可,但是速度最慢;朴素贝叶斯算法对于短文本分类的效果最好,精度很高;支持向量机算法的优势是支持线性不可分的情况,精度上取中。
本文选用Scikit-Learn的朴素贝叶斯算法进行文本分类,测试集随机抽取自训练集中的文档集合,每个分类取10个文档,过滤掉1KB以下的文档。分类器有封装好了的函数,MultinomialNB,获取训练集的权重矩阵和标签,进行训练,然后获取测试集的权重矩阵,进行预测(给出预测标签)。
训练步骤与训练集相同,首先是分词,之后生成文件词向量文件,直至生成词向量模型。不同的是,在训练词向量模型时,需要加载训练集词袋,将测试集产生的词向量映射到训练集词袋的词典中,生成向量空间模型。
首先,把测试数据也映射到TF-IDF词向量空间上:
import sys
import os
from sklearn.datasets.base import Bunch #引入Bunch类
import cPickle as pickle #引入持久化类
from sklearn import feature_extraction
from sklearn.feature_extraction.text import TfidfTransformer #向量转换类
from sklearn.feature_extraction.text import TfidfVectorizer #向量生成类
#配置UTF-8输出环境
reload(sys)
sys.setdefaultencoding('utf-8')
#读取Bunch对象
def readbunchobj(path):
file_obj=open(path,"rb")
bunch=pickle.load(file_obj)
file_obj.close()
return bunch
#写入Bunch对象
def writebunchobj(path,bunchobj):
file_obj=open(path,"wb")
pickle.dump(bunchobj,file_obj)
file_obj.close()
#读取文件
#1读取停用词表
stopword_path="train_word_bag/hlt_stop_words.txt"#停用词表的路径
stpwrdlst=readfile(stopword_path).splitlines()
#2导入分词后的词向量Bunch对象
path="test_word_bag/test_set.dat" #词向量空间保存路径
bunch=readbunchobj(path)
#3构建测试集TF-IDF词向量空间对象
testspace=Bunch(target_name=bunch.target_name,label=bunch.label,filenames=bunch.filenames,tdm=[],vocabulary={})
#导入训练集的词袋
trainbunch=readbunchobj("train_word_bag/tfdifspace.dat")
#使用Tfidfvectorizer初始化向量空间模型
vectorizer=TfidfVectorizer(stop_words=stpwrdlst,sublinear_tf=True,max_df=0.5,vocabulary=trainbunch.vocabulary) #使用训练集词袋向量
transformer=TfidfTransformer()
#文本转换为词频矩阵,单独保存字典文件
testspace.tdm=vectorizer.fit_transform(bunch.contents)
testspace.vocabulary=trainbunch.vocabulary
#创建词袋的持久化
space_path="test_word_bag/testspace.dat" #词向量词袋保存路径
writebunchobj(space_path,testspace)
测试集进行了上述处理后,接下来执行多项式贝叶斯算法进行测试文本分类,并返回分类精度。
#导入多项式贝叶斯算法包
import sys
import cPickle as pickle
from sklearn.naive_bayes import MultinomialNB
reload(sys)
sys.setdefaultencoding('utf-8')
def readbunchobj(path):
file_obj=open(path,"rb")
bunch=pickle.load(file_obj)
file_obj.close()
return bunch
#导入训练集向量空间
trainpath="train_word_bag/tfdifspace.dat"
train_set=readbunchobj(trainpath)
#导入测试集向量空间
testpath="test_word_bag/testspace.dat"
test_set=readbunchobj(testpath)
#应用朴素贝叶斯算法。训练分类器:输入词袋向量和分类标签
#alpha:0.001,越小,迭代次数越多,精度越高
clf = MultinomialNB(alpha=0.001).fit(train_set.tdm, train_set.label)
#预测分类结果
predicted = clf.predict(test_set.tdm)
total=len(predicted);rate=0
for flabel,file_name,expct_cate in zip(test_set.label,test_set.filenames,predicted):
if flabel != expct_cate:
rate+=1
print file_name,": 实际类别:",flabel," -->预测类别:",expct_cate
print "error rate:",float(rate)*100/float(total),"%"