一、朴素贝叶斯
(一)、什么是贝叶斯
导入贝叶斯:
from sklearn.naive_bayes import *
(二)、多条件的贝叶斯
-
公式:
-
案例:
-
多个参数得预测:
- 独立性假设,每个属性参数时独立的,互不影响。
- 真实情况中,不存在绝对的不相互影响的情况
- 我们为了减少计算的复杂的程度,我们假设他们之间是相互独立的
- 这种方式就叫做----(朴素贝叶斯 )
-
朴素贝叶斯与贝叶斯公式对比:
(三)、朴素贝叶斯代码
-
案例:
如果一个未婚男士具有以上的特点,请问女生会不会嫁给他?
-
计算:
上面多个属性使用贝叶斯来计算概率是不好计算的。
所以我们使用朴素贝叶斯--假设属性之间是相互独立的。
-
多个特征集于一身本身就是小概率的事件。
单独提取特征,进行概率的计算,再进行累成、
前提是所有的属性都是相互独立的。
我们在进行判断的时候,算出嫁与不嫁的概率比较其大小---得出结果。
不嫁的计算方式与上面是类似的,下面的额代码会做展示。
(四、)朴素贝叶斯常用的三种模型
朴素贝叶斯基础上+独立性的假设
朴树贝叶斯分三种:
-
(1)高斯分布朴素贝叶斯--》正太分布--GaussianNB
如果我们的特征数据,服从正太分布,我们就是用高斯分布的朴素贝叶斯,效果就很好。
-
(2)多项式分布朴素贝叶斯--MultinomialNB。
多项分布是二项分布的推广。
-
多项分布--密度函数
-
(3 )伯努力分布朴素贝叶斯--BernoulliNB。
伯努力分布也叫做二项分布(即0-1分布)
实验的结果只有两个--比如抛硬币(结果只有两个)
(五、垃圾短息的分类--如何将文本数量化
)
- 量化导包:
from sklearn.feature_extraction.text import CountVectorizer
(一、稀松矩阵)
- 只保留非零数据的索引信息
- 用处---减少内存的存储量
-
稀松矩阵如何转换回去:
(二、稠密矩阵)
- 就是常规的矩阵
(三、两种矩阵的对比)
- 上面讲解这两种矩阵的对比,主要是文本数据使用feature_extraction.text 量化后,为什么转换成稀松矩阵?
- 就一个作用----减少内存的占用量
import warnings
warnings.filterwarnings("ignore")
import numpy as np
from sklearn import datasets
from sklearn.naive_bayes import GaussianNB,BaseDiscreteNB,MultinomialNB
# 朴素贝叶斯
# 朴素贝叶斯---就是假设属性之间是相互独立的
# 相互不影响的
import matplotlib.pyplot as plt
# 朴素贝叶斯实现垃圾短信的识别
x,y=datasets.load_iris(True)
# 数据x中,花萼的长宽的属性,自然属性都是正太分布的。
from sklearn.model_selection import train_test_split
x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.2,random_state=1028)
plt.hist(x[:,0],bins=20)
# 画出第一个属性的图形--可以看出他们像正态分布
(array([ 4., 5., 7., 16., 9., 5., 13., 14., 10., 6., 10., 16., 7.,
11., 4., 2., 4., 1., 5., 1.]),
array([4.3 , 4.48, 4.66, 4.84, 5.02, 5.2 , 5.38, 5.56, 5.74, 5.92, 6.1 ,
6.28, 6.46, 6.64, 6.82, 7. , 7.18, 7.36, 7.54, 7.72, 7.9 ]),
<a list of 20 Patch objects>)
plt.hist(x[:,1],bins=20)
# 画出第二个属性的图形--可以看出他们像正态分布
(array([ 1., 3., 4., 3., 8., 14., 14., 10., 26., 11., 19., 12., 6.,
4., 9., 2., 1., 1., 1., 1.]),
array([2. , 2.12, 2.24, 2.36, 2.48, 2.6 , 2.72, 2.84, 2.96, 3.08, 3.2 ,
3.32, 3.44, 3.56, 3.68, 3.8 , 3.92, 4.04, 4.16, 4.28, 4.4 ]),
<a list of 20 Patch objects>)
plt.hist(x[:,2],bins=20)
# 画出第三个属性的图形--可以看出他们像正态分布
(array([ 4., 33., 11., 2., 0., 0., 1., 2., 3., 5., 12., 14., 12.,
17., 6., 12., 7., 4., 2., 3.]),
array([1. , 1.295, 1.59 , 1.885, 2.18 , 2.475, 2.77 , 3.065, 3.36 ,
3.655, 3.95 , 4.245, 4.54 , 4.835, 5.13 , 5.425, 5.72 , 6.015,
6.31 , 6.605, 6.9 ]),
<a list of 20 Patch objects>)
plt.hist(x[:,3],bins=20)
# 画出第四个属性的图形--这个不是很像正态分布,但是这个数据中三个都像所有,
# 用高斯分布是最好的。
(array([34., 7., 7., 1., 1., 0., 0., 7., 3., 5., 21., 12., 4.,
2., 12., 11., 6., 3., 8., 6.]),
array([0.1 , 0.22, 0.34, 0.46, 0.58, 0.7 , 0.82, 0.94, 1.06, 1.18, 1.3 ,
1.42, 1.54, 1.66, 1.78, 1.9 , 2.02, 2.14, 2.26, 2.38, 2.5 ]),
<a list of 20 Patch objects>)
高斯分布
# 使用到的高斯分布
gNB=GaussianNB(priors=[1.0,0,0])
# priors=[1.0,0,0] priors指定预测类别的权重
# priors如果不指定,默认是根据样本的权重来的。
gNB.fit(x_train,y_train)
gNB.score(x_test,y_test)
0.23333333333333334
gNB.class_prior_
array([0.35833333, 0.29166667, 0.35 ])
len(y_train)
120
count=[]
for i in range(3):
count.append((y_train==i).sum())
count=np.asarray(count)
count/count.sum()
array([0.35833333, 0.29166667, 0.35 ])
伯努力分布
bNB=BernoulliNB()
bNB.fit(x_train,y_train)
bNB.score(x_test,y_test)
0.23333333333333334
np.e**(bNB.class_log_prior_)
array([0.35833333, 0.29166667, 0.35 ])
数据是正泰分布的,使用二项分布是不好的额。
多项分布
mNB=MultinomialNB()
mNB.fit(x_train,y_train)
mNB.score(x_test,y_test)
0.5
正泰分布的数据使用多项分布也是不好的。
(四、短信处理--文本数量化)
import numpy as np
import pandas as pd
from sklearn.naive_bayes import GaussianNB,BernoulliNB,MultinomialNB
from sklearn.model_selection import train_test_split
from scipy import sparse
# feature_selection 特征选择!
# feature_extraction 特征提取,萃取
# 土壤中,炼铁,这个过程类比 萃取
# 统计词频!通过词频,判断类别,判断短信是否是垃圾短信
# free、phone、获奖、优惠
from sklearn.feature_extraction.text import CountVectorizer
# 短信数据
sms = pd.read_csv('./SMSSpamCollection.csv',sep = '\t',header= None)
sms.rename({0:'label',1:'message'},axis = 1,inplace = True)
display(sms.shape,sms.head())
(5572, 2)
X = sms[['message']]# 机器学习,要求数据必须是二维的!!!
y = sms['label']
display(type(X),type(y))
display(X.head(),y.head())
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size = 0.2)
pandas.core.frame.DataFrame
pandas.core.series.Series
# 我们的短信内容是文本,数据
# 文本数据,计算机,可以进行计算吗?概率计算吗?
gNB = GaussianNB()
gNB.fit(X_train,y_train)
# 计算机中的计算,都是数字化的计算,KNN,LR,决策树,贝叶斯……
# 现在的数据是str,不能计算,不能计算距离,不能计算概率,不能构造决策
# 进行量化
# 将str类型的数据,数量化,数值化
-------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-12-0f6a1b7ae1aa> in <module>
2 # 文本数据,计算机,可以进行计算吗?概率计算吗?
3 gNB = GaussianNB()
----> 4 gNB.fit(X_train,y_train)
d:\python3.7.4\lib\site-packages\sklearn\naive_bayes.py in fit(self, X, y, sample_weight)
207 y = column_or_1d(y, warn=True)
208 return self._partial_fit(X, y, np.unique(y), _refit=True,
--> 209 sample_weight=sample_weight)
210
211 def _check_X(self, X):
d:\python3.7.4\lib\site-packages\sklearn\naive_bayes.py in _partial_fit(self, X, y, classes, _refit, sample_weight)
358 self : object
359 """
--> 360 X, y = check_X_y(X, y)
361 if sample_weight is not None:
362 sample_weight = _check_sample_weight(sample_weight, X)
d:\python3.7.4\lib\site-packages\sklearn\utils\validation.py in check_X_y(X, y, accept_sparse, accept_large_sparse, dtype, order, copy, force_all_finite, ensure_2d, allow_nd, multi_output, ensure_min_samples, ensure_min_features, y_numeric, warn_on_dtype, estimator)
737 ensure_min_features=ensure_min_features,
738 warn_on_dtype=warn_on_dtype,
--> 739 estimator=estimator)
740 if multi_output:
741 y = check_array(y, 'csr', force_all_finite=True, ensure_2d=False,
d:\python3.7.4\lib\site-packages\sklearn\utils\validation.py in check_array(array, accept_sparse, accept_large_sparse, dtype, order, copy, force_all_finite, ensure_2d, allow_nd, ensure_min_samples, ensure_min_features, warn_on_dtype, estimator)
513 array = array.astype(dtype, casting="unsafe", copy=False)
514 else:
--> 515 array = np.asarray(array, order=order, dtype=dtype)
516 except ComplexWarning:
517 raise ValueError("Complex data not supported\n"
d:\python3.7.4\lib\site-packages\numpy\core\_asarray.py in asarray(a, dtype, order)
83
84 """
---> 85 return array(a, dtype, copy=False, order=order)
86
87
ValueError: could not convert string to float: 'Lol no. Just trying to make your day a little more interesting'
文本数据的量化
cv = CountVectorizer()#stop-words 停用词
# 主要目的,节省内存空间
# 量化
X = cv.fit_transform(sms['message'])
display(X)
print(X)
# 保存文件大小是147kb
sparse.save_npz('./sms.npz',X)
# 保存文件大小388M
# 普通numpy矩阵,稠密矩阵
np.savez('./sms2.npz',X.toarray())
<5572x8713 sparse matrix of type '<class 'numpy.int64'>'
with 74169 stored elements in Compressed Sparse Row format>
(0, 3571) 1
(0, 8084) 1
(0, 4374) 1
(0, 5958) 1
(0, 2338) 1
(0, 1316) 1
(0, 5571) 1
(0, 4114) 1
(0, 1767) 1
(0, 3655) 1
(0, 8548) 1
(0, 4501) 1
(0, 1765) 1
(0, 2061) 1
(0, 7694) 1
(0, 3615) 1
(0, 1082) 1
(0, 8324) 1
(1, 5538) 1
(1, 4537) 1
(1, 4342) 1
(1, 8450) 1
(1, 5567) 1
(2, 4114) 1
(2, 3373) 1
: :
(5570, 4245) 1
(5570, 8371) 1
(5570, 1097) 1
(5570, 4642) 1
(5570, 7089) 1
(5570, 3323) 1
(5570, 7674) 1
(5570, 1451) 1
(5570, 5367) 1
(5570, 2606) 1
(5570, 8120) 1
(5570, 1794) 1
(5570, 7099) 1
(5570, 2905) 1
(5570, 3489) 1
(5570, 1802) 1
(5570, 3709) 1
(5570, 4188) 1
(5570, 914) 1
(5570, 1561) 1
(5571, 7806) 1
(5571, 5276) 1
(5571, 4253) 2
(5571, 7938) 1
(5571, 6548) 1
# 第一条短信的量化数据
'''Go until jurong point, crazy.. Available only in bugis n great world la e buffet...
Cine there got amore wat...'''
print(X[:1])
(0, 3571) 1
(0, 8084) 1
(0, 4374) 1
(0, 5958) 1
(0, 2338) 1
(0, 1316) 1
(0, 5571) 1
(0, 4114) 1
(0, 1767) 1
(0, 3655) 1
(0, 8548) 1
(0, 4501) 1
(0, 1765) 1
(0, 2061) 1
(0, 7694) 1
(0, 3615) 1
(0, 1082) 1
(0, 8324) 1
'''Rofl. Its true to its name'''
print(X[-1])
(0, 7806) 1
(0, 5276) 1
(0, 4253) 2
(0, 7938) 1
(0, 6548) 1
vc = cv.vocabulary_
vc['its']
4253
vc['to']
7806
# scipy中提供了方法
# 稀松矩阵、稠密矩阵 对比
a = np.random.randint(0,10,size = (10,5))
a[a >=3] = 0
s = sparse.csc_matrix(a)
display(a,s)
print(s)
array([[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 1, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 1, 2, 0, 0],
[1, 0, 0, 0, 2],
[2, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0]])
# 此时X是稀松矩阵
# 稀松矩阵也可以进行拆分
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size = 0.2,random_state = 1187)
X_train
<4457x8713 sparse matrix of type '<class 'numpy.int64'>'
with 59438 stored elements in Compressed Sparse Row format>
%%time
gNB = GaussianNB() # 高斯分布,是正太分布,数据属性必须是稠密矩阵
gNB.fit(X_train.toarray(),y_train)
print('高斯分布',gNB.score(X_test.toarray(),y_test))
高斯分布 0.8914798206278027
Wall time: 2.03 s
%%time
# 稀松矩阵,计算优势,内存中占有量很小
bNB = BernoulliNB() # 二项分布,数据可以稀松的,准确率提升了很多,计算时间大大缩短
bNB.fit(X_train,y_train)
print('伯努利:',bNB.score(X_test,y_test))
伯努利: 0.9730941704035875
Wall time: 56.1 ms
%%time
mNB = MultinomialNB()
mNB.fit(X_train,y_train)
print('多项式分布:',mNB.score(X_test,y_test))
多项式分布: 0.979372197309417
Wall time: 23.6 ms
# 自然语言处理,用词分布,不是正太分布
import matplotlib.pyplot as plt
dX = X.toarray()
# dX是稠密矩阵, 第一列属性一(单词),第二列属性二(单词),……
dX
array([[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]], dtype=int64)
# 不是正太分布了,二项分布
_ = plt.hist(dX[:,1024])