RTextTools是一个关于文本分类的工具包,汇集了9种算法:
- BAGGING(ipred:bagging):bagging集成分类
- BOOSTING (caTools:LogitBoost):Logit Boosting 集成分类
- GLMNET(glmnet:glmnet):基于最大似然的广义线性回归
- MAXENT(maxent:maxent):最大熵模型
- NNET(nnet:nnet) :神经网络
- RF(randomForest:randomForest):随机森林
- SLDA(ipred:slda):scaled 线性判别分析
- SVM(e1071:svm) :支持向量机
- TREE (tree:tree):递归分类树
RTextTools提供非常简单的接口和清晰的流程使用这些算法创建一个文本分类模型。下面使用电视剧《龙门镖局》在豆瓣上的324篇长篇影评数据为例,介绍RTextTools的使用方法。使用Rdouban可以非常方便的获取到豆瓣影评数据,使用Rwordseg分词,分类标签为用户评分。324篇影评中,一星11篇,二星 27篇,三星 97篇,四星123篇,五星 66篇,豆瓣综合评分7.4(截止2013-09-09)。本文主要参考
RTextTools作者的《RTextTools: A Supervised Learning Package for Text Classification》一文。
1. 创建文档-词项矩阵
影评数据名称为
longmen,移除所有的数字和字母,其中一篇影评为英文,被移除,仅处理323篇中文评论。其中用于生成
TermDocumentMatrix的列为
longmen$word,是影评分词后的词汇集合,可以用create_matrix函数生成TermDocumentMatrix,但是此函数对中文处理可能产生乱码,所有可以换一种处理方式:01 longmen<-longmen[nchar(longmen$word)>0,]
02 myReader <- readTabular(mapping =list(Content = "word"))03 corpus <- Corpus(DataframeSource(longmen),04 readerControl = list(reader = myReader,05 language = "zh_cn"))06 mat<-TermDocumentMatrix(corpus, control =list(wordLengths=c(2,Inf)))07 mat<-weightTfIdf(mat,normalize = TRUE)08 mat<-t(removeSparseTerms(mat, sparse=0.99))09 10 # mat2<- create_matrix(longmen$word,removeNumbers=TRUE, stemWords=FALSE, 11 # weighting=weightTfIdf,removeSparseTerms=.99)
为了降低后面的计算量和内存开销,removeSparseTerms设置为0.99(不一定好),保留词汇2660个,实际上有词汇13428个,得到的数据是归一化后的TF-IDF矩阵。
2. 创建容器(Container) 使用函数create_container创建一个container,分类标签是评分longmen$rating,前250(约77.4%)行为训练集,剩余的为测试集。
1 container <- create_container(mat,longmen$rating,trainSize=1:250,
2 testSize=251:323, virgin=FALSE)
3. 训练模型
使用train_model函数对container进行训练,选择其中7种算法,另外两种太吃内存了,破电脑受不了。train_models函数可以一次性选择所有的算法。
1 SVM <- train_model(container,"SVM")
2 GLMNET <- train_model(container,"GLMNET")
3 MAXENT <- train_model(container,"MAXENT")
4 # SLDA <- train_model(container,"SLDA")
5 # BAGGING <- train_model(container,"BAGGING")
6 BOOSTING <- train_model(container,"BOOSTING")
7 RF <- train_model(container,"RF")
8 NNET <- train_model(container,"NNET")
9 TREE <- train_model(container,"TREE")
4. 分类
对测试集进行分类预测。
1 SVM_CLASSIFY <- classify_model(container, SVM)
2 GLMNET_CLASSIFY <- classify_model(container, GLMNET)
3 MAXENT_CLASSIFY <- classify_model(container, MAXENT)
4 # SLDA_CLASSIFY <- classify_model(container,SLDA)
5 # BAGGING_CLASSIFY <- classify_model(container, BAGGING)
6 BOOSTING_CLASSIFY <- classify_model(container, BOOSTING)
7 RF_CLASSIFY <- classify_model(container, RF)
8 NNET_CLASSIFY <- classify_model(container,NNET)
9 TREE_CLASSIFY <- classify_model(container, TREE)
5. 分析 结果解析是机器学习过程非常重要的一步。函数create_analytics帮助我们理解测试集的分类结果,使用summary函数返回四个结果:类标签(label_summary)、算法摘要(algorithm_summary)、文档摘要(document_summary)、集成摘要(ensemble_summary)。算法摘要给出了四个评估指标:
精确度(precision),召回率(recall), 准确率(accuracy),
F-scores 。(不知prercision和accuracy的确切翻译,谁是精确度、准确率有不同的翻译)- accuracy = 正确识别的个体总数 / 识别出的个体总数:反映了分类器统对整个样本的判定能力——能将正的判定为正,负的判定为负 ;
- precision=正确识别的个体总数/测试集中存在的个体总数:反映了被分类器判定的正例中真正的正例样本的比重;
- recall = 正确识别的个体总数 / 测试集中存在的个体总数:反映了被正确判定的正例占总的正例的比重;
- F值 = precision * recall * 2 / ( precision +recall ):F1-Measure,综合了precision 和recall,平衡二者之间的矛盾,当F1值较高时结果比较理想。
注意;输出的结果出现NaN时,说明数据集太小,无法给出确定的估计,本文使用的数据集太小,结果很差。
- NUM_MANUALLY_CODED:每类包含文档的数量
- NUM_CONSENSUS_CODED:the number that were coded using the ensemble method ,
- NUM_PROBABILITY_CODED:the number that were coded using the probability method
- PCT_CONSENSUS_CODED and PCT_PROBABILITY_CODED:the rate of over- or under-coding with each method
- PCT_CORRECTLY_CODED_CONSENSUS and PCT_CORRECTLY_CODED_PROBABILITY: the percentage that were correctly coded using either the ensemble method or the probability method
文档摘要给出了每一个算法对每一个文档的分类标签和对应的概率值(doc_summary)。
01 analytics<-create_analytics(container,
02 cbind(SVM_CLASSIFY, BOOSTING_CLASSIFY,
03 RF_CLASSIFY, GLMNET_CLASSIFY,
04 NNET_CLASSIFY, TREE_CLASSIFY,
05 MAXENT_CLASSIFY))
06 summary(analytics)
07 topic_summary <- analytics@label_summary
08 alg_summary <- analytics@algorithm_summary
09 ens_summary <-analytics@ensemble_summary
10 doc_summary <- analytics@document_summary
11 create_ensembleSummary(analytics@document_summary)
6. 集成分类一致性(Ensemble Agreement)
使用集成分类的方法可以提高分类的准确性,通常采用投票的原则,即每一种算法做一次分类,如果多个算法都得到相同的分类结果,就认为这种结果更为可信,也就是少数服从多数的原则。文本分类采用至少四种分类算法的集成,能够达到不错的效果。函数create_ensembleSummary产生的结果和上述的集成摘要结果相同,返回集成分类的召回率和覆盖度(coverage)。覆盖度可以理解为满足召回率阈值的文档百分比。覆盖度随着召回率的增大而减小,通常90%的召回率是比较由于价值的结果,如果在不少于4种算法和不太低的覆盖度(个人认为>60%)情况下,这种结果是相当令人满意的。本文的数据集的结果如下,召回率都不令人满意。
| n-ENSEMBLE COVERAGE | n-ENSEMBLE RECALL |
---|
n > = 1 | 1.00 | 0.29 |
n > = 2 | 1.00 | 0.29 |
n > = 3 | 1.00 | 0.29 |
n > = 4 | 0.84 | 0.33 |
n > = 5 | 0.59 | 0.35 |
n > = 6 | 0.25 | 0.33 |
n > = 7 | 0.10 | 0.29 |
7. 交叉验证(Cross Validation)
可以使用N-折交叉验证评估算法的准确性(Accuracy)和稳定性,以决定哪些算法可以参与到集成算法中。N-折交叉验证,初始采样分割成N个子样本,一个单独的子样本被保留作为验证模型的数据,其他N-1个样本用来训练。交叉验证重复N次,每个子样本验证一次,平均N次的结果或者使用其它结合方式,最终得到一个单一估测。这个方法的优势在于,同时重复运用随机产生的子样本进行训练和验证,每次的结果验证一次,10折交叉验证是最常用的。函数cross_validate()可以完成此项操作。其中比较靠近 1 的数字表示在预测方面具有较高的可信度,比较靠近 0
的数字则表示预测的可信度较低。本文采用的数据集样本数实在太少,选择N=3。
01 N=3
02 cross_SVM <- cross_validate(container,N,"SVM")
03 cross_GLMNET <- cross_validate(container,N,"GLMNET")
04 cross_MAXENT <- cross_validate(container,N,"MAXENT")
05 # cross_SLDA <- cross_validate(container,N,"SLDA")
06 # cross_BAGGING <- cross_validate(container,N,"BAGGING")
07 cross_BOOSTING <- cross_validate(container,N,"BOOSTING")
08 cross_RF <- cross_validate(container,N,"RF")
09 cross_NNET <- cross_validate(container,N,"NNET")
10 cross_TREE <- cross_validate(container,N,"TREE")
其中最好的两个模型是MAXENT(0.85)和 GLMNET(0.65).
文本分类(实际上文本挖掘都是如此)是非常消耗计算资源的应用,对于小数据根本没有意义,尤其对BAGGING、BOOSTING等这类超级复杂度算法,小内存根本无法计算。代码和数据在这里。