【Python】机器学习笔记03-朴素贝叶斯(Naive Bays)

本文的参考资料:《Python数据科学手册》
本文的源代上传到了Gitee上;

本文用到的包:

%matplotlib inline
import pandas as pd
import seaborn as sns
from matplotlib.pylab import *

from sklearn.naive_bayes import GaussianNB, MultinomialNB

from sklearn.datasets import make_blobs, fetch_20newsgroups
from sklearn.metrics import accuracy_score, confusion_matrix
from sklearn.feature_extraction.text import TfidfVectorizer

sns.set()
plt.rc('font', family='SimHei')
plt.rc('axes', unicode_minus=False)

朴素贝叶斯分类(Naive Bayes)

朴素贝叶斯分类是一种基于贝叶斯定理的,有监督的机器学习算法,用于分类任务,通常适用于高维度的数据集,因为运行速度快、可调参数少,非常适合为分类问题提供快速粗糙的解决方案。

贝叶斯定理

P ( L ∣ 特 征 ) = P ( 特 征 ∣ L ) P ( L ) P ( 特 征 ) P(L|特征) = \frac{P(特征|L)P(L)}{P(特征)} P(L)=P()P(L)P(L)

我们需要做的就是寻找一个能够计算每一个 P ( L ∣ 特 征 ) P(L|特征) P(L)的模型,这样的模型称为生成模型

高斯朴素贝叶斯

高斯朴素贝叶斯假设每一个标签的数据都满足高斯分布,且标签之间线性无关(协方差=0),高斯朴素贝叶斯在sklearn中由GaussianNB类实现;

x_train, y_train = make_blobs(
    n_samples=300,
    n_features=2,
    centers=2,
    cluster_std=[1.5, 2.5],
    random_state=2
)

fig, axs = plt.subplots(1, 2, figsize=(20, 10))
ax_train = axs[0]  # type: plt.Axes
ax_test = axs[1]  # type: plt.Axes

ax_train.scatter(x=x_train[:, 0], y=x_train[:, 1], c=y_train, s=25, cmap=plt.cm.get_cmap('winter', lut=2))
ax_train.set_title('训练集')
ax_train.set_xlim(-6, 6)
ax_train.set_xticks(range(-6, 6 + 1, 2))
ax_train.set_ylim(-13, 8)
ax_train.set_yticks(range(-14, 8 + 1, 2))
fig.colorbar(
    mappable=plt.cm.ScalarMappable(cmap=plt.cm.get_cmap('winter', lut=2)),
    ax=ax_train,
    ticks=[1, 0]
)

x_test = np.zeros((2000, 2))
x_test[:, 0] = np.random.rand(2000) * 12 - 6
x_test[:, 1] = np.random.rand(2000) * 22 - 14

model = GaussianNB()
model.fit(x_train, y_train)
y_test = model.predict(x_test)
y_prob = model.predict_proba(x_test)  # 每个样例属于每个标签的概率
y_size = np.zeros(2000)
y_size[y_test == 1] = (2 ** y_prob[:, 1][y_test == 1]) * 10
y_size[y_test == 0] = (2 ** y_prob[:, 0][y_test == 0]) * 10

ax_test.scatter(x=x_test[:, 0], y=x_test[:, 1], c=y_test, s=y_size, cmap=plt.cm.get_cmap('winter', lut=2))
ax_test.set_title('拟合随机数据结果')
ax_test.set_xlim(-6, 6)
ax_test.set_xticks(range(-6, 6 + 1, 2))
ax_test.set_ylim(-13, 8)
ax_test.set_yticks(range(-14, 8 + 1, 2))
fig.colorbar(
    mappable=plt.cm.ScalarMappable(cmap=plt.cm.get_cmap('winter', lut=2)),
    ax=ax_test,
    ticks=[0, 1],
)

效果:

在这里插入图片描述

多项式朴素贝叶斯

多项式朴素贝叶斯假设样本中的每一个特征都是服从多项式分布的,适用于处理“出现次数”或者是“出现比例”这样的特征;
这里使用sklearn提供的英语新闻语料库来演示使用多项式贝叶斯进行文本分类(使用sklearn内置工具计算词频逆文档频率);
sklearn中,多项式朴素贝叶斯由MultinomialNB类实现;

加载训练数据并查看训练数据的情况:

text_data = fetch_20newsgroups()
print('新闻组:')
for i, j in enumerate(text_data.target_names):
    print(f'{j:<25}', end=('\n' if (i + 1) % 3 == 0 else ' | '))
print('\n')

categories_selected = ['talk.religion.misc', 'soc.religion.christian', 'sci.space', 'comp.graphics']  # 需要用到的四个组
text_train = fetch_20newsgroups(subset='train', categories=categories_selected)
text_test = fetch_20newsgroups(subset='test', categories=categories_selected)

输出:

新闻组:
alt.atheism               | comp.graphics             | comp.os.ms-windows.misc  
comp.sys.ibm.pc.hardware  | comp.sys.mac.hardware     | comp.windows.x           
misc.forsale              | rec.autos                 | rec.motorcycles          
rec.sport.baseball        | rec.sport.hockey          | sci.crypt                
sci.electronics           | sci.med                   | sci.space                
soc.religion.christian    | talk.politics.guns        | talk.politics.mideast    
talk.politics.misc        | talk.religion.misc        | 

训练模型、进行测试、输出正确率:

vec = TfidfVectorizer().fit(text_train.data)
model = MultinomialNB()

model.fit(vec.transform(text_train.data), text_train.target)
text_res = model.predict(vec.transform(text_test.data))

print(f'多项式朴素贝叶斯应用于文本分类的准确率:{accuracy_score(text_test.target, text_res) * 100:0.3f}%')

输出结果:

多项式朴素贝叶斯应用于文本分类的准确率:80.168%

使用sklearn提供的工具计算混淆矩阵,并使用seaborn进行可视化:

mat = confusion_matrix(text_test.target, text_res)
plt.figure(figsize=(10, 10))
sns.heatmap(
    mat.T,
    square=True,
    annot=True,
    fmt='d',
    cbar=False,
    xticklabels=text_train.target_names,
    yticklabels=text_train.target_names,
    cmap='Greens',
)
plt.xlabel('正确分类')
plt.ylabel('模型预测')

结果:

在这里插入图片描述

通过混淆矩阵可以看到,模型能够很好的分辨计算机新闻与宇宙新闻,但是不能很好的分辨宗教新闻与基督教新闻;

完整代码(Jupyter Notebook)

#%%

%matplotlib inline
import pandas as pd
import seaborn as sns
from matplotlib.pylab import *

from sklearn.naive_bayes import GaussianNB, MultinomialNB

from sklearn.datasets import make_blobs, fetch_20newsgroups
from sklearn.metrics import accuracy_score, confusion_matrix
from sklearn.feature_extraction.text import TfidfVectorizer

sns.set()
plt.rc('font', family='SimHei')
plt.rc('axes', unicode_minus=False)

#%% md

# 朴素贝叶斯分类

朴素贝叶斯分类通常适用于高维度的数据集,因为运行速度快、可调参数少,非常适合为分类问题提供快速粗糙的解决方案。

## 贝叶斯定理

$$ P(L|特征) = \frac{P(特征|L)P(L)}{P(特征)} $$

我们需要做的就是寻找一个能够计算每一个$P(L|特征)$的模型,这样的模型称为**生成模型**## 高斯朴素贝叶斯

高斯朴素贝叶斯假设每一个标签的数据都满足高斯分布,且标签之间线性无关(协方差=0)。

#%%

x_train, y_train = make_blobs(
    n_samples=300,
    n_features=2,
    centers=2,
    cluster_std=[1.5, 2.5],
    random_state=2
)

fig, axs = plt.subplots(1, 2, figsize=(20, 10))
ax_train = axs[0]  # type: plt.Axes
ax_test = axs[1]  # type: plt.Axes

ax_train.scatter(x=x_train[:, 0], y=x_train[:, 1], c=y_train, s=25, cmap=plt.cm.get_cmap('winter', lut=2))
ax_train.set_title('训练集')
ax_train.set_xlim(-6, 6)
ax_train.set_xticks(range(-6, 6 + 1, 2))
ax_train.set_ylim(-13, 8)
ax_train.set_yticks(range(-14, 8 + 1, 2))
fig.colorbar(
    mappable=plt.cm.ScalarMappable(cmap=plt.cm.get_cmap('winter', lut=2)),
    ax=ax_train,
    ticks=[1, 0]
)

x_test = np.zeros((2000, 2))
x_test[:, 0] = np.random.rand(2000) * 12 - 6
x_test[:, 1] = np.random.rand(2000) * 22 - 14

model = GaussianNB()
model.fit(x_train, y_train)
y_test = model.predict(x_test)
y_prob = model.predict_proba(x_test)  # 每个样例属于每个标签的概率
y_size = np.zeros(2000)
y_size[y_test == 1] = (2 ** y_prob[:, 1][y_test == 1]) * 10
y_size[y_test == 0] = (2 ** y_prob[:, 0][y_test == 0]) * 10

ax_test.scatter(x=x_test[:, 0], y=x_test[:, 1], c=y_test, s=y_size, cmap=plt.cm.get_cmap('winter', lut=2))
ax_test.set_title('拟合随机数据结果')
ax_test.set_xlim(-6, 6)
ax_test.set_xticks(range(-6, 6 + 1, 2))
ax_test.set_ylim(-13, 8)
ax_test.set_yticks(range(-14, 8 + 1, 2))
fig.colorbar(
    mappable=plt.cm.ScalarMappable(cmap=plt.cm.get_cmap('winter', lut=2)),
    ax=ax_test,
    ticks=[0, 1],
)

#%% md

## 多项式朴素贝叶斯

多项式朴素贝叶斯假设样本中的每一个特征都是服从多项式分布的,适用于处理“出现次数”或者是“出现比例”这样的特征;
这里使用sklearn提供的英语新闻语料库来演示使用多项式贝叶斯进行文本分类;

#%%

text_data = fetch_20newsgroups()
print('新闻组:')
for i, j in enumerate(text_data.target_names):
    print(f'{j:<25}', end=('\n' if (i + 1) % 3 == 0 else ' | '))
print('\n')

categories_selected = ['talk.religion.misc', 'soc.religion.christian', 'sci.space', 'comp.graphics']
text_train = fetch_20newsgroups(subset='train', categories=categories_selected)
text_test = fetch_20newsgroups(subset='test', categories=categories_selected)

vec = TfidfVectorizer().fit(text_train.data)
model = MultinomialNB()

model.fit(vec.transform(text_train.data), text_train.target)
text_res = model.predict(vec.transform(text_test.data))

print(f'多项式朴素贝叶斯应用于文本分类的准确率:{accuracy_score(text_test.target, text_res) * 100:0.3f}%')

mat = confusion_matrix(text_test.target, text_res)
plt.figure(figsize=(10, 10))
sns.heatmap(
    mat.T,
    square=True,
    annot=True,
    fmt='d',
    cbar=False,
    xticklabels=text_train.target_names,
    yticklabels=text_train.target_names,
    cmap='Greens',
)
plt.xlabel('正确分类')
plt.ylabel('模型预测')

#%% md

通过混淆矩阵可以看到,模型能够很好的分辨计算机新闻与宇宙新闻,但是不能很好的分辨宗教新闻与基督教新闻;
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值