深入浅出python机器学习(3)Naive_Bayes

这章主要讲解朴素贝叶斯的分类操作,贝叶斯定理是概率论一个重要部分
由条件概率:P(A∩B) = P(A)P(B|A)=P(B)P(A|B)
和全概率公式 P(A)=P(AB1)+P(AB2)+...+P(ABn)),其中A与Bn的关系为交)。
推导出来:P(A|B)=P(B|A)*P(A)/P(B)
在生活中,我们也经常用到,这里就不展开数学推导了,有兴趣的同学可以百度,接下来我们跟着书里面的代码走起。
1、假设上一周的天气有4个特征:刮北风、闷热、多云、天气预报有雨

import numpy as np 
X = np.array([[0,1,0,1],
             [1,1,1,0],
             [0,1,1,0],
             [0,0,0,1],
             [0,1,1,0],
             [0,1,0,1],
             [1,0,0,1]])
y = np.array([0,1,1,0,1,0,0])

counts = {}  # 设置一个空字典,把分类统计进去
for label in np.unique(y):
    counts[label] = X[y == label].sum(axis = 0)
    
counts

{0: array([1, 2, 0, 4]), 1: array([1, 3, 3, 0])}
可以发现,预报有雨,但是都没有下雨,没有预报有雨的反而下雨了

# 使用贝努力贝叶斯进行拟合,因为这个符合二项式分布
from sklearn.naive_bayes import BernoulliNB
clf = BernoulliNB()
clf.fit(X,y)

# 如果今天是 没有北风、不闷热,没有预报有雨,但是多云,是否会下雨

today = [[0,0,1,0]]
today_predict = clf.predict(today)
if today_predict == 1:
    print('要下雨啦')
else:
    print('没事,不会下雨的')

print('概率:',clf.predict_proba(today))

要下雨啦
概率: [[0.13848881 0.86151119]]
可以发现有86%的可能会下雨
刚刚用的是二项式分布,我们再试试更复杂的数据集

##使用测试集生成数据,进行贝努利贝叶斯测试
from sklearn.datasets import make_blobs
from sklearn.naive_bayes import BernoulliNB
from sklearn.model_selection import train_test_split
# 生成500个样本,分成5类
X,y = make_blobs(n_samples = 500, centers = 5, random_state = 8)

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.25, random_state = 8)
# 调整参数移动分类界限
bl = BernoulliNB(binarize=3) 

bl.fit(X_train, y_train)
print('得分 = {:.3f}'.format(bl.score(X_test, y_test)))

得分 = 0.592
得分有点低,我们通过可视化来看看分类情况

# 用matplotlib 进行可视化
import matplotlib.pyplot as plt
%matplotlib inline

plt.figure(figsize=(20,10))

#限定X Y 轴的最大值和最小值
x_min, x_max = X[:,0].min() - 1, X[:,0].max() + 1
y_min, y_max = X[:,1].min() - 1, X[:,1].max() + 1

#用不同的颜色表示不同的类别
xx, yy = np.meshgrid(np.arange(x_min, x_max,0.02),
                    np.arange(y_min,y_max,0.02))
z = bl.predict(np.c_[xx.ravel(), yy.ravel()]).reshape(xx.shape)
plt.pcolormesh(xx,yy,z,cmap = plt.cm.Pastel1)

#将训练集和测试集用散点图表示
plt.scatter(X_train[:,0], X_train[:,1], c = y_train, cmap = plt.cm.cool, edgecolor = 'k')
plt.scatter(X_test[:,0], X_test[:,1], c = y_test, cmap = plt.cm.cool, edgecolor = 'k',marker = '*',s = 150)

plt.xlim(x_min, x_max)
plt.ylim(y_min, y_max)
plt.title('Classifier: BernoulliNB')
plt.show()
image.png

可以发现分类界限就在 3 ,可见贝努利贝叶斯不合适分类复杂的数据
2、我们接下来用高斯朴素贝叶斯来拟合一下,高斯朴素贝叶斯适用于 当特征值符合高斯正态分布的数据

## 高斯朴素贝叶斯
from sklearn.naive_bayes import GaussianNB
gnb = GaussianNB()
gnb.fit(X_train, y_train)
print('得分:', gnb.score(X_test, y_test))
# 进行可视化
z1 = gnb.predict(np.c_[xx.ravel(),yy.ravel()]).reshape(xx.shape)
plt.figure(figsize = (10,8))
plt.pcolormesh(xx, yy, z1, cmap = plt.cm.Pastel1)
plt.scatter(X_train[:,0], X_train[:,1], c = y_train, cmap = plt.cm.cool, edgecolor = 'k')
plt.scatter(X_test[:,0], X_test[:,1], c = y_test, cmap = plt.cm.cool, edgecolor = 'k', marker = '*', s = 150)

plt.title('Classifier : GaussianNB')
plt.show()

得分: 0.968


image.png

可以发现高斯朴素贝叶斯的拟合效果会好很多,因为在现实生活中,很多特征也都是符合正态分布的。
3、接下来我们看看另一种贝叶斯模型:多项式朴素贝叶斯
什么是多项式分布呢,0和1就是二项式分布,那像骰子一样6个数的,就是多项式分布了,不过需要注意,多项式朴素贝叶斯的特征值需是非负值。

# 使用多项式朴素贝叶斯
from sklearn.naive_bayes import MultinomialNB

# 使用多项式朴素贝叶斯,需要将 X 值转化为 非负值 使用自带的 MinMaxScaler 对原始数据进行预处理
from sklearn.preprocessing import MinMaxScaler

scaler = MinMaxScaler()
scaler.fit(X_train)
X_train_scaled = scaler.transform(X_train)
X_test_scaled = scaler.transform(X_test)

mnb = MultinomialNB()
mnb.fit(X_train_scaled, y_train)
mnb_scores = mnb.score(X_test_scaled, y_test)

print('多项式朴素贝叶斯得分:{:.3f}'.format(mnb_scores))
# 多项式朴素贝叶斯可视化
z = mnb.predict(np.c_[xx.ravel(),yy.ravel()]).reshape(xx.shape)
# 区域分颜色
plt.figure(figsize = (10,8))
plt.pcolormesh(xx,yy,z,cmap = plt.cm.Pastel1)
#画散点
plt.scatter(X_train[:,0], X_train[:,1], c = y_train, cmap = plt.cm.cool, edgecolor = 'k')
plt.scatter(X_test[:,0], X_test[:,1], c = y_test, cmap = plt.cm.cool,marker = '*', s = 150, edgecolor = 'k')

plt.title('Classifier MultinomialNB')
plt.show()

多项式朴素贝叶斯得分:0.320


image.png

可见多项式分布也不适合以上的样本数据。
多项式朴素贝叶斯只适合用于对非负离散型数值进行分类,典型例子为 转化为向量后的文本数据进行分类,后面也会有文章讲到。
4、实战:肿瘤分类

from sklearn.datasets import load_breast_cancer
cancer = load_breast_cancer()
print(cancer.keys())
print('标签:',cancer.target_names,'\n 特征',cancer.feature_names)

dict_keys(['data', 'target', 'target_names', 'DESCR', 'feature_names', 'filename'])
标签: ['malignant' 'benign']
特征 ['mean radius' 'mean texture' 'mean perimeter' 'mean area'
'mean smoothness' 'mean compactness' 'mean concavity'
'mean concave points' 'mean symmetry' 'mean fractal dimension'
'radius error' 'texture error' 'perimeter error' 'area error'
'smoothness error' 'compactness error' 'concavity error'
'concave points error' 'symmetry error' 'fractal dimension error'
'worst radius' 'worst texture' 'worst perimeter' 'worst area'
'worst smoothness' 'worst compactness' 'worst concavity'
'worst concave points' 'worst symmetry' 'worst fractal dimension']
以上都是一些医学方面的描述。
因为是连续型数据,推荐使用高斯朴素贝叶斯,我们也可以用三个模型一起测试一下

from sklearn.naive_bayes import MultinomialNB,BernoulliNB,GaussianNB
from sklearn.model_selection import train_test_split

# 拆分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(cancer.data, cancer.target, test_size = 0.25, random_state = 8)

#可以看看训练集和测试集数据的形状
print('训练集数据情况:', X_train.shape)
print('测试集数据情况:', X_test.shape)
#顺便看看有没有非负值
print(cancer.data[cancer.data < 0])

训练集数据情况: (426, 30)
测试集数据情况: (143, 30)
[]
可见没有非负值,无需转化特征值

# 使用多项式朴素贝叶斯进行拟合
mnb = MultinomialNB()
mnb.fit(X_train, y_train)

# 查看得分情况
print('训练集得分:{:.3f}'.format(mnb.score(X_train, y_train)))
print('测试集得分:{:.3f}'.format(mnb.score(X_test, y_test)))

训练集得分:0.899
测试集得分:0.874

#使用贝努利贝叶斯进行拟合
bnb = BernoulliNB()
bnb.fit(X_train, y_train)

# 查看得分情况
print('训练集得分:{:.3f}'.format(bnb.score(X_train, y_train)))
print('测试集得分:{:.3f}'.format(bnb.score(X_test, y_test)))

训练集得分:0.638
测试集得分:0.594

#使用高斯朴素贝叶斯进行拟合
gnb = GaussianNB()
gnb.fit(X_train, y_train)

# 查看得分情况
print('训练集得分:{:.3f}'.format(gnb.score(X_train, y_train)))
print('测试集得分:{:.3f}'.format(gnb.score(X_test, y_test)))

训练集得分:0.948
测试集得分:0.937
果然还是高斯朴素贝叶斯的拟合效果要好
现在随机抽取一个样本进行测试,书本抽的是312,我这里抽取第300个

sample_one = cancer.data[300]
print('贝努利贝叶斯得出的结果是:',bnb.predict([sample_one]))
print('多项式朴素贝叶斯得出的结果是:',mnb.predict([sample_one]))
print('高斯朴素贝叶斯得出的结果是:',gnb.predict([sample_one]))
print('真实结果是:',cancer.target[300])

贝努利贝叶斯得出的结果是: [1]
多项式朴素贝叶斯得出的结果是: [0]
高斯朴素贝叶斯得出的结果是: [0]
真实结果是: 0
5、学习曲线

from sklearn.model_selection import learning_curve, ShuffleSplit
# 定义一个函数绘制学习曲线
def plot_learning_curve(estimator, title, X, y, ylim = None, cv = None, n_jobs = 1, train_sizes = np.linspace(0.1,1,5)):
    plt.figure(figsize = (10,8))
    plt.title(title)
    if ylim is not None:
        plt.ylim(*ylim)
    # 设置轴标签
    plt.rcParams['font.sans-serif']=['FangSong'] 
    plt.rcParams['axes.unicode_minus'] = False
    plt.xlabel('测试样本')
    plt.ylabel('得分')
    
    train_sizes, train_scores, test_scores = learning_curve(estimator, X, y, cv = cv, n_jobs = n_jobs, train_sizes = train_sizes)
    train_scores_mean = np.mean(train_scores, axis = 1)
    test_scores_mean = np.mean(test_scores,axis = 1)
    
    plt.grid()
    
    plt.plot(train_sizes,train_scores_mean, 'o-', c = 'r', label = '训练集得分')
    plt.plot(train_sizes,test_scores_mean, 'o-', c = 'g', label = '交叉验证得分')
    
    plt.legend(loc = 'best')
    return plt

title = '高斯朴素贝叶斯学习曲线'
cv = ShuffleSplit(n_splits = 10, test_size = 0.2, random_state = 0)
estimator = GaussianNB()
#调用函数
plot_learning_curve(estimator, title, X, y, ylim = (0.9,1.01), cv = cv, n_jobs = 4)
plt.show()
image.png
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,744评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,505评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,105评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,242评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,269评论 6 389
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,215评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,096评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,939评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,354评论 1 311
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,573评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,745评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,448评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,048评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,683评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,838评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,776评论 2 369
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,652评论 2 354

推荐阅读更多精彩内容