0%

机器学习—朴素贝叶斯

一、贝叶斯

贝叶斯定理是关于随机事件A和B的条件概率

image-20240906101253074

其中P(A|B)是在 B 发生的情况下 A 发生的概率, A 的后验概率

P(B|A)是在 A 发生的情况下 B发生的概率, B 的后验概率

P(A)是 A 的先验概率

P(B)是 B 的先验概率

后验概率=(相似度*先验概率)/标准化常量

相似度= P(B|A)/P(B)

后验概率=标准相似度*先验概率

条件概率就是事件 A 在另外一个事件 B 已经发生条件下的发生概率。条件概率表示为P(A|B),读作“在 B 发生的条件下 A 发生的概率”。

联合概率表示两个事件共同发生(数学概念上的交集)的概率。A 与 B 的联合概率表示为P(A∩B)。

二、朴素贝叶斯

朴素贝叶斯法是典型的生成学习方法、生成方法由训练数据学习联合概率分布P(X,Y),然后求得后验概率分布P(Y\X).具体来说,利用训练数据学习P(X |y)和P(Y)的估计,得到联合概率分布:
$$
P(X,Y)=P(Y)P(X/Y)
$$
朴素贝叶斯的基本条件是条件独立性

image-20240906103804404

朴素贝叶斯利用贝叶斯定理与学到的联合概率模型进行分类预测

image-20240906103905845

将输入x分到后验概率最大的类y

image-20240906103929386

后验概率最大等价于0-1损失函数时的期望风险最小化

三、朴素贝叶斯算法

极大似然估计

image-5b043befdc4747031b3bd8c6e4019b7f

贝叶斯估计

用极大似然估计可能会出现所要估计的概率为 0 的情况,这会影响到后验概率的计算结果,使分类产生偏差。解决这一问题的方法是采用贝叶斯估计。

条件概率的贝叶斯估计

image-a299f3fd3b86dd7a942653c8f49b6313

其中,λ ≥ 0 λ ≥ 0λ≥0。当 λ = 0 λ = 0λ=0 时就是极大似然估计。常取 λ = 1 λ = 1λ=1,这时称为拉普拉斯平滑
先验概率的贝叶斯估计

image-8a5c25f06e340cccb93dc9755b61145a

K的含义和Sj相同,即表示分类个数

四、sklearn代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# -*- codeing = utf-8 -*-
# @Time : 2024/9/6 11:04
# @Author : Luo_CW
# @File : cn_weibo_test.py
# @Software : PyCharm

# 导包
import numpy as np
import pandas as pd
import re
import jieba
# 训练模型,朴素贝叶斯算法
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.naive_bayes import MultinomialNB,BernoulliNB

# 停去词
stopword_path = "cn_stopwords.txt"

def load_stopwords(file_path):
stop_words = []
with open(file_path, encoding='UTF-8') as words:
stop_words.extend([i.strip() for i in words.readlines()])
return stop_words


# 去掉{% %}之间的内容
def clearContentWithSpecialCharacter(content):
content = content.replace("{%", "1")
content = content.replace("%}", "1")
pattern = re.compile(r'(1)(.*)(1)')
return pattern.sub(r'', content)


# 预处理
def review_to_text(review):
stop_words = load_stopwords(stopword_path)

# 去掉@用户名
review = re.sub("(@[a-zA-Z0-9_\u4E00-\u9FA5]+)", '', review)

# 去除英文
review = re.sub("[^\u4e00-\u9fa5^a-z^A-Z]", '', review)

# 分词
review_cut = jieba.cut(review)

# 去掉停用词
if stop_words:
all_stop_words = set(stop_words)
words = [w for w in review_cut if w not in all_stop_words]
return words

# 加载语料
def load_curpus(path):
data = []
with open(path,"r",encoding="utf-8") as f:
for line in f:
[_,sentiment,comment] = line.split(",",2)
data.append((comment,int(sentiment)))
return data

# 处理语料
def pro_curpus(path):
data = []
with open(path,"r",encoding="utf-8") as f:
for line in f:
[_,sentiment,comment] = line.split(",",2) #以,为分界 分成3份
content = review_to_text(comment)
data.append((content,int(sentiment)))
return data


train_data = load_curpus("train.txt")
test_data = load_curpus("test.txt")

train_data_pro = pro_curpus("train.txt")
test_data_pro = pro_curpus("test.txt")



train_df = pd.DataFrame(train_data_pro,columns=['content','sentiment'])
test_df = pd.DataFrame(test_data_pro,columns=['content','sentiment'])

# 将文档处理成 tokens
data_str = [' '.join(content) for content,sentiment in train_data_pro ] + \
[' '.join(content) for content,sentiment in test_data_pro ] # 以' '将切割的词连接(join)起来

# 词向量(数据处理)
vect = CountVectorizer(max_df = 0.8,min_df = 5)

# 训练模型,朴素贝叶斯算法
nb = BernoulliNB()

vect.fit_transform(data_str) # 对训练集用fit_transform 测试集用transform,否则词向量的维度会不等


# 生成训练集 测试集的 词向量
X_data, y_data = [], []
for content, sentiment in train_data_pro:
X_data.append(" ".join(content))
y_data.append(sentiment)
X_train = vect.transform(X_data)
y_train = y_data

X_data2,y_data2 =[],[]
for content,sentiment in test_data_pro:
X_data2.append(" ".join(content))
y_data2.append(sentiment)
X_test = vect.transform(X_data2)
y_test = y_data2

# 使用贝叶斯进行训练
nb.fit(X_train,y_train)
train_score = nb.score(X_train,y_train)
print(train_score)

# 打印 bad_cases
bad_cases = []
for i in range(X_train.shape[0]):
if(nb.predict(X_train[i])!=y_train[i]):
# print("[%s],[%s],[真实:%s],[判断:%s]" %(review_data[i],X_train[i],y_train[i],nb.predict(X_train_vect[i])))
print("[%s],[%s],[真实:%s],[判断:%s]" %(train_data[i],X_data[i],y_train[i],nb.predict(X_train[i])))

# 测试模型
test_score = nb.score(X_test,y_test)
print(test_score)

from sklearn import metrics
result = nb.predict(X_test)
print(metrics.classification_report(y_test, result))

bad_cases = []
for i in range(result.shape[0]):
if(result[i]!=y_test[i]):
print("[%s],[真实:%s],[判断:%s]" %(train_df['content'][i],y_test[i],result[i]))