预测酒店评论是好评还是差评:
1. 房间真棒,离大马路很近,非常方便,不错。 好评 0.9954
2. 房间有点脏,厕所还漏水,空调不制冷,下次再也不来了。 差评 0.99
3. 地板不太干净,电视没信号,但是空调还可以,总之还行。 好评 0.56
pip3 install nltk -i
https://pypi.tuna.tsinghua.edu.cn/simple/
pip3 install jieba -i
https://pypi.tuna.tsinghua.edu.cn/simple/
import nltk.tokenize as tk
# 把样本按句子进行拆分 sent_list:句子列表
sent_list = tk.sent_tokenize(text)
# 把样本按单子进行拆分 word_list:单词列表
word_list = tk.word_tokenize(text)
# 把样本按单词进行拆分 punctTokenizer:分词器对象
punctTokenizer = tk.WordPunctTokenizer()
word_list = punctTokenizer.tokenize(text)
doc = "Are you curious about tokenization? Let's see how it works! We need to analyze a couple of sentences with punctuations to see it in action."
# 分句子
sents = tk.sent_tokenize(doc)
for i in range(len(sents)):
print(i+1, ':', sents[i])
"""
1 : Are you curious about tokenization?
2 : Let's see how it works!
3 : We need to analyze a couple of sentences with punctuations to see it in action.
"""
# 分单词
words = tk.word_tokenize(doc)
for i in range(len(words)):
print(i+1, ':', words[i])
"""
1 : Are
2 : you
3 : curious
4 : about
5 : tokenization
6 : ?
7 : Let
8 : 's
9 : see
10 : how
11 : it
12 : works
13 : !
14 : We
15 : need
16 : to
17 : analyze
18 : a
19 : couple
20 : of
21 : sentences
22 : with
23 : punctuations
24 : to
25 : see
26 : it
27 : in
28 : action
29 : .
"""
tokenizer = tk.WordPunctTokenizer()
words = tokenizer.tokenize(doc)
for i in range(len(words)):
print(i+1, ':', words[i])
"""
1 : Are
2 : you
3 : curious
4 : about
5 : tokenization
6 : ?
7 : Let
8 : '
9 : s
10 : see
11 : how
12 : it
13 : works
14 : !
15 : We
16 : need
17 : to
18 : analyze
19 : a
20 : couple
21 : of
22 : sentences
23 : with
24 : punctuations
25 : to
26 : see
27 : it
28 : in
29 : action
30 : .
"""
This hotel is very bad. The toilet in this hotel smells bed. The environment of this hotel is very good.
This hotel is very bad.
The toilet in this hotel smells bed.
The environment of this hotel is very good.
This | hotel | is | very | bad | The | toilet | in | smells | environment | of | good |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
1 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 |
1 | 1 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 1 | 1 | 1 |
import sklearn.feature_extraction.text as ft
# 构建词袋模型对象
cv = ft.CountVectorizer()
# 训练模型,把句子中所有可能出现的单词作为特征名,每一个句子为一个样本,单词在句子中出现的次数为特征值
bow = cv.fit_transform(sentences).toarray()
print(bow)
# 获取所有特征名
words = cv.get_features_names()
import sklearn.feature_extraction.text as ft
sents = ['This hotel is very bad.',
'The toilet in this hotel smells bad.',
'The environment of this hotel is very good.']
cv = ft.CountVectorizer()
bow = cv.fit_transform(sents)
print(bow)
print(bow.toarray())
print(cv.get_feature_names())
"""
(0, 9) 1
(0, 3) 1
(0, 5) 1
(0, 11) 1
(0, 0) 1
(1, 9) 1
(1, 3) 1
(1, 0) 1
(1, 8) 1
(1, 10) 1
(1, 4) 1
(1, 7) 1
(2, 9) 1
(2, 3) 1
(2, 5) 1
(2, 11) 1
(2, 8) 1
(2, 1) 1
(2, 6) 1
(2, 2) 1
[[1 0 0 1 0 1 0 0 0 1 0 1]
[1 0 0 1 1 0 0 1 1 1 1 0]
[0 1 1 1 0 1 1 0 1 1 0 1]]
['bad', 'environment', 'good', 'hotel', 'in', 'is', 'of', 'smells', 'the', 'this', 'toilet', 'very']
"""
这家酒店棒,装修棒,早餐棒,环境棒。 1
这家酒店烂,烂烂烂,真的烂。 0
这家酒店装修棒,服务烂。 ?
文
档
频
率
:
D
F
=
含
有
某
个
单
词
的
文
档
样
本
数
总
文
档
样
本
数
(
与
样
本
语
义
贡
献
度
反
相
关
)
文档频率: DF = \frac{含有某个单词的文档样本数}{总文档样本数}(与样本语义贡献度反相关)
文档频率:DF=总文档样本数含有某个单词的文档样本数(与样本语义贡献度反相关)
逆
文
档
频
率
:
I
D
F
=
l
o
g
(
总
样
本
数
1
+
含
有
某
个
单
词
的
样
本
数
)
(
与
样
本
语
义
贡
献
度
正
相
关
)
逆文档频率: IDF = log\left(\frac{总样本数}{1+含有某个单词的样本数}\right)(与样本语义贡献度正相关)
逆文档频率:IDF=log(1+含有某个单词的样本数总样本数)(与样本语义贡献度正相关)
# 构建词袋模型对象
cv = ft.CountVectorizer()
# 训练模型,把句子中所有可能出现的单词作为特征名,每一个句子为一个样本,单词在句子中出现的次数为特征值
bow = cv.fit_transform(sentences).toarray()
# 获取TF-IDF模型训练器
tt = ft.TfidfTransformer()
tfidf = tt.fit_transform(bow).toarray()
tt = ft.TfidfTransformer()
tfidf = tt.fit_transform(bow).toarray()
print(np.round(tfidf, 3))
print(cv.get_feature_names())
"""
[[0.488 0. 0. 0.379 0. 0.488 0. 0. 0. 0.379 0. 0.488]
[0.345 0. 0. 0.268 0.454 0. 0. 0.454 0.345 0.268 0.454 0. ]
[0. 0.429 0.429 0.253 0. 0.326 0.429 0. 0.326 0.253 0. 0.326]]
['bad', 'environment', 'good', 'hotel', 'in', 'is', 'of', 'smells', 'the', 'this', 'toilet', 'very']
"""
import numpy as np
import pandas as pd
import sklearn.datasets as sd
import sklearn.model_selection as ms
import sklearn.linear_model as lm
import sklearn.metrics as sm
# 加载数据集
data = sd.load_files('20news', encoding='latin1')
len(data.data) # 2968个样本
"""
2968
"""
import sklearn.feature_extraction.text as ft
# 整理输入集与输出集 TFIDF 把每一封邮件转成一个特征向量
cv = ft.CountVectorizer()
bow = cv.fit_transform(data.data)
tt = ft.TfidfTransformer()
tfidf = tt.fit_transform(bow)
# tfidf.shape # (2968,40605)
# 拆分测试集与训练集
train_x, test_x, train_y, test_y = ms.train_test_split(tfidf, data.target, test_size=0.1, random_state=7)
# 交叉验证
model = lm.LogisticRegression()
scores = ms.cross_val_score(model, tfidf, data.target, cv=5, scoring='f1_weighted')
# f1得分
print(scores.mean()) # 0.9597980963781605
# 训练模型
model.fit(train_x, train_y)
# 测试模型,评估模型
pred_test_y = model.predict(test_x)
print(sm.classification_report(test_y, pred_test_y))
"""
0.9597980963781605
precision recall f1-score support
0 0.81 0.96 0.88 57
1 0.97 0.89 0.93 65
2 1.00 0.95 0.97 61
3 1.00 1.00 1.00 54
4 1.00 0.95 0.97 60
accuracy 0.95 297
macro avg 0.96 0.95 0.95 297
weighted avg 0.96 0.95 0.95 297
"""
# 整理一组测试样本进行模型测试
test_data = ["In the last game, the spectator was accidentally hit by a baseball injury and has been hospitalized.",
"Recently, Lao Wang is studying asymmetric encryption algorithms.",
"The two-wheeled car is pretty good on the highway."]
# 把样本按照训练时的方式转换成tfidf矩阵,才可以交给模型进行预测
bow = cv.transform(test_data)
test_data = tt.transform(bow)
pred_test_y = model.predict(test_data)
print(pred_test_y)
print(data.target_names)
"""
[2 0 1]
['misc.forsale', 'rec.motorcycles', 'rec.sport.baseball', 'sci.crypt', 'sci.space']
"""
data.target_names
"""
['misc.forsale',
'rec.motorcycles',
'rec.sport.baseball',
'sci.crypt',
'sci.space']
"""
概率是反映随机事件出现的可能性大小. 随机事件是指在相同条件下,可能出现也可能不出现的事件. 例如:
(1)抛一枚硬币,可能正面朝上,可能反面朝上,这是随机事件. 正/反面朝上的可能性称为概率;
(2)掷骰子,掷出的点数为随机事件. 每个点数出现的可能性称为概率;
(3)一批商品包含良品、次品,随机抽取一件,抽得良品/次品为随机事件. 经过大量反复试验,抽得次品率越来越接近于某个常数,则该常数为概率.
我们可以将随机事件记为A或B,则P(A), P(B)表示事件A或B的概率.
指包含多个条件且所有条件同时成立的概率,记作 P ( A , B ) P ( A , B ) P(A,B) ,或 P ( A B ) P(AB) P(AB),或 P ( A ⋂ B ) P(A \bigcap B) P(A⋂B)
已知事件B发生的条件下,另一个事件A发生的概率称为条件概率,记为: P ( A ∣ B ) P(A|B) P(A∣B)
p(下雨|阴天)
事件A不影响事件B的发生,称这两个事件独立,记为:
P
(
A
B
)
=
P
(
A
)
P
(
B
)
P(AB)=P(A)P(B)
P(AB)=P(A)P(B)
因为A和B不相互影响,则有:
P
(
A
∣
B
)
=
P
(
A
)
P(A|B) = P(A)
P(A∣B)=P(A)
可以理解为,给定或不给定B的条件下,A的概率都一样大.
先验概率也是根据以往经验和分析得到的概率,例如:在没有任何信息前提的情况下,猜测对面来的陌生人姓氏,姓李的概率最大(因为全国李姓为占比最高的姓氏),这便是先验概率.
后验概率是指在接收了一定条件或信息的情况下的修正概率,例如:在知道对面的人来自“牛家村”的情况下,猜测他姓牛的概率最大,但不排除姓杨、李等等,这便是后验概率.
事情还没有发生,求这件事情发生的可能性的大小,是先验概率(可以理解为由因求果). 事情已经发生,求这件事情发生的原因是由某个因素引起的可能性的大小,是后验概率(由果求因). 先验概率与后验概率有不可分割的联系,后验概率的计算要以先验概率为基础.
贝叶斯定理由英国数学家托马斯.贝叶斯 ( Thomas Bayes)提出,用来描述两个条件概率之间的关系,定理描述为:
P
(
A
∣
B
)
=
P
(
A
)
P
(
B
∣
A
)
P
(
B
)
P(A|B) = \frac{P(A)P(B|A)}{P(B)}
P(A∣B)=P(B)P(A)P(B∣A)
其中,
P
(
A
)
P(A)
P(A)和
P
(
B
)
P(B)
P(B)是A事件和B事件发生的概率.
P
(
A
∣
B
)
P(A|B)
P(A∣B)称为条件概率,表示B事件发生条件下,A事件发生的概率. 推导过程:
P
(
A
,
B
)
=
P
(
B
)
P
(
A
∣
B
)
P
(
B
,
A
)
=
P
(
A
)
P
(
B
∣
A
)
P(A,B) =P(B)P(A|B)\\ P(B,A) =P(A)P(B|A)
P(A,B)=P(B)P(A∣B)P(B,A)=P(A)P(B∣A)
其中
P
(
A
,
B
)
P(A,B)
P(A,B)称为联合概率,指事件B发生的概率,乘以事件A在事件B发生的条件下发生的概率. 因为
P
(
A
,
B
)
=
P
(
B
,
A
)
P(A,B)=P(B,A)
P(A,B)=P(B,A), 所以有:
P
(
B
)
P
(
A
∣
B
)
=
P
(
A
)
P
(
B
∣
A
)
P(B)P(A|B)=P(A)P(B|A)
P(B)P(A∣B)=P(A)P(B∣A)
两边同时除以P(B),则得到贝叶斯定理的表达式. 其中,
P
(
A
)
P(A)
P(A)是先验概率,
P
(
A
∣
B
)
P(A|B)
P(A∣B)是已知B发生后A的条件概率,也被称作后验概率.
假设一个学校中 60%的男生 和40%的女生 ,女生穿裤子的人数和穿裙子的人数相等,所有的男生都穿裤子,一个人随机在远处眺望,看一个穿裤子的学生,请问这个学生是女生的概率:
p(女) = 0.4
p(裤子|女) = 0.5
p(裤子) = 0.8
P(女|裤子) = 0.4 * 0.5 / 0.8 = 0.25
P ( A ∣ B ) = P ( A ) P ( B ∣ A ) P ( B ) P(A|B) = \frac{P(A)P(B|A)}{P(B)} P(A∣B)=P(B)P(A)P(B∣A)
天气情况 | 穿衣风格 | 约女朋友 | ==> | 心情 |
---|---|---|---|---|
0(晴天) | 0(休闲) | 0(约了) | ==> | 0(高兴) |
0 | 1(风骚) | 1(没约) | ==> | 0 |
1(多云) | 1 | 0 | ==> | 0 |
0 | 2(破旧) | 1 | ==> | 1(郁闷) |
2(雨天) | 2 | 0 | ==> | 0 |
… | … | … | ==> | … |
0 | 1 | 0 | ==> | ? |
import sklearn.naive_bayes as nb
# 创建高斯朴素贝叶斯分类器对象
model = nb.GaussianNB()
model = nb.MultinomialNB()
model.fit(x, y)
result = model.predict(samples)
GaussianNB 更适合服从高斯分布的训练样本
MultinomialNB 更适合服从多项分布的训练样本
在sklearn中,提供了三个朴素贝叶斯分类器,分别是:
该示例中,样本的值为连续值,且呈正态分布,所以采用GaussianNB模型. 代码如下:
# 朴素贝叶斯分类示例
import numpy as np
import sklearn.naive_bayes as nb
import matplotlib.pyplot as mp
# 输入,输出
x, y = [], []
# 读取数据文件
with open("../data/multiple1.txt", "r") as f:
for line in f.readlines():
data = [float(substr) for substr in line.split(",")]
x.append(data[:-1]) # 输入样本:取从第一列到倒数第二列
y.append(data[-1]) # 输出样本:取最后一列
x = np.array(x)
y = np.array(y, dtype=int)
# 创建高斯朴素贝叶斯分类器对象
model = nb.GaussianNB()
model.fit(x, y) # 训练
# 计算显示范围
left = x[:, 0].min() - 1
right = x[:, 0].max() + 1
buttom = x[:, 1].min() - 1
top = x[:, 1].max() + 1
grid_x, grid_y = np.meshgrid(np.arange(left, right, 0.01),
np.arange(buttom, top, 0.01))
mesh_x = np.column_stack((grid_x.ravel(), grid_y.ravel()))
mesh_z = model.predict(mesh_x)
mesh_z = mesh_z.reshape(grid_x.shape)
mp.figure('Naive Bayes Classification', facecolor='lightgray')
mp.title('Naive Bayes Classification', fontsize=20)
mp.xlabel('x', fontsize=14)
mp.ylabel('y', fontsize=14)
mp.tick_params(labelsize=10)
mp.pcolormesh(grid_x, grid_y, mesh_z, cmap='gray')
mp.scatter(x[:, 0], x[:, 1], c=y, cmap='brg', s=80)
mp.show()
import numpy as np
import pandas as pd
import sklearn.datasets as sd
import sklearn.model_selection as ms
import sklearn.linear_model as lm
import sklearn.metrics as sm
# 加载数据集
data = sd.load_files('20news', encoding='latin1')
import sklearn.feature_extraction.text as ft
# 整理输入集与输出集 TFIDF 把每一封邮件转成一个特征向量
cv = ft.CountVectorizer()
bow = cv.fit_transform(data.data)
tt = ft.TfidfTransformer()
tfidf = tt.fit_transform(bow)
# tfidf.shape # (2968,40605)
# 拆分测试集与训练集
train_x, test_x, train_y, test_y = ms.train_test_split(tfidf, data.target, test_size=0.1, random_state=7)
# 交叉验证
# 使用朴素贝叶斯
import sklearn.naive_bayes as nb
model = nb.MultinomialNB()
scores = ms.cross_val_score(model, tfidf, data.target, cv=5, scoring='f1_weighted')
# f1得分
print(scores.mean())
# 训练模型
model.fit(train_x, train_y)
# 测试模型,评估模型
pred_test_y = model.predict(test_x)
print(sm.classification_report(test_y, pred_test_y))
"""
0.9458384770112502
precision recall f1-score support
0 1.00 0.84 0.91 57
1 0.94 0.94 0.94 65
2 0.95 0.97 0.96 61
3 0.90 1.00 0.95 54
4 0.97 1.00 0.98 60
accuracy 0.95 297
macro avg 0.95 0.95 0.95 297
weighted avg 0.95 0.95 0.95 297
"""
# 整理一组测试样本进行模型测试
test_data = ["In the last game, the spectator was accidentally hit by a baseball injury and has been hospitalized.",
"Recently, Lao Wang is studying asymmetric encryption algorithms.",
"The two-wheeled car is pretty good on the highway.",
"Next year, China will explore Mars."]
# 把样本按照训练时的方式转换成tfidf矩阵,才可以交给模型进行预测
bow = cv.transform(test_data)
test_data = tt.transform(bow)
pred_test_y = model.predict(test_data)
print(pred_test_y)
print(data.target_names)
"""
[2 3 1 4]
['misc.forsale', 'rec.motorcycles', 'rec.sport.baseball', 'sci.crypt', 'sci.space']
"""
① 优点
② 缺点