贝叶斯算法的原理和代码实现

贝叶斯算法要解决的问题:
假设我们知道了在A条件发生的情况下,B条件发生的概率(即条件概率),但是我们想知道在B条件发生的情况下,A条件发生的概率。我们就可以用到贝叶斯公式。
在这里插入图片描述
贝叶斯公式的分母是全概率公式,全概率公式如下:
如果事件B1、B2、B3…Bn 构成一个完备事件组,即它们两两互不相容,其和为全集;并且P(Bi)大于0,则对任一事件A有
P(A)=P(A|B1)P(B1) + P(A|B2)P(B2) + … + P(A|Bn)P(Bn)。
它将对一复杂事件A的概率求解问题转化为了在不同情况下发生的简单事件的概率的求和问题。

    而对于朴素贝叶斯算法,他的内容是这样的:

如果一个事物在一些属性条件发生的情况下,事物属于A的概率>属于B的概率,则判定事物属于A
全概率公式的经典案例:
例:高射炮向敌机发射三发炮弹,每弹击中与否相互独立且每发炮弹击中的概率均为0.3,又知敌机若中一弹,坠毁的概率为0.2,若中两弹,坠毁的概率为0.6,若中三弹,敌机必坠毁。求敌机坠毁的概率。
解:
假设敌机坠毁的事件为A,飞机中弹的事件为B,根据全概率公式
P(A)= P(A|B1)P(B1)+ P(A|B2)P(B2)+ P(A|B3)P(B3)
P(B1) = C31 0.30.70.7 = 0.441
P(B2) = C32 0.30.30.7 = 0.189
P(B3) = C33 0.30.30.3 = 0.027
然后代入就行。
贝叶斯算法在人工智能中的应用:
更常见于朴素贝叶斯算法。案例
大众点评、淘宝等电商上都会有大量的用户评论,比如:

评论 好评还是差评
1、衣服质量太差了!!!!颜色根本不纯!!! 0
2、我有一有种上当受骗的感觉!!!! 0
3、质量太差,衣服拿到手感觉像旧货!!!,穿上去不帅 0
4、上身漂亮,合身,很帅,给卖家点赞 1
5、穿上衣服帅呆了,给点一万个赞 1
6、我在他家买了三件衣服!!!!质量都很差! 0
7.衣服质量一点也不差,我很喜欢 1

我们的目的是让机器自动识别好评和差评。
解题思路,如果想要获得某条评论是好评还是差评。就需要得到他在某个词语下是好评的概率,然后相乘
为了获得在某个词语下好评的概率,例如P(好评|上当受骗)就必须通过贝叶斯算法获得在假如好评的情况下,上当受骗这个词语出现的概率。而这个概率是我们许多条数据统计出来的,可以获得的,拿这个数据为例。
(比如分解a: “差” “帅” ……)

 根据条件概率公式:
   在好评情况下差这个词出现的概率 P(差|好评)= P(差*好评)/P(好评)= 通过左边直接算是1/3,通过右边算
   在差评情况下差这个词出现的概率 P(差|差评)= P(差*差评)/P(差评)= 通过左边直接算是3/4,通过右边算
         在好评情况下帅这个词出现的概率 P(帅|好评)= P(帅*好评)/P(好评)= 通过左边直接算是2/3,通过右边算
   在差评情况下帅这个词出现的概率 P(帅|差评)= P(帅*差评)/P(差评)= 通过左边直接算是1/4,通过右边算
   帅的概率P(帅) = 3/7
   差的概率p(差)=4/7
   好评的概率,这种叫做先验概率。
   
   最大似然:最符合观测数据的例如(差|好评)最有优势。
   奥卡姆剃刀:P(好评)较大的模型有较大的优势

这样机器就学习到了一种思路:
之后又来了三个数据让机器自己判断
a、这么差的衣服以后再也不买了

 b、帅,有逼格
 c.这件衣服很帅,很帅,一点都不差

首先来判断a评论是好评还是差评
理论上: P(a是好评的概率) = P(好评的概率|差)*P(好评的概率|帅)

由于这一条评论没有出现帅,所以
P(a是好评的概率) = P(好评的概率|差)
转而去求后面两个概率的问题,根据贝叶斯算法
P(好评的概率|差)=(P(差|好评)P(好评))/P(差)=0.25

P(a是好评的概率)= 0.25
#####################################################################################################################
理论上:P(a是差评的概率)=P(差评的概率|差)*P(差评的概率|帅)
由于这一条评论没有出现帅,所以
P(a是好评的概率) = P(好评的概率|差)
P(差评的概率|差)=(P(差|差评)P(差评))/P(差)=0.75
P(a是差评的概率) = 0.75
因为0.75>0.25所以是差评

其次再来判断b是好评还是差评
理论上:P(b是好评的概率)=P(好评的概率|差)*P(好评的概率|帅)
但是没有出现差,所以
P(b是好评的概率)=P(好评的概率|帅)
P(好评的概率|帅)=(P(帅|好评)P(好评))/P(帅)=2/3
######################################################
#######################################################
P(b是差评的概率)=P(差评的概率|帅)
P(差评的概率|帅)=P(P(帅|差评)P(差评))/P(帅) = 1/3
2/3 >1/3所以是好评
最后再来判断c语句是好评还是差评
P(c是好评的概率)=P(好评的概率|帅)*P(好评的概率|差)
由于帅出现了两次:所以
P(c是好评的概率)=P(好评的概率|帅)*P(好评的概率|差)*P(好评的概率|帅)
P(好评的概率|帅)=(P(帅的概率|好评的情况下)P(好评))/ P(帅的全概率)=2/3
P(好评的概率|差)=(P(差的概率|好评的情况下)P(好评))/差的全概率=1/4
P(c是好评的概率)=1/9
######################################################################################################################
P(c是差评的概率)=P(差评的概率|帅)*P(差评的概率|差)*P(差评的概率|帅)
P(差评的概率|帅)=(P(帅|差评)P(差评))/P(帅)=1/3
P(差评的概率|差)=(P(差|差评的概率)P(差评))/P(差)=3/4
P(c是好评的概率)=1/3 * 1/3 *3/4 =1/12
1/9 >1/12 所以是好评
但是实际上,这个分词是有缺陷的,需要加入否定词,比如不差,应该单独拿出来作为好评,不然会导致判断不准确。所以以上的概率计算可能是有一点点问题的

Python代码实现新闻分类
原理:计算文本的相似度,跟哪个相似度高,就属于哪个类。首先进行训练数据,把某个种类下某些词出现的概率拿到,然后给出测试数据,然后分词,计算每个词出现的情况下是这个的概率,计算总概率。

import pandas as pd
import jieba
import numpy as np
df_news = pd.read_table("val.txt",names=["category","theme","url","content"],encoding="utf-8")
#读取数据
df_news.head()
content_list = df_news.content.values.tolist()
#把内容列变成list,然后用jieba分词
print(content_list[1000])
#结巴的分词,分为三种,全模式,精准模式,搜索引擎模式
new_list=[]
#分好词拼成字符串,中间用空格隔开,然后每个放在列表里
for line in content_list:
    string=""
    words = jieba.cut(line,cut_all=True)
    for j in words:
        if(j == " "):
            continue
        if (j != "\r\n"):
            j = j.strip()
            string = string + " " +j 
    new_list.append(string)
print(new_list[1000])

将词语变成稀疏向量

from sklearn.feature_extraction.text import CountVectorizer
'''主要有两个api来实现 CountVectorizer 和 TfidfVectorizer
CountVectorizer:
    只考虑词汇在文本中出现的频率
TfidfVectorizer:
    除了考量某词汇在文本出现的频率,还关注包含这个词汇的所有文本的数量
    能够削减高频没有意义的词汇出现带来的影响, 挖掘更有意义的特征'''
#具体查阅API文档
'''max_features : int or None, default=None
If not None, build a vocabulary that only consider the top max_features ordered by term frequency across the corpus.
This parameter is ignored if vocabulary is not None.'''

juzhen = CountVectorizer(analyzer="word",max_features=4000,lowercase=False)
#max_feature越大越好区分
result = juzhen.fit_transform(new_list)
print(result)

结果如下

(0, 1369)	1
  (0, 3684)	1
  (0, 2594)	1
  (0, 1222)	1
  (0, 3536)	1
  (0, 1255)	1
  (0, 2600)	1
  (0, 247)	1
  (0, 2060)	1
  (0, 298)	2
  (0, 1600)	2
  (0, 2995)	1
  (0, 286)	1
  (0, 985)	1
  (0, 76)	1
  (0, 1681)	2
  (0, 2254)	1
  (0, 3597)	2
  (0, 2593)	1
  (0, 1801)	2
  (0, 1800)	2
  (0, 3119)	1
  (0, 233)	1
  (0, 2592)	5
  (0, 3582)	1
  :	:
  (4999, 2423)	2
  (4999, 3183)	1
  (4999, 1447)	1
  (4999, 1248)	2
  (4999, 1053)	1
  (4999, 2215)	1
  (4999, 1512)	1
  (4999, 1111)	2
  (4999, 1506)	1
  (4999, 3181)	6
  (4999, 1453)	1
  (4999, 1363)	1
  (4999, 2994)	1
  (4999, 2298)	3
  (4999, 1229)	2
  (4999, 3909)	1
  (4999, 3989)	1
  (4999, 2449)	1
  (4999, 3205)	1
  (4999, 3666)	1
  (4999, 2567)	1
  (4999, 669)	1
  (4999, 275)	3
  (4999, 3771)	1
  (4999, 1255)	1

然后把种类换成数字,因为文字无法参与矩阵计算

np1 = df_news["category"].unique()
np1

种类如下

array(['汽车', '财经', '科技', '健康', '体育', '教育', '文化', '军事', '娱乐', '时尚'], dtype=object)
a = np1.size
for i in range((a)):
    print(np1[i])
    df_news.loc[df_news["category"] == np1[i],"category"] = i
df_news.head(5)

处理完成。

导包,建立模型
#首先对数据进行切分、
from sklearn.cross_validation import train_test_split
from sklearn.naive_bayes import MultinomialNB
from sklearn.metrics import confusion_matrix,classification_report,accuracy_score


x_train,x_test,y_train,y_test = train_test_split(result,np.array(df_news["category"],dtype=np.int32),test_size = 0.33,random_state=0)
classifier = MultinomialNB()
print(x_train.size)
print(y_train.size)

classifier.fit(x_train,y_train)
y_pred = classifier.predict(x_test)
cnf_matrix =confusion_matrix(y_test,y_pred)
#把小数位数改为2位
np.set_printoptions(precision=2)
print(accuracy_score(y_test,y_pred))

cnf_matrix

结果如下

324413
3350
0.806666666667
Out[99]:
array([[146,   0,   1,   0,   1,   0,   0,   0,   0,   1],
       [  1, 133,   8,   9,   0,   5,   4,   1,   0,   2],
       [  5,   4, 132,   3,   1,   4,   2,   0,   4,   6],
       [  0,   8,   0, 127,   0,   3,   2,   5,   0,  22],
       [  0,   0,   1,   0, 151,   1,   0,   1,   1,   0],
       [  7,   3,   1,  11,   0, 135,   1,   4,   7,  10],
       [  0,   1,   1,   0,   3,   5,  89,   6,  50,   6],
       [  2,   4,   0,   2,   6,   6,   5, 142,   2,   0],
       [  0,   1,   0,   0,   2,   1,  14,   2, 164,   1],
       [  3,   1,   5,  14,   0,   2,   3,   0,  21, 112]], dtype=int64)

模型的评估分数是80.6。混淆矩阵如下

猜你喜欢

转载自blog.csdn.net/qq_41302130/article/details/82927787