最近看完了 Willi Richert的《机器学习系统设计》。书虽然有点薄但也比较全,内容感觉有点偏文本处理,里面介绍了一些文本处理的方法和工具。综合起来看作为机器学习入门还是挺不错的,这里就简单记一下我做的笔记,方便回顾。书中的代码可以通过它说到的网站下载,这里是第5部分笔记。

第六章 贝叶斯分类器

情感分析问题其实还是很有意思的,对于一篇文档,一个微博或者一个推文,分析他的情绪有时候也叫做观点挖掘(optinion mining)。这是一个非常活跃的研究领域,而且一些公司对于这方面也非常感兴趣。这里使用的数据是来自Niek Sanders的语料库 http://www.sananalytics.com/lab/twitter-sentiment/ 数据中包含4种情感标签: Positive, Neutral, Negative, Irrelevant。

贝叶斯分类器

贝叶斯分类器的学习和预测的速度都很快,存储需求少,当所有特征相互独立时,效果是所有机器学习方法中最好的。但实际情况中往往不能满足特征的相互独立,但贝叶斯分类器的效果依旧非常好,因此很值得学习学习。

什么是贝叶斯定理

条件概率:指在事件B发生的情况下,事件A发生的概率,记为P(A|B)

贝叶斯定理的内容: $P(A|B) = P(A)\cdot\dfrac{P(B|A)}{P(B)}$

我们把P(A)称为“先验概率(Prior probability)”,即在事件B发生前,我们对A事件发生概率的一个判断。P(A|B)称为“后验概率(Posterior probability)”,即在B事件发生后,我们对A事件概率的重新评估。P(B|A)称为“可能性函数(likelyhood)”这是一个调整银子,使得预估概率更接近真实概率,P(B)称为“证据(evidence)”(有的地方也把$\dfrac{P(B|A)}{P(B)}$称为“可能性函数(likelyhood),这里可能是因为书上后面把P(B)直接舍掉有关”)。

朴素贝叶斯分类器

贝叶斯分类器就是建立在贝叶斯定理的基础上,朴素贝叶斯的核心功能是跟踪哪个特征在哪个类别中出现。设$C$为属于某一个类别,$F_1$,$F_2$是某样本的两个特征,因此贝叶斯定理就可以变为下式:

$$P(F_1,F_2)\cdot P(C|F_1, F_2) = P(C) \cdot P(F_1, F_2|C)$$

我们可以用其他概率来表达$P(C|F_1, F_2)$,这个概率的意义就是在已知$F_1$,$F_2$的情况下样本属于某类别C的概率:

$$P(C|F_1, F_2) = \dfrac{P(C)\cdot P(F_1, F_2|C)}{P(F_1, F_2)}$$

在这个公式里面,$P(F_1,F_2|C)$表示如果知道样本的类别C,那么有多大的可能性可以看到特征值$F_1$,$F_2$,计算这个值需要依靠朴素的性质。

朴素

在概率论中,我们还知道以下关系:

$$P(F_1,F_2|C) = P(F_1|C)\cdot P(F_2|C,F_1)$$

然而这个式子本身并没有什么帮助,但我们如果假设$F_1$和$F_2$之间相互独立,那么就可以把$P(F_2|C,F_1)$简化成$P(F_2|C)$,即变成如下式子:

$$P(F_1,F_2|C) = P(F_1|C)\cdot P(F_2|C)$$

我们就可以最终得到一个比较容易处理的式子:

$$P(C|F_1, F_2) = \dfrac{P(C)\cdot P(F_1|C)\cdot P(F_2|C)}{P(F_1, F_2)}$$

使用这个式子来处理问题就变得容易多了。这个式子中$P(C)$是C这类占所有类型的比例,$P(F_1|C)$指在C类中$F_1$发生的概率,$P(F_2|C)$指C类中$F_2$发生的概率,$P(F_1,F_2)$是这个特征在所有样本中占的比例。

对于一个文档来说,他的样本特征是一样的,也就是把他判定为是哪一类时,所有的计算公式中都会有$P(F_1,F_2)$,因此这一项完全可以舍掉而不影响分类的结果。对于上式,很多实际情景就算不满足特征相互独立的条件,我们依旧使用上面的式子进行替换,理论上并不正确,但实际中效果可能也不会太差。

使用sklearn的贝叶斯分类器

对于实际情况,有可能出现有些特征组合是我们事先没有见过的,这就会导致一些严重问题(如求解时遇到除以0的问题)。为了解决这个问题,我们可以对所有的计数都加1,这叫做“加1平滑”或者叫做拉普拉斯平滑,如果通过调整一个大于0的参数alpha来平滑,就叫做Lidston平滑。

在sklearn中,已经实现了朴素贝叶斯分类器,他有三种不同的种类:

  1. GaussianNB 它假设特征是正太分布的,它的一个使用场景是,根据给定人物的高度和宽度,判定这个人的性别。
  2. MultinomialNB 它假设特征就是出现次数。这和我们是相关的,因为我们会把推文中的词频当作特征,在实践中,这个分类器对TF-IDF向量处理的也不错
  3. BernoulliNB 它和MultinomialNB类似,但更适合于判断词语是否出现了这种二值特征,而不是词频统计。

由于没有太多的数据,这里使用交叉验证。但并不打算使用KFold,因为他会把数据切分成连续的几折。我们使用ShuffleSplit,他会讲数据打散,但并不能保证相同的数据样本不会出现在多个数据折中。

参数调优的一些方法

在机器学习中,很多的方法都有很多参数需要设置,这种工作很有必要,但确实太耗精力,因此Scikit-learn中有一个专门的类处理参数搜素问题,叫做GridSearchCV。它使用一个估算器(一个接口跟分类器一样的实例)和一个包含所有可能值的参数字典。参数字典需要根据他的要求编写特定的格式,估算器这里使用f1_score,他既包含对准确度的考量又考虑到召回率,它由metrics.f1_score实现。

$$F = \dfrac{2 \times 准确率 \times 召回率}{准确率 + 召回率}$$

另外还有一些预处理的部分,考虑到情感问题,1, 对表情进行了词语的替换,2, 对于同义词的问题,使用词义消歧来进行处理,3,使用了SentiWordNet来进行一些词语的分数替换,这里面记录了大部分英文单词的正负向分数。