前言

最近学了下几个监督学习的算法,觉得朴素贝叶斯很有意思,来做一个总结。


一、概念

朴素贝叶斯算法(Naive Bayes Algorithm)用来解决分类问题,尤其是文本分类。在分类问题中,数据常常包含很高的维度(因为每个词代表数据中的一个特征),故其他算法可能不太适合。该算法用于垃圾邮件过滤、情感检测、评分分类等。使用朴素贝叶斯的优势在于其速度,使得高纬度的数据预测变得非常简单。

朴素贝叶斯算法模型预测的是实例属于给定特征集合类别的概率,它是一个概率分类器。因为它假定模型中的一个特征独立于另一个特征而存在,所以被称为朴素。换句话说,参与预测的每个特征之间彼此没有关系。但在我们的现实世界中,很少能满足这个条件。


贝叶斯定理

Python 实现朴素贝叶斯算法 朴素贝叶斯算法举例_算法


举例:

P( X | Y ) = [P ( Y | X ) * P ( X )] / P ( Y )

记忆方法:
P( 狗 )*P( 猫 | 狗 ) = P( 猫 )*P( 狗 | 猫 )


现在,思考一个机器学习的分类问题。假设有 k 个 C 类别的特性,目标是预测一个实例属于 Ci 类的概率。朴素贝叶斯算法使用特征向量并通过这些特征集计算 Ci 类的条件概率,计算所有类别的条件概率,并且将具有最大概率的类别被判定为预测的类别。

朴素贝叶斯算法的优点是实现起来简单快捷。它在分类特征中表现良好,其假设数字特征的数据来自于正态分布。


二、朴素贝叶斯的简单应用

女生的脾气总是捉摸不透,对于一个程序猿来说相当棘手,但是如果我们能在和女生的聊天的同时,利用朴素贝叶斯构建模型,来预测女生说到某些关键词时所对应的情绪,那岂不是完美。

下面展示实例:

在某猪的7段对话中的几个关键词。用0和1来代表说某段话时的心情,0代表心情差,1代表心情好。我们可以用一个数组来表示7段对话的心情:

y = [ 1,0,1,0,0,1,1]

而在这七段对话当中,含有重复的关键词有:“嗯嗯”、“好嘞”、“哈哈哈”、“嘿嘿”、“?”。信息列在下表:

嗯嗯

好嘞

哈哈哈

嘿嘿


第一段

1

1

1

1

0

第二段

1

0

0

0

1

第三段

0

0

1

1

0

第四段

0

1

0

0

0

第五段

1

0

0

0

1

第六段

0

1

1

1

0

第七段

0

0

1

0

0

同样的,我们将其转化为数组X。

下面我们用 Jupyter Notebook 来看一下数据的关系,在 Jupyter Notebook 中输入代码如下:

# 导入numpy
import numpy as np

# 将X, y赋值为np数组
X = np.array([[1,1,1,1,0],
              [1,0,0,0,1],
              [0,0,1,1,0],
              [0,1,0,0,0],
              [1,0,0,0,1],
              [0,1,1,1,0],
              [0,0,1,0,0]])
y = np.array([1,0,1,0,0,1,1])
# 对不同分类计算每个特征为1的数量
counts = {}
for label in np.unique(y):
    counts[label] = X[y == label].sum(axis=0)
print("feature counts:\n{}".format(counts))

运行代码,得到以下结果:

Python 实现朴素贝叶斯算法 朴素贝叶斯算法举例_朴素贝叶斯_02


结果分析:当 y 为0时,也就是在心情差的3段对话中,有2段说了 “嗯嗯” ,有1段说了 “好嘞”,没有出现 “哈哈哈” 和 “嘿嘿”,有2段说了 “?”;同时,在 y 为1时,也就是在心情好的4段对话中,有1段说了 “嗯嗯”,有2段说了 “好嘞”,有4段说了 “哈哈哈”,有3段说了 “嘿嘿”,没有出现 “?”。我们发现,说了 “嗯嗯” 时,如果没有说 “哈哈”,心情就倾向于差,反之同理。

那么对于朴素贝叶斯来说,它会根据上述的计算来进行推理。我们进行验证:

# 导入伯努利贝叶斯
from sklearn.naive_bayes import BernoulliNB

# 使用伯努利贝叶斯拟合数据
clf = BernoulliNB()
clf.fit(X,y)
# 要进行预测的这一段对话,只有嗯嗯,没有哈哈 
Dialog = [[1,0,0,0,0]]
pre = clf.predict(Dialog)
print('=========================')
if pre == [1]:
    print("放心,没有生气")
else:
    print("生气啦,快哄哄")
print('=========================')

运行代码的结果如下:

Python 实现朴素贝叶斯算法 朴素贝叶斯算法举例_朴素贝叶斯_03


结果分析:可以看出,朴素贝叶斯分类器放到心情差分类当中。

那么如果有另外一段对话,说了 “好嘞” ,“哈哈哈”,但是没有说 “嗯嗯”,结果会怎么样呢?

# 假设另一段对话数据如下
Another_Dialog = [[0,1,1,1,0]]
# 使用训练好的模型进行预测
pre2 = clf.predict(Another_Dialog)
print('=========================')
if(pre2 == [1]):
    print("放心,没有生气")
else:
    print("生气啦,快哄哄")
print('=========================')

运行代码,结果如下:

Python 实现朴素贝叶斯算法 朴素贝叶斯算法举例_python_04


结果分析:可以看到,这次分类器将其放到心情好的分类中。


现在让我们来看看朴素贝叶斯给出的预测准确率:

print(clf.predict_proba(Dialog))

运行代码,结果如下图:

Python 实现朴素贝叶斯算法 朴素贝叶斯算法举例_python_05


结果分析:这就是说,我们预测的第一段对话,心情不好的概率是9%,心情好的概率是91%,看起来还是挺不错的。


同样,再看下第二段对话:

Python 实现朴素贝叶斯算法 朴素贝叶斯算法举例_朴素贝叶斯_06


结果分析:也就是说,第二段对话,心情不好的概率是1.2%,心情好的概率是98.8%,可以可以。

不要太乐观!朴素贝叶斯虽然是很好用的分类器,但是对于预测具体的数值不是很擅长,因此 predict_proba 给出的概率,不必当真。