【SciKit-Learn学习笔记】6:朴素贝叶斯做文档分类并绘制混淆矩阵

版权声明:本文为博主原创学习笔记,如需转载请注明来源。 https://blog.csdn.net/SHU15121856/article/details/84590496

学习《scikit-learn机器学习》时的一些实践。


条件独立

朴素即指的是条件独立假设,假设n个特征之间不相关,则可据联合概率的条件展开式:
p ( C k ) P ( x C k ) = P ( C k , x ) = P ( x 1 , x 2 , . . , x n , C k ) = P ( x 1 x 2 , . . , x n , C k ) P ( x 2 , . . , x n , C k ) = P ( x 1 x 2 , . . , x n , C k ) P ( x 2 x 3 , . . , x n , C k ) P ( x 3 , . . , x n , C k ) . . . . . . = P ( x 1 x 2 , . . , x n , C k ) P ( x 2 x 3 , . . , x n , C k ) . . . P ( x n C k ) P ( C k ) p(C_k)P(\pmb{x}|C_k)=P(C_k,\pmb{x}) \\=P(x_1,x_2,..,x_n,C_k) \\=P(x_1|x_2,..,x_n,C_k)P(x_2,..,x_n,C_k) \\=P(x_1|x_2,..,x_n,C_k)P(x_2|x_3,..,x_n,C_k)P(x_3,..,x_n,C_k) \\...... \\=P(x_1|x_2,..,x_n,C_k)P(x_2|x_3,..,x_n,C_k)...P(x_n|C_k)P(C_k)
将其中的
P ( x i x i + 1 , x i + 2 , . . , x n , C k ) P(x_i|x_{i+1},x_{i+2},..,x_n,C_k)
变为
P ( x i C k ) P(x_i|C_k)
从而,朴素贝叶斯下的联合概率可展开为:
P ( x 1 , x 2 , . . , x n , C k ) = P ( x 1 C k ) P ( x 2 C k ) . . . P ( x n C k ) P ( C k ) P(x_1,x_2,..,x_n,C_k)=P(x_1|C_k)P(x_2|C_k)...P(x_n|C_k)P(C_k)
右侧的每一项都可从数据集中统计出来,因此可通过计算和比较联合概率来比较后验概率,以对类别做判断。

对于连续的特征值,可以通过区间划分形成离散值。但对于小数据集,这样做的偏差太大。可以通过考虑该特征作为随机变量的概率分布,计算其统计量并放入相应的概率分布函数模型中做计算。如计算方差 σ \sigma 和均值 μ \mu 便可得到正态分布的概率密度函数。

概率分布

概率分布是描述随机变量的概率规律。

PDF和PMF

概率密度函数(PDF)用于描述连续型随机变量在某个特定值的可能性,概率质量函数(PMF)用于描述离散型随机变量在某个特定值的可能性。

伯努利分布

零一分布两点分布,意在非黑即白:
f ( k ; p ) = p k ( 1 p ) 1 k k = 0 , 1 f(k;p)=p^k(1-p)^{1-k},其中k=0,1

类别分布

不止两种情况,即可能有多种情况:
f ( x p ) = i = 1 n p i x i x i = 1 x = i f(x|p)=\prod_{i=1}^{n}p_i^{x_i},其中x^i=1当且仅当类别x=i

二项式分布

即将伯努利实验(符合伯努利分布的实验)重复 n n 次,结果概率为 p p 的事件出现 k k 次的概率:
f ( k ; n , p ) = ( n k ) p k ( 1 p ) n k ( n k ) C n k f(k;n,p)=\binom{n}{k} p^k(1-p)^{n-k},其中\binom{n}{k}即C_n^k
当实验只做一次时,二项式分布退化为伯努利分布。

多项式分布

满足类别分布(即有多种情况)的实验,连续做n次后,每种类别出现的特定次数组合的概率分布情况。

x i x_i 表示类别 i i 出现的次数, p i p_i 表示类别 i i 在单次实验(即类别分布)中出现的概率。
f ( X , n , P ) = n ! i = 1 k x i ! i = 1 k p i x i f(\pmb{X},n,\pmb{P})=\frac{n!}{\prod_{i=1}^{k}x_i!}\prod_{i=1}^{k}p_i^{x_i}
作者给出一个易懂的理解,将后面的 i = 1 k p i x i \prod_{i=1}^{k}p_i^{x_i} 视为按特定顺序出现的所有类别的一个排列的概率,前面的系数将排列变成任意次序的组合。

多项式分布式二项式分布在类别数上的推广(两类变多类),也是类别分布在重复次数上的推广(一次变多次)。

TF-IDF

使用 T F × I D F TF \times IDF 衡量词在文档中的重要程度。

词频TF

特定词语在这篇文章中出现次数除以文档的词语总数。衡量词语对文档的重要程度,因为某词出现的频率较高则可能对该文档有标定意义

逆文档频率指数IDF

总文档数目除以包含该词语的文档数目,再取对数。表达词语的权重指数,因为某词的出现很广泛则很可能是一个泛用词,对特定的文档没有标定意义

朴素贝叶斯做文档分类

from sklearn.datasets import load_files
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.metrics import classification_report
from sklearn.metrics import confusion_matrix
from matplotlib import pyplot as plt

# 读取数据,这里的数据文件每一类在一个子目录中,子目录的名字即是文档的类别
news_train = load_files(r"E:\Data\code\datasets\mlcomp\379\train")
print("共{}文档分为{}类".format(len(news_train.data), len(news_train.target_names)))
# data中存的是所有文档,target中存的是类别号,若要知道类别名,在target_names中查询
print("0号文档的类别名:", news_train.target_names[news_train.target[0]])

共13180文档分为20类
0号文档的类别名: talk.politics.misc

# 转化为由TF-IDF表达的权重信息构成的向量
vectorizer = TfidfVectorizer(encoding='latin-1')
# 相当于先fit(完成语料分析,提取词典),再transform(把每篇文档转化为向量以构成矩阵)
X_train = vectorizer.fit_transform((d for d in news_train.data))
y_train = news_train.target
print("样本数:%d,特征数%d" % X_train.shape)
print("样本{}中的非零特征数为{}".format(news_train.filenames[0], X_train[0].getnnz()))

样本数:13180,特征数130274
样本E:\Data\code\datasets\mlcomp\379\train\talk.politics.misc\17860-178992中的非零特征数为108

# 多项式分布的朴素贝叶斯.其中alpha是平滑参数,越小越容易造成过拟合
clf = MultinomialNB(alpha=0.001)
clf.fit(X_train, y_train)
train_score = clf.score(X_train, y_train)
print("训练集得分:", train_score)

训练集得分: 0.9974203338391502

# 加载测试集
news_test = load_files(r"E:\Data\code\datasets\mlcomp\379\test")
print("共{}文档分为{}类".format(len(news_train.data), len(news_train.target_names)))

共13180文档分为20类

# 对测试集进行向量化,前面的语料分析和提取词典是基于训练集的,这里只调用transform
X_test = vectorizer.transform((d for d in news_test.data))
y_test = news_test.target
print("样本数:%d,特征数%d" % X_train.shape)

样本数:5648,特征数130274

# 尝试预测第一篇文档
pred = clf.predict(X_test[0])
print("预测为:{},实际是:{}".format(pred[0], news_test.target[0]))

预测为:7,实际是:7

# 在整个测试集上做预测
pred = clf.predict(X_test)
# 查看对每个类别的预测准确性
print("使用的分类器是", clf, "分类表现如下")
print(classification_report(y_test, pred, target_names=news_test.target_names))

在这里插入图片描述

# 生成混淆矩阵
cm = confusion_matrix(y_test, pred)
print("混淆矩阵:\n", cm)

如第1行第20列的13,即表示类别为0的文档有13个被分到类别19。对角线上的数字都是正确分类的(行列相同,即分类到自己)。
在这里插入图片描述

# 混淆矩阵可视化
plt.figure(figsize=(8, 8), dpi=144)
plt.title("混淆矩阵")
ax = plt.gca()  # Get Current Axes
ax.spines['right'].set_color('none')  # ax.spines是数据区域的边界
ax.spines['top'].set_color('none')
ax.spines['bottom'].set_color('none')
ax.spines['left'].set_color('none')
ax.xaxis.set_ticks_position('none')  # 删除轴上的刻度点
ax.yaxis.set_ticks_position('none')
ax.set_xticklabels([])
ax.set_yticklabels([])
plt.matshow(cm, fignum=1, cmap='gray')  # plt.matshow专门用于矩阵可视化
plt.colorbar()  # 添加渐变色条
plt.show()

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/SHU15121856/article/details/84590496