带你从入门到精通——机器学习(八. 朴素贝叶斯算法)
当我们有一个函数y = f(x)时,若有结果x0 = argmax(f(x)),则表示当函数f(x)取x = x0的时候,得到f(x)在取值范围内的最大值,上式表示朴素贝叶斯法会将样本分到后验概率最大的类别中。上式中x代表特征的取值,Y=Ck代表Ck这个类别,j代表第j个特征,分母是全概率公式,对于所有类别都是一样的,对结果没有影响,通过。:是指在考虑了新数据或证据之后,对事件概率的重新评估。其中
建议先阅读我之前的博客,掌握一定的机器学习前置知识后再阅读本文,链接如下:
带你从入门到精通——机器学习(一. 机器学习概述)-CSDN博客
带你从入门到精通——机器学习(二. KNN算法)-CSDN博客
带你从入门到精通——机器学习(三. 线性回归)-CSDN博客
带你从入门到精通——机器学习(四. 逻辑回归)-CSDN博客
带你从入门到精通——机器学习(六. 集成学习)-CSDN博客
带你从入门到精通——机器学习(七. 特征降维)-CSDN博客
目录
8 朴素贝叶斯算法
8.1 概率相关知识
概率:一件事情发生的可能性。
条件概率:表示事件A在另外一个事件B已经发生条件下的发生概率,表示为P(A|B)。
联合概率:表示多个条件同时发生的概率,表示P(AB) = P(A) * P(B|A) = P(B) * P(A|B)。
相互独立:如果P(AB) = P(A) * P(B),则称事件A与事件B相互独立。
基于联合概率和条件概率的相关公式,即可推出贝叶斯公式,其具体表达式如下:
其中,P(C) 表示C发生的概率,一般是目标值,P(W|C)表示C条件W出现的概率,P(W)表示W出现的概率。
全概率公式:若事件A1,A2,…构成一个完备事件组(即它们两两互不相容,且其和为全集)且都有正概率,则对任意一个事件B,有如下公式成立:
P(B) = P(BA1) + P(BA2) +...+ P(BAn) = P(B|A1)P(A1) + P(B|A2)P(A2) + ... + P(B|An)P(An)
先验概率:是指在没有考虑新数据或证据之前,基于历史数据、专家知识或直觉估计的概率。它反映了我们对某个事件发生概率的初步判断或是在进行实验或分析之前对事件可能性的主观评估。
后验概率:是指在考虑了新数据或证据之后,对事件概率的重新评估。它是先验概率与新证据(通常是观测数据)相结合的结果,通过贝叶斯公式计算得出。
8.2 朴素贝叶斯算法的含义
朴素贝叶斯算法是利用概率值进行分类的一种机器学习算法,朴素贝叶斯算法在贝叶斯算法的基础上增加了特征之间相互独立的条件假设(这点也是朴素一词的具体体现),其一般公式如下:
注意:上式中为后验概率,
为先验概率。
上式中X代表特征,x代表该特征的取值,上标j代表第j个特征,Y代表类别,Ck代表类别具体的取值,分母是P(X = x)对完备事件组Y的全概率公式展开,对于Y的所有不同的取值,分母的值都是一样的,对结果没有影响,基于极大似然估计的思想,朴素贝叶斯分类器期望将样本分到后验概率最大的类别中,因此朴素贝叶斯分类器就简化为:
上式中的argmax是一种函数,是对函数求参数(或参数集合)的函数。当我们有一个函数y = f(x)时,若有结果x0 = argmax(f(x)),则表示当函数f(x)取x = x0的时候,得到f(x)在取值范围内的最大值,上式中argmax的下标Ck表示对参数Ck求argmax,即Ck为何值能够使得式的值最大。
8.3 拉普拉斯平滑
在朴素贝叶斯算法中,存在连乘的计算。如果某个特征值在某个类别下没有出现过,那么按照传统的概率估计方法,该特征值在这个类别下的概率会被估计为0,进而导致概率连乘以后得结果也会是0。
为了避免概率值为0,在分子和分母分别加上一个数值,这就是拉普拉斯平滑系数的作用,拉普拉斯平滑系数的具体表达式如下:
上式中α是拉普拉斯平滑系数,一般指定为1,Ni是特征F1中类别为C的样本数量,N是类别为C的样本总数,m 表示所有独立样本的总数。
8.4 情感分类项目
使用朴素贝叶斯算法完成情感分类项目的具体实现代码如下:
import jieba
import pandas as pd
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.metrics import accuracy_score
# 以GBK编码格式读取数据
data = pd.read_csv('data/书籍评价.csv', encoding='gbk')
# 将标签列转化为0和1
data['评价'] = data['评价'].apply(lambda x: 1 if x == '好评' else 0)
# 加载停用词
with open('data/stopwords.txt', mode='r', encoding='utf-8') as f:
rl = f.readlines() # 读取所有行(包括换行符),存放在列表中
# 去除停用词中的换行符并去重
stop_words = [i.strip() for i in rl]
stop_words = list(set(stop_words))
# 使用jieba分词工具进行分词
sentences = ['|'.join(jieba.lcut(sent)) for sent in data['内容']]
# 创建CountVectorizer对象,该对象的作用是将文本转化为词向量
cnt_vec = CountVectorizer(stop_words=stop_words)
# 训练CountVectorizer对象并将句子转化为词向量
sent_vec = cnt_vec.fit_transform(sentences)
# 词向量化后的sent_vec为稀疏矩阵,需要转化为数组类型
x = sent_vec.toarray()
# 划分训练集和测试集
x_train = x[:10, :]
x_test = x[10:, :]
# data['评价'].values用于获取数组类型的标签列,data['评价']为Series类型
y_train = data['评价'].values[:10]
y_test = data['评价'].values[10:]
# 创建朴素贝叶斯模型并训练模型,alpha为拉普拉斯平滑系数
nb = MultinomialNB(alpha=1.0)
nb.fit(x_train, y_train)
# 模型预测
y_pred = nb.predict(x_test)
# 模型评估
print(f"模型在测试集上的准确率:{accuracy_score(y_test, y_pred)}")
# 对新评论进行预测
# 创建新评论并分词
sentence_new = '内容太浅显, 一点用没有'
sentence_new = ['|'.join(jieba.lcut(sentence_new)), ]
# 将分词后的新评论转化为词向量,这里直接使用CountVectorizer的transform方法,因为nb是使用x_train训练的
# 这里需要保证新评论转换后的词向量与训练集的词向量有着一致的维度,所以不能重新使用fit方法训练CountVectorizer对象
pred_vec = cnt_vec.transform(sentence_new)
print(nb.predict(pred_vec))
更多推荐
所有评论(0)