机器学习基础

朴素贝叶斯:用概率做判断

14 分钟

这一节讲一个基于概率的分类器。它的假设很「天真」,效果却出奇地好——尤其在文本分类上。


从贝叶斯公式出发

我们想知道:看到这些特征,它属于某一类的概率有多大?

分母对所有类别都一样,比大小时可以扔掉。所以只需比较分子:

问题在于 没法算——特征的所有组合数量爆炸,数据再多也不够估计。


「朴素」假设:特征之间相互独立

假设在给定类别的条件下,各个特征相互独立,那么:

一个联合概率变成了 个单变量概率的乘积,每一个都能从数据里直接数出来。

这个假设几乎总是错的(「免费」和「优惠」在垃圾邮件里明显相关),但模型照样能用。原因是:分类只需要比较哪个类别的分数更高,即使概率估得不准,排序往往仍然正确。


垃圾邮件分类:最经典的应用

判断一封含「免费」「中奖」「点击」的邮件:

每一项都好算:

对「正常邮件」算一遍同样的式子,哪个大就判哪类。


两个必须处理的工程问题

① 零概率问题

如果「区块链」这个词从没在垃圾邮件里出现过,整个连乘就变成 0——一个词直接否决了所有其他证据。

解决:拉普拉斯平滑(加一平滑),分子加 1,分母加词表大小:

② 下溢问题

几百个小于 1 的概率连乘,结果会小到浮点数表示不了(变成 0)。

解决:取对数,连乘变连加

对数不改变大小顺序,但数值稳定得多。这是数值计算里的通用技巧,在损失函数、似然估计中反复出现。


三个变体,对应不同数据

变体 适用 sklearn
多项式 词频计数 MultinomialNB
伯努利 词「出现/未出现」的 0-1 特征 BernoulliNB
高斯 连续特征(假设服从正态分布) GaussianNB
from sklearn.naive_bayes import MultinomialNB
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.pipeline import make_pipeline

clf = make_pipeline(CountVectorizer(), MultinomialNB(alpha=1.0))  # alpha 就是平滑系数

它的价值在哪

训练极快(就是数数)、内存极省小数据也能work天然支持增量学习

在深度学习之前,朴素贝叶斯长期是文本分类的标准基线。今天它依然是很好的第一个模型——用来快速判断「这个文本分类问题到底有多难」。

练习:为什么朴素贝叶斯要对概率取对数?如果不取会发生什么?

小纸条

朴素贝叶斯「朴素」在哪里,这个假设错了为什么还能用?零概率和下溢分别怎么解决?

登录 后可看答案