学习目标:
4. 说明条件概率与联合概率
5. 说明贝叶斯公式、以及特征独立的关系
6. 记忆贝叶斯公式
7. 知道拉普拉斯平滑系数
8. 应用贝叶斯公式实现概率的计算
9. 会使用朴素贝叶斯对商品评论进行情感分析
朴素贝叶斯算法主要还是用来分类的。
Q:那么与之前学习的 KNN 算法有什么区别呢?
A:朴素贝叶斯算法和 KNN 算法都是分类算法,但它们之间有一些区别:
根据上面两张图可以知道,朴素贝叶斯就是根据 概率 来判断所属的类别,这跟我们之前学习的 KNN 和决策树判断类别不同。
KNN 算法是通过测量不同特征值之间的距离来进行分类。它的思路是:如果一个样本在特征空间中的 k 个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别。
决策树算法则是通过构建一棵决策树来进行分类。它从根节点开始,对实例的某一特征进行测试,根据测试结果将实例分配到其子节点;每一个子节点对应着该特征的一个取值。然后,每个子节点都按照这种方式进行测试,直到所有实例都被正确分类或者没有更多的特征可供选择为止。
学习目标:
概率是一种用来衡量事件发生可能性的数值。它通常用一个 [0, 1] 之间的实数来表示,其中0表示事件不可能发生,1表示事件一定会发生。概率的定义有多种方式,其中最常见的是经典概率和频率概率。
简而言之:概率就是一件事情发生的可能性。
例如:扔出一个硬币,头像朝上的概率为 P ( X ) P(X) P(X),它的取值在 [ 0 , 1 ] [0, 1] [0,1]之间。
在讲这两个概率之前我们通过一个例子,来计算一些结果:
样本数 | 职业 | 体型 | 女生是否喜欢 |
---|---|---|---|
1 | 程序员 | 超重 | 不喜欢 |
2 | 产品 | 匀称 | 喜欢 |
3 | 程序员 | 匀称 | 喜欢 |
4 | 程序员 | 超重 | 喜欢 |
5 | 美工 | 匀称 | 不喜欢 |
6 | 美工 | 超重 | 不喜欢 |
7 | 产品 | 匀称 | 喜欢 |
问题如下:
计算结果为:
P ( 喜欢 ) = 喜欢的人数 总人数 = 4 7 P ( 程序员 , 匀称 ) 联合概率 = 同时满足两个条件的人数 总人数 = 1 7 P ( 程序员 ∣ 喜欢 ) 条件概率 = 女生喜欢且职业是程序员的人数 女生喜欢的人数 = 2 4 = 1 2 P ( 程序员 , 超重 ∣ 喜欢 ) 联合条件概率 = 女生喜欢且职业是程序员且体重超重的人数 女生喜欢的人数 = 1 4 \begin{aligned} &P(喜欢) = \frac{喜欢的人数}{总人数} = \frac{4}{7} \\ &P(程序员,匀称)_{联合概率} = \frac{同时满足两个条件的人数}{总人数} = \frac{1}{7} \\ &P(程序员|喜欢)_{条件概率} = \frac{女生喜欢且职业是程序员的人数}{女生喜欢的人数} = \frac{2}{4} = \frac{1}{2}\\ &P(程序员,超重|喜欢)_{联合条件概率} = \frac{女生喜欢且职业是程序员且体重超重的人数}{女生喜欢的人数} = \frac{1}{4} \end{aligned} P(喜欢)=总人数喜欢的人数=74P(程序员,匀称)联合概率=总人数同时满足两个条件的人数=71P(程序员∣喜欢)条件概率=女生喜欢的人数女生喜欢且职业是程序员的人数=42=21P(程序员,超重∣喜欢)联合条件概率=女生喜欢的人数女生喜欢且职业是程序员且体重超重的人数=41
P ( 喜欢 ) P(喜欢) P(喜欢) 是一个简单的概率
思考题:在小明是产品经理并且体重超重的情况下,如何计算小明被女生喜欢的概率?
即 P ( 喜欢 ∣ 产品 , 超重 ) = ? P(喜欢|产品,超重)=? P(喜欢∣产品,超重)=?。
在这个例子中,我们无法计算小明被女生喜欢的概率,因为表格中没有关于小明的信息。我们只能根据表格中给出的数据计算概率,而不能推断出不在表格中的人的概率。
而且给出的表格中,所有的产品都是体型匀称的,没有超重的情况。
此时我们需要用到朴素贝叶斯进行求解,在讲解贝叶斯公式之前,首先复习一下联合概率、条件概率和相互独立的概念。
P ( A ∣ B ) = P ( B ∣ A ) P ( A ) P ( B ) P(A|B) = P(B|A)\frac{P(A)}{P(B)} P(A∣B)=P(B∣A)P(B)P(A)
P ( C ∣ W ) = P ( W ∣ C ) P ( C ) P ( W ) P(C|W) = \frac{P(W|C)P(C)}{P(W)} P(C∣W)=P(W)P(W∣C)P(C)
其中:
那么思考题就可以套用贝叶斯公式来解决:
P ( C ∣ W ) = P ( W ∣ C ) P ( C ) P ( W ) P ( 喜欢 ∣ 产品 , 超重 ) = P ( 产品 , 超重 ∣ 喜欢 ) P ( 喜欢 ) P ( 产品 , 超重 ) \begin{aligned} & P(C|W) = \frac{P(W|C)P(C)}{P(W)} \\ & P(喜欢|产品, 超重) = \frac{P(产品, 超重|喜欢)P(喜欢)}{P(产品,超重)} \end{aligned} P(C∣W)=P(W)P(W∣C)P(C)P(喜欢∣产品,超重)=P(产品,超重)P(产品,超重∣喜欢)P(喜欢)
上式中, P ( 产品 , 超重 ∣ 喜欢 ) P(产品,超重|喜欢) P(产品,超重∣喜欢) 和 P ( 产品 , 超重 ) P(产品,超重) P(产品,超重) 的结果均为0,导致无法计算结果。这是因为我们的样本量太少了,不具有代表性。
本来现实生活中,肯定是存在职业是产品经理并且体重超重的人的, P ( 产品 , 超重 ) P(产品,超重) P(产品,超重) 不可能为0。而且事件“职业是产品经理”和事件“体重超重”通常被认为是相互独立的事件,但是根据我们有限的7个样本计算 P ( 产品 , 超重 ) = P ( 产品 ) P ( 超重 ) P(产品, 超重) = P(产品) P(超重) P(产品,超重)=P(产品)P(超重) 不成立。而朴素贝叶斯可以帮助我们解决这个问题。
朴素贝叶斯,简单理解,就是假定了特征与特征之间相互独立的贝叶斯公式。也就是说,朴素贝叶斯,之所以朴素,就在于假定了特征与特征相互独立。所以,思考题如果按照朴素贝叶斯的思路来解决,就可以是:
P ( 产品 , 超重 ) = P ( 产品 ) × P ( 超重 ) = 2 7 ∗ 3 7 = 6 49 P ( 产品 , 超重 ∣ 喜欢 ) = P ( 产品 ∣ 喜欢 ) × P ( 超重 ∣ 喜欢 ) = 1 2 × 1 4 = 1 8 P ( 喜欢 ∣ 产品 , 超重 ) = P ( 产品 , 超重 ∣ 喜欢 ) × P ( 喜欢 ) P ( 产品 , 超重 ) = 1 8 × 4 7 × 6 49 = 7 12 \begin{aligned} & P(产品, 超重) = P(产品) \times P(超重) = \frac{2}{7} * \frac{3}{7} = \frac{6}{49}\\ & P(产品, 超重 | 喜欢) = P(产品 | 喜欢) \times P(超重 | 喜欢) = \frac{1}{2} \times \frac{1}{4} = \frac{1}{8}\\ & P(喜欢 | 产品, 超重) = P(产品, 超重 | 喜欢) \times \frac{P(喜欢)}{P(产品, 超重)} = \frac{1}{8} \times \frac{4}{7} \times \frac{6}{49} = \frac{7}{12} \end{aligned} P(产品,超重)=P(产品)×P(超重)=72∗73=496P(产品,超重∣喜欢)=P(产品∣喜欢)×P(超重∣喜欢)=21×41=81P(喜欢∣产品,超重)=P(产品,超重∣喜欢)×P(产品,超重)P(喜欢)=81×74×496=127
那么这个公式如果应用在文章分类的场景当中,我们可以这样看:
公式可以理解为:
P ( C ∣ F 1 , F 2 , . . . ) = P ( F 1 , F 2 , . . . ∣ C ) P ( C ) P ( F 1 , F 2 , . . . ) P(C|F1, F2, ...) = \frac{P(F1, F2, ... | C)P(C)}{P(F1, F2, ...)} P(C∣F1,F2,...)=P(F1,F2,...)P(F1,F2,...∣C)P(C)
其中 C C C 可以是不同类别。
公式分为三个部分:
如果计算两个类别概率比较,所以我们只要比较前面的大小就可以,得出谁的概率大。
需求:通过前四个训练样本(文章),判断第五篇文章,是否属于China类。
文档ID | 文档中的词 | 属于C=China类 | |
---|---|---|---|
训练集 | 1 | Chinese Beijing Chinese | Yes |
2 | Chinese Chinese Shanghai | Yes | |
3 | Chinese Macao | Yes | |
4 | Tokyo Japan Chinese | No | |
测试集 | 5 | Chinese Chinese Chinese Tokyo Japan | ? |
计算结果:
P ( C ∣ C h i n e s e , C h i n e s e , C h i n e s e , T o k y o , J a p a n ) = P ( C h i n e s e , C h i n e s e , C h i n e s e , T o k y o , J a p a n ∣ C ) × P ( C ) P ( C h i n e s e , C h i n e s e , C h i n e s e , T o k y o , J a p a n ) = P ( C h i n e s e ) 3 × P ( T o k y o ∣ C ) × P ( J a p a n ∣ C ) × P ( C ) [ P ( C h i n e s e ) 3 × P ( T o k y o ) × P ( J a p a n ) ] \begin{aligned} P(C|Chinese, Chinese, Chinese, Tokyo, Japan) & = P(Chinese, Chinese, Chinese, Tokyo, Japan|C) \\ & \times \frac{P(C)}{P(Chinese, Chinese, Chinese, Tokyo, Japan)}\\ & = P(Chinese)^3 \times P(Tokyo|C) \times P(Japan | C) \\ & \times \frac{P(C)}{[P(Chinese)^3 \times P(Tokyo) \times P(Japan)]} \end{aligned} P(C∣Chinese,Chinese,Chinese,Tokyo,Japan)=P(Chinese,Chinese,Chinese,Tokyo,Japan∣C)×P(Chinese,Chinese,Chinese,Tokyo,Japan)P(C)=P(Chinese)3×P(Tokyo∣C)×P(Japan∣C)×[P(Chinese)3×P(Tokyo)×P(Japan)]P(C)
这个文章是需要计算是不是China类,是或者不是最后的分母值都相同。
首先计算是China类的概率:
P ( C h i n e s e ∣ C ) = 5 / 8 P ( T o k y o ∣ C ) = 0 / 8 P ( J a p a n ∣ C ) = 0 / 8 \begin{aligned} & P(Chinese|C) = 5/8 \\ & P(Tokyo|C) = 0/8\\ & P(Japan|C) = 0/8 \end{aligned} P(Chinese∣C)=5/8P(Tokyo∣C)=0/8P(Japan∣C)=0/8
接着计算不是China类的概率:
P ( C h i n e s e ∣ C ) = 1 / 3 P ( T o k y o ∣ C ) = 1 / 3 P ( J a p a n ∣ C ) = 1 / 3 \begin{aligned} & P(Chinese|C) = 1/3\\ & P(Tokyo|C) = 1/3\\ & P(Japan|C) = 1/3\\ \end{aligned} P(Chinese∣C)=1/3P(Tokyo∣C)=1/3P(Japan∣C)=1/3
问题:从上面的例子我们得到 P ( T o k y o ∣ C ) P(Tokyo|C) P(Tokyo∣C) 和 P ( J a p a n ∣ C ) P(Japan|C) P(Japan∣C) 都为0,这是不合理的。如果词频列表里面有很多出现次数都为0,很可能计算结果都为零。
主要还是因为样本数量太少了,不具有普遍性和规律性。
解决方法:拉普拉斯平滑系数
P ( F 1 ∣ C ) = N i + α N + α m P(F1|C) = \frac{N_i + \alpha}{N + \alpha m} P(F1∣C)=N+αmNi+α
其中:
这个文章是需要计算是不是China类:
首先计算是China类的概率:0.0003
P ( C h i n e s e ∣ C ) = 5 8 → 5 + 1 8 + 6 = 6 14 P ( T o k y o ∣ C ) = 0 8 → 0 + 1 8 + 6 = 1 14 P ( J a p a n ∣ C ) = 0 8 → 0 + 1 8 + 6 = 1 14 \begin{aligned} & P(Chinese|C) = \frac{5}{8} \rightarrow \frac{5 + 1}{8 + 6} = \frac{6}{14}\\ & P(Tokyo|C) = \frac{0}{8} \rightarrow \frac{0 + 1}{8 + 6} = \frac{1}{14}\\ & P(Japan|C)= \frac{0}{8} \rightarrow \frac{0 + 1}{8 + 6} = \frac{1}{14}\\ \end{aligned} P(Chinese∣C)=85→8+65+1=146P(Tokyo∣C)=80→8+60+1=141P(Japan∣C)=80→8+60+1=141
m m m 为训练集中特征词的个数,重复不计,这里为6
接着计算不是China类的概率:0.0001
P ( C h i n e s e ∣ C ) = 1 3 → 1 + 1 3 + 6 = 2 9 P ( T o k y o ∣ C ) = 1 3 → 1 + 1 3 + 6 = 2 9 P ( J a p a n ∣ C ) = 1 3 → 1 + 1 3 + 6 = 2 9 \begin{aligned} & P(Chinese|C) = \frac{1}{3} \rightarrow \frac{1+1}{3+6} = \frac{2}{9}\\ & P(Tokyo|C)= \frac{1}{3} \rightarrow \frac{1+1}{3+6} = \frac{2}{9}\\ & P(Japan|C)= \frac{1}{3} \rightarrow \frac{1+1}{3+6} = \frac{2}{9}\\ \end{aligned} P(Chinese∣C)=31→3+61+1=92P(Tokyo∣C)=31→3+61+1=92P(Japan∣C)=31→3+61+1=92
0.0003 > 0.0001 0.0003 > 0.0001 0.0003>0.0001,所以我们认为文章属于China的概率大一些。
小结:
学习目标:
sklearn.naive_bayes.MultinomialINB(alpha=1.0)
sklearn.naive_bayes.MultinomialNB
是一个朴素贝叶斯分类器,适用于具有离散特征的分类,例如文本分类中的单词计数。多项式分布通常需要整数特征计数。但是,在实践中,分数计数(如tf-idf)也可以工作。alpha
:浮点型或形状为(n_features,)的数组,可选,默认为1.0。添加(拉普拉斯/ Lidstone)平滑参数(设置alpha = 0和force_alpha = True,以获得无平滑)。fit_prior
:布尔型,可选,默认为True。是否学习类先验概率。如果为false,则将使用均匀先验。class_prior
:形状为(n_classes,)的数组,可选,默认为None。类的先验概率。如果指定,则根据数据不调整先验概率。fit(X, y[, sample_weight])
:根据X,y拟合朴素贝叶斯分类器。数据集创建如下:
{"Unnamed: 0":{"0":0,"1":1,"2":2,"3":3,"4":4,"5":5,"6":6,"7":7,"8":8,"9":9,"10":10,"11":11,"12":12},"\u5185\u5bb9":{"0":"\u4ece\u7f16\u7a0b\u5c0f\u767d\u7684\u89d2\u5ea6\u770b\uff0c\u5165\u95e8\u6781\u4f73\u3002","1":"\u5f88\u597d\u7684\u5165\u95e8\u4e66\uff0c\u7b80\u6d01\u5168\u9762\uff0c\u9002\u5408\u5c0f\u767d\u3002","2":"\u8bb2\u89e3\u5168\u9762\uff0c\u8bb8\u591a\u5c0f\u7ec6\u8282\u90fd\u6709\u987e\u53ca\uff0c\u4e09\u4e2a\u5c0f\u9879\u76ee\u53d7\u76ca\u532a\u6d45\u3002","3":"\u524d\u534a\u90e8\u5206\u8bb2\u6982\u5ff5\u6df1\u5165\u6d45\u51fa\uff0c\u8981\u8a00\u4e0d\u70e6\uff0c\u5f88\u8d5e","4":"\u770b\u4e86\u4e00\u904d\u8fd8\u662f\u4e0d\u4f1a\u5199\uff0c\u6709\u4e2a\u6982\u5ff5\u800c\u5df2","5":"\u4e2d\u89c4\u4e2d\u77e9\u7684\u6559\u79d1\u4e66\uff0c\u96f6\u57fa\u7840\u7684\u770b\u4e86\u4f9d\u65e7\u770b\u4e0d\u61c2","6":"\u5185\u5bb9\u592a\u6d45\u663e\uff0c\u4e2a\u4eba\u8ba4\u4e3a\u4e0d\u9002\u5408\u6709\u5176\u5b83\u8bed\u8a00\u7f16\u7a0b\u57fa\u7840\u7684\u4eba","7":"\u7834\u4e66\u4e00\u672c","8":"\u9002\u5408\u5b8c\u5b8c\u5168\u5168\u7684\u5c0f\u767d\u8bfb\uff0c\u6709\u5176\u4ed6\u8bed\u8a00\u7ecf\u9a8c\u7684\u53ef\u4ee5\u53bb\u770b\u522b\u7684\u4e66\u3002","9":"\u57fa\u7840\u77e5\u8bc6\u5199\u7684\u633a\u597d\u7684!","10":"\u592a\u57fa\u7840","11":"\u7565_\u55e6\u3002\u3002\u9002\u5408\u5b8c\u5168\u6ca1\u6709\u7f16\u7a0b\u7ecf\u9a8c\u7684\u5c0f\u767d","12":"\u771f\u7684\u771f\u7684\u4e0d\u5efa\u8bae\u4e70"},"\u8bc4\u4ef7":{"0":"\u597d\u8bc4","1":"\u597d\u8bc4","2":"\u597d\u8bc4","3":"\u597d\u8bc4","4":"\u5dee\u8bc4","5":"\u5dee\u8bc4","6":"\u5dee\u8bc4","7":"\u5dee\u8bc4","8":"\u5dee\u8bc4","9":"\u597d\u8bc4","10":"\u5dee\u8bc4","11":"\u5dee\u8bc4","12":"\u5dee\u8bc4"}}
复制上述JSON代码,保存到本地,然后使用pd.read_json()
方法读取即可。
import pandas as pd
import numpy as np
import jieba
import matplotlib.pyplot as plt
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.naive_bayes import MultinomialNB
# 1. 获取数据
data = pd.read_csv("./data/书籍评价.csv", encoding='gbk')
# 2. 数据基本处理
## 2.1 取出内容列,对数据进行分析
content = data["内容"]
content.head()
0 从编程小白的角度看,入门极佳。
1 很好的入门书,简洁全面,适合小白。
2 讲解全面,许多小细节都有顾及,三个小项目受益匪浅。
3 前半部分讲概念深入浅出,要言不烦,很赞
4 看了一遍还是不会写,有个概念而已
Name: 内容, dtype: object
## 2.2 选择停用词
# 加载停用词
stopwords = []
with open("./data/stopwords.txt", 'r', encoding="utf-8") as f:
lines = f.readlines()
for tmp in lines:
line = tmp.strip()
stopwords.append(line)
stopwords
['!',
'"',
'#',
'$',
'%',
'&',
"'",
'(',
...
'当着',
'形成',
'彻夜',
'彻底',
'彼',
'彼时',
...]
停用词大全:https://blog.csdn.net/Dorisi_H_n_q/article/details/82114913
## 2.3 把“内容”转换为标准格式
comment_lst = []
for tmp in content:
print("原始数据:", tmp)
# 通过结巴分词对文本数据进行切割(把一句句话变成一个个词)
seg_lst = jieba.cut(tmp, cut_all=False)
print("切割后的数据", seg_lst)
# 拼接字符串
seg_str = ','.join(seg_lst)
print("拼接后的字符串:", seg_str)
comment_lst.append(seg_str)
print()
comment_lst
原始数据: 从编程小白的角度看,入门极佳。
切割后的数据
拼接后的字符串: 从,编程,小白,的,角度看,,,入门,极佳,。
原始数据: 很好的入门书,简洁全面,适合小白。
切割后的数据
拼接后的字符串: 很,好,的,入门,书,,,简洁,全面,,,适合,小白,。
原始数据: 讲解全面,许多小细节都有顾及,三个小项目受益匪浅。
切割后的数据
拼接后的字符串: 讲解,全面,,,许多,小,细节,都,有,顾及,,,三个,小,项目,受益匪浅,。
原始数据: 前半部分讲概念深入浅出,要言不烦,很赞
切割后的数据
拼接后的字符串: 前半部,分讲,概念,深入浅出,,,要言不烦,,,很赞
原始数据: 看了一遍还是不会写,有个概念而已
切割后的数据
拼接后的字符串: 看,了,一遍,还是,不会,写,,,有个,概念,而已
原始数据: 中规中矩的教科书,零基础的看了依旧看不懂
切割后的数据
拼接后的字符串: 中规中矩,的,教科书,,,零,基础,的,看,了,依旧,看不懂
原始数据: 内容太浅显,个人认为不适合有其它语言编程基础的人
切割后的数据
拼接后的字符串: 内容,太,浅显,,,个人,认为,不,适合,有,其它,语言,编程,基础,的,人
原始数据: 破书一本
切割后的数据
拼接后的字符串: 破书,一本
原始数据: 适合完完全全的小白读,有其他语言经验的可以去看别的书。
切割后的数据
拼接后的字符串: 适合,完完全全,的,小白读,,,有,其他,语言,经验,的,可以,去,看,别的,书,。
原始数据: 基础知识写的挺好的!
切割后的数据
拼接后的字符串: 基础知识,写,的,挺,好,的,!
原始数据: 太基础
切割后的数据
拼接后的字符串: 太,基础
原始数据: 略_嗦。。适合完全没有编程经验的小白
切割后的数据
拼接后的字符串: 略,_,嗦,。,。,适合,完全,没有,编程,经验,的,小白
原始数据: 真的真的不建议买
切割后的数据
拼接后的字符串: 真的,真的,不,建议,买
['从,编程,小白,的,角度看,,,入门,极佳,。',
'很,好,的,入门,书,,,简洁,全面,,,适合,小白,。',
'讲解,全面,,,许多,小,细节,都,有,顾及,,,三个,小,项目,受益匪浅,。',
'前半部,分讲,概念,深入浅出,,,要言不烦,,,很赞',
'看,了,一遍,还是,不会,写,,,有个,概念,而已',
'中规中矩,的,教科书,,,零,基础,的,看,了,依旧,看不懂',
'内容,太,浅显,,,个人,认为,不,适合,有,其它,语言,编程,基础,的,人',
'破书,一本',
'适合,完完全全,的,小白读,,,有,其他,语言,经验,的,可以,去,看,别的,书,。',
'基础知识,写,的,挺,好,的,!',
'太,基础',
'略,_,嗦,。,。,适合,完全,没有,编程,经验,的,小白',
'真的,真的,不,建议,买']
## 2.4 统计词的个数
# 实例化统计词对象
cv = CountVectorizer(stop_words=stopwords)
# 进行词数统计
X = cv.fit_transform(comment_lst) # 计算出各个词语出现的次数
name = cv.get_feature_names_out() # 获取词袋中所有文本的关键字
print(X.toarray()) # 查看词频矩阵
print(name)
[[0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0
0]
[0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0
0]
[0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 1
1]
[0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 1 0 0 0 1 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0
0]
[0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0]
[0 0 0 1 1 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
0]
[0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 1 1 0
0]
[1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
0]
[0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 1 0
0]
[0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0]
[0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 1 0
0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0
0]]
['一本' '一遍' '三个' '中规中矩' '依旧' '入门' '内容' '分讲' '前半部' '受益匪浅' '基础' '基础知识' '完完全全'
'小白' '小白读' '建议' '很赞' '教科书' '有个' '极佳' '概念' '浅显' '深入浅出' '看不懂' '真的' '破书'
'简洁' '细节' '经验' '编程' '要言不烦' '角度看' '讲解' '语言' '适合' '项目' '顾及']
## 2.5 准备训练集和测试集(因为总共才13条数据,因此我们手动分训练集和测试集就行,不用sklearn的方法了)
# 准备训练集
x_train = X.toarray()[:10, :]
y_train = data["评价"][:10]
# 准备测试集
x_test = X.toarray()[10:, :]
y_test = data["评价"][10:]
print("训练集:\r\n", x_train, "\r\n", y_train)
print("测试集:\r\n", x_test, "\r\n", y_test)
训练集:
[[0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0
0]
[0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0
0]
[0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 1
1]
[0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 1 0 0 0 1 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0
0]
[0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0]
[0 0 0 1 1 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
0]
[0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 1 1 0
0]
[1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
0]
[0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 1 0
0]
[0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0]]
0 好评
1 好评
2 好评
3 好评
4 差评
5 差评
6 差评
7 差评
8 差评
9 好评
Name: 评价, dtype: object
测试集:
[[0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 1 0
0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0
0]]
10 差评
11 差评
12 差评
Name: 评价, dtype: object
# 3. 模型训练
# 构建朴素贝叶斯算法分类器
mnb = MultinomialNB(alpha=1) # alpha为Laplace平滑系数
# 训练数据
mnb.fit(x_train, y_train)
# 预测数据
y_pred = mnb.predict(x_test)
# 预测值与真实值展示
print("预测值:", y_pred)
print("真实值:\r\n", y_test)
预测值:['差评' '差评' '差评']
真实值:
10 差评
11 差评
12 差评
Name: 评价, dtype: object
score = mnb.score(x_test, y_test)
print("模型准确率为:", score * 100, "%")
模型准确率为: 100.0 %
上述案例中,我们的目标值设置的是汉字,其实对于大型项目而言,最好是设置为数字,这样会好一些。
应用案例:百度AI情感倾向分析
小结:
sklearn.naive_bayes.MultinomialNB(alpha=1.0)
alpha
:拉普拉斯平滑系数朴素贝叶斯法是基于贝叶斯定理与特征条件独立假设的分类方法。
Q:什么叫做先验,什么叫做后验?
A:先验概率(prior probability)是指在考虑新证据之前,我们对某个假设的不确定性的度量。它通常基于以往的经验或背景知识得出。
后验概率(posterior probability)是指在考虑新证据之后,我们对某个假设的不确定性的度量。它是根据贝叶斯定理计算出来的,结合了先验概率和新证据的可能性。
举个例子,假设你想知道明天是否会下雨。你知道这个季节下雨的概率是30%,所以你的先验概率是30%。然后你看了天气预报,发现预报说明天有90%的概率会下雨。你可以使用贝叶斯定理来结合这两个信息,计算出明天下雨的后验概率。
在计算条件概率分布 P ( X = x ∣ Y = c k ) P(X=x | Y=c_k) P(X=x∣Y=ck) 时,朴素贝叶斯引入了一个很强的条件独立假设,即,当 Y Y Y 确定时, X X X 的各个特征分量取值之间相互独立。
朴素贝叶斯算法之所以被称为“朴素”,是因为它假设所有特征之间都是相互独立的。这意味着,它假设每个特征对分类结果的影响都是独立的,不受其他特征的影响。
然而,在现实生活中,这种假设并不总是成立的。特征之间可能存在相关性,这可能会影响算法的准确性。尽管如此,朴素贝叶斯算法仍然在许多应用中表现良好。
为了避免贝叶斯定理求解时面临的组合爆炸、样本稀疏问题。
假设条件概率分为:
P ( X = x ∣ Y = c k ) = P ( X ( 1 ) = x ( 1 ) , x ( 2 ) , . . . , x ( n ) ∣ Y = c k ) P(X=x|Y=c_k) = P(X^{(1)} = x^{(1)}, x^{(2)}, ..., x^{(n)} | Y=c_k) P(X=x∣Y=ck)=P(X(1)=x(1),x(2),...,x(n)∣Y=ck)
其中: x ( j ) x^{(j)} x(j) 可能取值有 S j S_j Sj 个, j = 1 , 2 , . . . , n j = 1,2,..., n j=1,2,...,n, Y Y Y 可能取值有 K K K 个,那么参数个数为 K ∏ j = 1 m S j K \prod^m_{j=1}S_j K∏j=1mSj 个,这就导致条件概率分布的参数数量为指数级别。
朴素贝叶斯算法引入条件独立性假设,是为了简化计算。根据贝叶斯定理,我们需要计算每个类别的后验概率,然后选择具有最大后验概率的类别作为预测结果。为了计算后验概率,我们需要计算联合概率分布,即所有特征同时发生的概率。
如果不引入条件独立性假设,则计算联合概率分布需要考虑所有特征之间的相关性,这会使计算变得非常复杂。但是,如果我们假设所有特征之间都是条件独立的,则可以将联合概率分布简化为每个特征的概率的乘积,这大大简化了计算。
尽管条件独立性假设在现实生活中并不总是成立,但朴素贝叶斯算法仍然在许多应用中表现良好。
在估计条件概率 P(X∣Y) 时,如果出现概率为0的情况,会导致整个后验概率为0。为了避免这种情况,可以使用平滑技术来调整概率估计。
简单来说,引入 λ \lambda λ:
人们在使用分类器之前,首先做的第一步(也是最重要的一步)往往是特征选择,这个过程的目的就是为了排除特征之间的共线性,即选择相对较为独立的特征。
对于分类任务来说,只要各类别的条件概率排序正确,无需精准概率值就可以得出正确分类。如果属性间依赖对所有类别影响相同,或依赖关系的影响能相互抵消,则属性条件独立性假设在降低计算复杂度的同时不会对性能产生负面影响。
尽管朴素贝叶斯算法的属性独立性假设在实际情况中很难成立,但它仍然能够在许多应用中取得较好的效果。这主要是因为朴素贝叶斯算法的目标是选择具有最大后验概率的类别,而不是准确地估计后验概率。
即使属性之间存在相关性,朴素贝叶斯算法仍然能够在大多数情况下正确地对类别进行排序。这意味着,具有最大后验概率的类别通常仍然是正确的类别,即使后验概率的绝对值并不准确。
此外,朴素贝叶斯算法通常在数据量较大时表现良好。当数据量足够大时,算法能够从数据中学习到足够的信息来弥补属性独立性假设的不足。
朴素贝叶斯和逻辑回归(LR)都是常用的分类算法,但它们之间存在一些重要的区别。
区别一:朴素贝叶斯是生成模型,而 LR 是判别模型。
朴素贝叶斯:
逻辑回归LR:
从概率框架的角度来理解机器学习,主要有两种策略:
显然,前面介绍的逻辑回归、决策树都可归入判别式模型的范畴,还有后面学到的 BP 神经网络、支持向量机等。
对生成式模型来说,必然需要考虑 P ( c ∣ x ) = P ( x , c ) P ( x ) P(c|x) = \frac{P(x, c)}{P(x)} P(c∣x)=P(x)P(x,c)
区别二:
区别三:
进一步说明:
前者是生成式模型,后者是判别式模型,二者的区别就是生成式模型与判别式模型的区别。
首先,Naive Bayes通过已知样本求得先验概率 P ( Y ) P(Y) P(Y) 及条件概率 P ( X ∣ Y ) P(X|Y) P(X∣Y)。对于给定的实例,计算联合概率,进而求出后验概率。也就是说,它尝试去找到底这个数据是怎么生成的(产生的),然后再进行分类。哪个类别最有可能产生这个信号,就属于那个类别。
优点:
缺点:
相比之下,LR 不关心样本中类别的比例及类别下出现特征的概率,它直接给出预测模型的式子。设每个特征都有一个权重,训练样本数据更新权重 w w w,得出最终表达式。
优点:
缺点: