基于Redis实现一个朴素贝叶斯文本分类器

基于朴素贝叶斯进行文本分类因为实现简单被广泛应用,很多开源的机器学习框架都提供了相应的实现。使用场景如新闻类内容的分类,垃圾信息识别等等。

原理

贝叶斯的定义就不具体说了,概率统计都有讲,如果没学过也没关系,去wikipedia上看看。非常朴素,值得一看。

分类器最重要的是先要有“分类”,而且分类之间应该是相对来说重合度比较低的,或者说是正交的。然后对每个分类进行词的统计,然后就会生成一个关键词序列,或者叫模型。有点像这个分类的DNA序列一样,即可以理解为这个分类在用词维度上的特征(特征向量)。然后就是将目标内容基于这一系列的“DNA”序列进行计算likelihood,值最大的那个就是了。

实践

具体的实现我就不上代码了。主要几步:

0. 抽样

从对应的分类中获取足够多的样本,并且要避免有脏样本,否则生成的分类器会不准确。

1. 分词

这个很容易理解,因为是要用到词,中文就一定会用到分词工具。Java里有paoding, PHP里有Jieba,甚至新浪SAE的分词服务…这方面有很多开源的解决方案。

2. 统计、生成DNA(模型)

针对每个分类的样本集合,统计每个关键词的出现频率。最终得到一个“词-次数”的Map。这里就用到Redis了,其实不一定要用Redis,用Redis主要是考虑到后续的模型自动反馈改进。如果只是不怕麻烦而手动生成的话,这里保存模型到哪里其实无所谓。

3. 权重设置

针对每个词在所在分类里出现的频率来设置一个后续计算的权重。最简单是:这个词在所有词中的出现概率(该词的出现次数 / 所在分类中样本的总词数)。用Redis的SortedSet来保存。

4. 使用

对于一个目标样本,分词,然后针对每个分类计算相应的权重值和。

5. 模型自动化反馈

这个还是比较重要的思路,因为模型也是会变动的,你的分类可能也在不断进化,比如法制新闻的内容可能随着法制热点或者法治进程的变化,产生不同的特征(这个例子有点YY了)。所以模型的产生应该随着新的样本不断地变化,所以生成模型的过程应该是保持一定的频率进行,同时,每次的使用模型进行分类的目标样本如果区分度较高,也可以直接加入到模型里进行计算。

 

优化

避免overfit – 模型并不容易达到足够高的准确率,准确率过高的原因可能是因为分类区分度很高,也许根本就不需要用分类器类做这件事,而准确率过低有可能是你的抽样有问题,或者你的分类有很大的重叠,比如生活和社会这种。所以如果是目标样本非常fit某个分类,建议就不要放到新的抽样样本里,因为不会产生新的“基因”了,如果这种样本过多,最终就容易overfit。

数量取胜 – 也是很朴素的想法,一个分类器不行,那么十个、二十个呢?如果能够把整个抽样提取、模型生成、模型反馈机制都自动化了,那么用多个分类器进行交叉验证,或者是来个投票机制。准确率应该也可以有很好的提升。