朴素贝叶斯(naive bayes)原理小结
1. 朴素贝叶斯的学习
1.1 基本假设:条件独立性
1.2 朴素贝叶斯分类器
1.3 后验概率的含义
2. 参数估计
2.1 极大似然估计
2.2 贝叶斯估计:极大似然估计+平滑机制
2.3 分类算法
3. 代码示例:朴素贝叶斯 文本分类
(1)加载数据
(2)文本预处理(清洗文本,分词,去除停用词)
(3)抽取文本特征:使用词袋模型
(4)训练贝叶斯模型(多项式贝叶斯)
(5)评价指标&测试
4. 模型评价
参考
本博客中使用到的完整代码请移步至我的github:https://github.com/qingyujean/Magic-NLPer,求赞求星求鼓励~~~
朴素贝叶斯,基于贝叶斯定理
与特征条件独立假设
。
条件概率公式:
全概率公式:
适用问题:多类分类
模型特点:特征与类别的联合概率分布,特征条件独立性
模型类型:生成模型
损失函数:对数似然损失
学习策略:极大似然估计,最大后验概率估计
学习算法:概率计算公式
1. 朴素贝叶斯的学习
1.1 基本假设:条件独立性
设输入空间
,输出为类标记,输出空间为
,设训练集由 联合概率分布
独立用分布
产生。
朴素贝叶斯
,就是基于给定的训练集,在基于 特征条件独立的假设
下,学习联合概率分布
。
就是学得的模型,然后用于预测,预测时要使用到贝叶斯定理。
先验概率分布:
条件概率分布:
后验概率分布:
朴素贝叶斯法对如上条件概率作了
“特征条件独立假设”
:这是一个较强的假设,它使得朴素贝叶斯法实现简单,高效,易于实现,但有时会牺牲一定的分类准确率。不过在实际应用中,朴素贝叶斯也有work的很好的时候,比如垃圾邮件分类,文本分类。
条件概率分布 的参数数量是
指数级
的。假设 的取值有 个, 的取值有 个,则参数总个数为:
1.2 朴素贝叶斯分类器
在给定训练集学习到联合概率分布
后,就可以对给定的输入
做类别预测了,即计算后验概率
,后验概率最大的类作为预测结果
。计算时使用 贝叶斯定理
:
所以,朴素贝叶斯分类器
可表示为:
分母对所有
都一样,所以朴素贝叶斯分类器
可简化为:
1.3 后验概率的含义
后验概率最大化等价于0-1损失的期望风险最小化。
基于后验概率 可知样本 分类为 所产生的期望损失,即在样本 上的条件风险为:
其中
为0-1损失函数
:
那么总体风险(期望风险函数)则为:
显然,对每个样本
若能使得其相应的条件风险
最小化,则总体风险
也将被最小化
。这样就产生了 贝叶斯判定准则
:为最小化总体风险,只需在每个样本上选择那个能使条件风险
最小的类别标记
,即:
期望风险最小化:
如此,根据期望最小化准则,就得到了后验概率最大化准则:
即对每个样本 ,选择能使后验概率 最大的类别标记。
此时, 成为贝叶斯最优分类器,与之对应的总体风险 成为贝叶斯风险。 反映了分类器所能达到的最好性能,即通过机器学习所能产生的模型精度的理论上限。
2. 参数估计
朴素贝叶斯法中,学习就意味着估计先验概率
和条件概率
。
2.1 极大似然估计
先验概率
表达了特种空间中各类样本所占比例,根据大数定律
,当训练集包含充足的独立同分布的样本时,
可通过各类样本出现的频率来进行估计。
先验概率的极大似然估计
:
对于条件概率
来说,由于它涉及
所有属性的联合概率,直接根据样本的频率估计将会遇到严重的困难,显然直接使用频率来估计是不可行。普斯贝叶斯采用了“特征/属性条件独立性
”:对已知类别,假设所有属性相互独立
。即:
此时,便可以使用频率来估计各类样本的某个属性出现的条件概率
,即为每个属性来估计条件概率
。
条件概率的极大似然估计
:
其中N和K分别表示共有N个样本和K个类别, 为指示函数
【注意】
:如果 是连续属性
,则假定,其中 和 分别是第 类样本在第 个属性上取值的均值
和方差
,则有。
2.2 贝叶斯估计:极大似然估计+平滑机制
极大似然估计的计算式中有连乘运算,如果其中一个概率值为0,就会影响后验概率 的计算,使分类结果产生偏差。很多样本的取值在训练集中可能没有出现,但这不代表概率就为0。
此时可在计算中引入一个平滑因子
,
时就是极大似然估计。取
时等价于在随机变量各个取值的频数上都赋予一个正数。
时成为 拉普拉斯平滑
。
先验概率的贝叶斯估计
:
条件概率的贝叶斯估计
:
引入平滑因子后, 仍然具有概率性质,因为有:
表明 确为一种概率分布。
拉普拉斯修正避免了因训练集样本不充分而导致的概率估值为0的问题,并且在训练集变大时,修正所引入的先验影响(拉普拉斯修正实质上假设了属性值与类别均匀分布)也会逐渐变得可忽略,使得估值逐渐趋向于实际概率值。
2.3 分类算法
基于极大似然估计的朴素贝叶斯算法:
在scikit-learn
中,一共有3个朴素贝叶斯的分类算法类:分别是GaussianNB
,MultinomialNB
和BernoulliNB
。其中GaussianNB
就是先验为高斯分布的朴素贝叶斯,MultinomialNB
就是先验为多项式分布的朴素贝叶斯,而BernoulliNB
就是先验为伯努利分布的朴素贝叶斯。
这三个类适用的分类场景各不相同,一般来说,如果样本特征的分布大部分是连续值,使用GaussianNB
会比较好。如果样本特征的分布大部分是多元离散值,使用MultinomialNB
比较合适。而如果样本特征是二元离散值或者很稀疏的多元离散值,应该使用BernoulliNB
。
3. 代码示例:朴素贝叶斯 文本分类
下面使用朴素贝叶斯,来实现一个中文文本分类的任务,数据是二分类,
-
数据说明:文本二分类,1和0,判断是否属于政治上的出访类事件 -
数据来源:https://github.com/ares5221/ALBERT_text_classification
(1)加载数据
df_train = pd.read_csv(data_dir+'train.txt', encoding='UTF-8', sep='\s', header=None,
names=['label', 'content'], index_col=False)
df_train = df_train.dropna() # 过滤含有NaN的数据
df_test = pd.read_csv(data_dir+'test.txt', encoding='UTF-8', sep='\s', header=None,
names=['label', 'content'], index_col=False)
df_test = df_test.dropna() # 过滤含有NaN的数据
print(df_train.head())
print()
print(df_train['label'].value_counts())
输出:
label content
0 1 当地时间2月10日,白宫发表声明称,美国总统特朗普及夫人梅拉尼娅将于2月24日至25日访问印...
1 0 俄罗斯卫星通讯社11日最新消息,菲律宾总统杜特尔特已下令终止与美国间的《访问部队协定》(VFA)。
2 1 据俄罗斯卫星网6日报道,土耳其总统发言人卡林表示,俄罗斯军事代表团将于近日访问安卡拉,讨论叙...
3 0 先来说说什么是LPDDR5:要知道,手机中有两种内存颗粒,一种就是DRAM也就是大家常说的“...
4 1 在疫情的关键时刻,出现了一件令人感动的事情,让我们明白这才是真正的好朋友,不惧疫情访问我国,...
0 151
1 149
Name: label, dtype: int64
查看训练集,测试集各多少条样本:
print(df_train.shape, df_test.shape)
输出:
(300, 2) (80, 2)
(2)文本预处理(清洗文本,分词,去除停用词)
# 保留文本中文、数字、英文、短横线
def clear_text(text):
p = re.compile(r"[^\u4e00-\u9fa5^0-9^a-z^A-Z\-、,。!?:;()《》【】,!\?:;[\]()]") # 匹配不是中文、数字、字母、短横线的部分字符
return p.sub('', text) # 将text中匹配到的字符替换成空字符
# 加载停用词表
def load_stopwords_file(filename):
print('加载停用词...')
stopwords=pd.read_csv(filename, index_col=False, quoting=3, sep="\t", names=['stopword'], encoding='utf-8')
#quoting:控制引用字符引用行为,QUOTE_MINIMAL (0), QUOTE_ALL (1), QUOTE_NONNUMERIC (2) or QUOTE_NONE (3).
stopwords = set(stopwords['stopword'].values)
print('停用词表大小:', len(stopwords))
return stopwords
# 文本预处理:清洗,分词,并去除停用词
def preprocess_text(df_content):
stopwords_set = load_stopwords_file(stopwords_file) # 加载停用词表
content_seg = []#分词后的content
for i,text in enumerate(df_content):
text = clear_text(text.strip())
segs = jieba.lcut(text, cut_all=False) # cut_all=False是精确模式,True是全模式;默认模式是False 返回分词后的列表
segs = filter(lambda x: len(x.strip())>1, segs) # 词长度要>1,没有保留标点符号
segs = filter(lambda x: x not in stopwords_set, segs)
# print(segs) # segs是一个filter object
# segs = list(segs) # segs需要一次类似“持久化”的操作,否则每次被操作一次后segs就为空了
content_seg.append(" ".join(segs))
return content_seg
df_train['content_seg'] = preprocess_text(df_train['content'])
df_test['content_seg'] = preprocess_text(df_test['content'])
print(df_train.head()) #
print(df_train.shape)
输出:
加载停用词...
停用词表大小:2613
加载停用词...
停用词表大小:2613
label content \
0 1 当地时间2月10日,白宫发表声明称,美国总统特朗普及夫人梅拉尼娅将于2月24日至25日访问印...
1 0 俄罗斯卫星通讯社11日最新消息,菲律宾总统杜特尔特已下令终止与美国间的《访问部队协定》(VFA)。
2 1 据俄罗斯卫星网6日报道,土耳其总统发言人卡林表示,俄罗斯军事代表团将于近日访问安卡拉,讨论叙...
3 0 先来说说什么是LPDDR5:要知道,手机中有两种内存颗粒,一种就是DRAM也就是大家常说的“...
4 1 在疫情的关键时刻,出现了一件令人感动的事情,让我们明白这才是真正的好朋友,不惧疫情访问我国,...
content_seg
0 时间 白宫 发表声明 美国 总统 特朗普 夫人 拉尼 日至 访问 印度 特朗普 上任 首次 ...
1 俄罗斯 卫星 通讯社 最新消息 菲律宾 总统 杜特 尔特 下令 终止 美国 访问 部队 协定...
2 俄罗斯 卫星 报道 土耳其 总统 发言人 卡林 俄罗斯 军事 代表团 近日 访问 安卡拉 讨...
3 LPDDR5 手机 中有 两种 内存 颗粒 一种 DRAM 常说 运行 内存 提到 LPDD...
4 疫情 关键时刻 一件 令人感动 事情 明白 这才 朋友 疫情 访问 我国 王毅 机场 迎接
(300, 3)
(3)抽取文本特征:使用词袋模型
vectorizer = CountVectorizer(analyzer='word', # 以词为粒度做ngram
max_features=4000, # 保留最常见的4000个词
)
vectorizer.fit(df_train['content_seg'].tolist())
print('CountVectorizer train finished!')
train_features = vectorizer.transform(df_train['content_seg'])
输出:
CountVectorizer train finished!
(4)训练贝叶斯模型(多项式贝叶斯)
bayes_classifier = MultinomialNB() # 使用多项式贝叶斯
bayes_classifier.fit(train_features, df_train['label'])
print('MultinomialNB train finished!')
输出:
MultinomialNB train finished!
(5)评价指标&测试
查看准确率accuracy:
test_features = vectorizer.transform(df_test['content_seg'])
bayes_classifier.score(test_features, df_test['label']) # Return the mean accuracy
输出:
0.9375
进一步查看精准率precision、召回率recall、f1值:
from sklearn.metrics import precision_score, recall_score, f1_score
y_pred = bayes_classifier.predict(test_features)
print('precision_score: %.3f' % precision_score(y_pred, df_test['label']))
print('recall_score: %.3f' % recall_score(y_pred, df_test['label']))
print('f1_score: %.3f' % f1_score(y_pred, df_test['label']))
输出:
precision_score: 0.952
recall_score: 0.930
f1_score: 0.941
分类结果还不错!
4. 模型评价
朴素贝叶斯法实现简单,高效,易于实现,但由于特征条件独立的假设太强,有时会牺牲一定的分类准确率。不过在实际应用中,朴素贝叶斯也有work的很好的时候,比如垃圾邮件分类,文本分类。
下面对该模型做一个评价总结。评价内容摘自刘建平老师的朴素贝叶斯算法原理小结 https://www.cnblogs.com/pinard/p/6069267.html:
优点:
-
1)朴素贝叶斯模型发源于古典数学理论,有稳定的分类效率。 -
2)对 小规模的数据
表现很好,能个处理多分类任务,适合增量式训练
,尤其是数据量超出内存时,我们可以一批批的去增量训练。 -
3)对缺失数据不太敏感,算法也比较简单, 常用于文本分类
。
缺点:
-
1)理论上,朴素贝叶斯模型与其他分类方法相比具有最小的误差率。但是实际上并非总是如此,这是因为朴素贝叶斯模型给定输出类别的情况下,假设属性之间相互独立,这个假设在实际应用中往往是不成立的,在属性个数比较多或者属性之间相关性较大时,分类效果不好。而在属性相关性较小时,朴素贝叶斯性能最为良好。对于这一点,有 半朴素贝叶斯
之类的算法通过考虑部分关联性适度改进。 -
2)需要知道先验概率,且先验概率很多时候取决于假设,假设的模型可以有很多种,因此在某些时候会由于假设的先验模型的原因导致预测效果不佳。 -
3)由于我们是通过先验和数据来决定后验的概率从而决定分类,所以分类决策存在一定的错误率。 -
4)对输入数据的表达形式很敏感。
完整代码地址
完整代码请移步至我的github:https://github.com/qingyujean/Magic-NLPer,求赞求星求鼓励~~~
最后:如果本文中出现任何错误,请您一定要帮忙指正,感激~
参考
[1] 统计学习方法(第2版) 李航
[2] 西瓜书-机器学习 周志华
[3] 朴素贝叶斯算法原理小结 刘建平 https://www.cnblogs.com/pinard/p/6069267.html