Skip to main content

朴素贝叶斯

朴素贝叶斯

这个算法是建立在贝叶斯理论上的分类方法。

它的假设条件是自变量之间相互独立。

简言之,朴素贝叶斯假定某一特征的出现与其它特征无关。即给定类别,特征之间没有相关性。这个假设是“朴素”的来源。

比如说,如果一个水果它是红色的,圆状的,直径大概 7cm 左右,我们可能猜测它为苹果。即使这些特征之间存在一定关系,在朴素贝叶斯算法中我们都认为红色,圆状和直径在判断一个水果是苹果的可能性上是相互独立的。

一个二分类的案例假设:

我今天收到了 100 封邮件,其中有 80 封是垃圾邮件,20 封是正常邮件。

P(垃圾邮件) = 80/100 = 0.8
P(正常邮件) = 20/100 = 0.2

我选定了一些词作为特征,这些词可能出现在邮件中,也可能不出现。这些词有“免费”,“恭喜”,“辛苦”等。

我发现垃圾邮件中有 20 封含有“免费”这个词,50 封含有“恭喜”这个词,0 封含有“辛苦”这个词。

P(免费|垃圾邮件) = 20/80 = 0.25
P(恭喜|垃圾邮件) = 50/80 = 0.625
P(辛苦|垃圾邮件) = 0/80 = 0

正常邮件中有 5 封含有“免费”这个词。6 封含有“恭喜”这个词,2 封含有“辛苦”这个词。

P(免费|正常邮件) = 5/20 = 0.25
P(恭喜|正常邮件) = 6/20 = 0.3
P(辛苦|正常邮件) = 2/20 = 0.1

现在我收到了一封邮件,这封邮件内容为:“恭喜您获得了一次免费的机会”,我想知道这封邮件是垃圾邮件的概率是多少?

P(垃圾邮件|免费,恭喜) = P(免费|垃圾邮件)_P(恭喜|垃圾邮件)_ P(垃圾邮件)= 0.25 _0.625_ 0.8 = 0.125

P(正常邮件|免费,恭喜) = P(免费|正常邮件)_P(恭喜|正常邮件)_ P(正常邮件)= 0.25 _0.3_ 0.2 = 0.015

因为 P(垃圾邮件|免费,恭喜) > P(正常邮件|免费,恭喜),所以这封邮件被判定为垃圾邮件。

如果狡猾的垃圾邮件制造者把邮件内容改为:“恭喜您获得了一次免费的机会,辛苦您动动手指参加我们的免费活动”,那么这封邮件被判定为垃圾邮件的概率就会变成 0,因为“辛苦”这个词在正常邮件中有出现,在垃圾邮件中没有出现。

改进:拉普拉斯平滑法

在每个关键词上人为的增加一个出现的次数,这样就不会出现概率为 0 的情况了。(下面的公式免费的平方表示这个关键词出现 2 次)

P(垃圾邮件|免费,恭喜) = P(免费|垃圾邮件)_P(恭喜|垃圾邮件)_ P(垃圾邮件)= (21/80)² _(51/80)_ 0.8 = 0.0351421875

P(正常邮件|免费,恭喜) = P(免费|正常邮件)_P(恭喜|正常邮件)_ P(正常邮件)= (6/20)²*(7/20)* 0.2 =0.0063
from sklearn.naive_bayes import GaussianNB
import numpy as np

# 创建一些示例数据
X = np.array([[1], [2], [3], [4], [5]]) # 特征
y = np.array([0, 0, 1, 1, 1]) # 目标标签

# 创建朴素贝叶斯分类器 (高斯朴素贝叶斯)
model = GaussianNB()

# .fit() 方法用于拟合模型
model.fit(X, y)

# 要预测的新数据点
new_data_point = np.array([[6]])

# .predict() 方法返回预测的类别
predicted_class = model.predict(new_data_point)
# .predict_proba() 方法返回每个类别的概率
predicted_proba = model.predict_proba(new_data_point)

print("预测类别:", predicted_class)
print("类别概率:", predicted_proba)

简单示例

from sklearn.naive_bayes import GaussianNB
from sklearn.model_selection import train_test_split
import sklearn.datasets
# 加载数据
data = sklearn.datasets.load_iris()
# .data 属性包含特征
X = data.data
# .target 属性包含目标标签
y = data.target
# 划分数据集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)
# 创建朴素贝叶斯分类器 (高斯朴素贝叶斯)
model = GaussianNB()
# 拟合模型
model.fit(X_train, y_train)

效果评估

from sklearn.metrics import accuracy_score

# 计算准确率
accuracy = accuracy_score(y_test, model.predict(X_test))
accuracy

查看分类错误的样本信息

import pandas as pd

# 把测试数据、目标标签、预测结果合并到一起
# pd.DataFrame()函数用于创建DataFrame
# pd.concat()函数用于合并多个DataFrame
# axis=1 表示按列合并
df = pd.concat(
[pd.DataFrame(X_test,columns=data.feature_names),
pd.DataFrame(y_test,columns=['target']),
pd.DataFrame(model.predict(X_test),columns=['predict'])
],axis=1 )

# 筛选target列与predict列不相等的数据
df.loc[df['target']!=df['predict']]