用朴素贝叶斯处理三类问题

朴素贝叶斯
1)基础思想:对于给出的待分类项,求解在此项出现的条件下各个类别出现的概率,哪个最大,就认为此分类项属于哪个类别。
2)优点:
可以和决策树、神经网络分类算法相媲美,能运用于大型数据库中。
方法简单,分类准确率高,速度快,所需估计的参数少,对于缺失数据不敏感。
3)缺点:
假设一个属性对定类的影响独立于其他的属性值,这往往并不成立。(喜欢吃番茄、鸡蛋,却不喜欢吃番茄炒蛋)。
需要知道先验概率。

根据自变量X的不同类型,有三种分类器。
若X为连续的数值型,选择高斯贝叶斯分类器;
若X为离散的数据类型,选择多项式贝叶斯分类器;
若X为0-1二元值,选择伯努利贝叶斯分类器。
以上核心假设为自变量之间条件独立。

优点:
算法在运算过程中简单高效,对大数量训练和查询时具有较高的速度。即使使用超大规模的训练集,针对每个项目通常也只会有相对较少的特征数,并且对项目的训练和分类也仅仅是特征概率的数学运算而已;
拥有古典概率的理论支撑,分类效率稳定;
对缺失数据和异常数据不太敏感。
支持增量式运算,即可以实时的对新增的样本进行训练;
朴素贝叶斯对结果解释容易理解;
对数据较少的情况下仍然有效;
可以处理多类别问题。

缺点:
模型的判断结果依赖于先验概率,会导致分类结果存在一定的错误率;
对输入的X要去相同特征(变量均为数值型或离散型或0-1型);
模型的前提假设在实际应用中很难满足;
由于使用了样本属性独立性的假设,所以如果样本属性有关联时其效果不好。

改进措施:
下溢出问题:对概率取对数;
词袋模型在解决文档分类问题上比词集模型好;
移除停用词(对分类基本上没有帮助的词,如助词、语气词等)。

注:Bag-of-Words词袋模型,经常用在自然语言处理和信息检索当中.在词袋模型中,一篇文本(文章)被表示成"装着词的袋子",也就是说忽略文章的词序和语法,句法;将文章看做词的组合,文中出现的每个词都是独立的,不依赖于其他词.Set-of-Words词集模型SoW:用0-1作为文章中词的数量表示.两者之间的区别在于词的数量表示不同,一个用0-1,一个用词频。

应用领域:
欺诈检测;一封电子邮件是否是垃圾邮件;一篇文章应该分到科技、政治,还是体育类;一段文字表达的是积极的情绪还是消极的情绪;人脸识别等。

一、高斯贝叶斯分类器

利用三原色RGB区分是否为人类面部皮肤,当均落在0~255时,为人类皮肤

# 导入第三方包
import pandas as pd
# 读入数据
skin = pd.read_excel(r'F:\Skin_Segment.xlsx')
skin.head()
image.png

1表示人类皮肤,2表示非人类皮肤

将2设置为负例,因变量0;1设置为正例,因变量1
通过map函数


# 设置正例和负例
skin.y = skin.y.map({2:0,1:1})
skin.y.head()

统计各自个数

skin.y.value_counts()

拆分数据集

#提取自变量,通过iloc获取数据框子集
skin.iloc[:,:3].head()
# 导入第三方模块
from sklearn import model_selection
# 样本拆分
X_train,X_test,y_train,y_test = model_selection.train_test_split(skin.iloc[:,:3], skin.y, 
                                                                 test_size = 0.25, random_state=1234)
from sklearn import naive_bayes
# 调用高斯朴素贝叶斯分类器的“类”
gnb = naive_bayes.GaussianNB()
# 模型拟合
gnb.fit(X_train, y_train)
# 模型在测试数据集上的预测
gnb_pred = gnb.predict(X_test)
# 各类别的预测数量
pd.Series(gnb_pred).value_counts()

得到预测为负例一共有50630个,预测为正例有10635个

为检验预测效果,构建混淆矩阵和绘制ROC曲线

# 导入第三方包
from sklearn import metrics
import matplotlib.pyplot as plt
import seaborn as sns
# 构建混淆矩阵
cm = pd.crosstab(gnb_pred,y_test)
cm
# 绘制混淆矩阵图
sns.heatmap(cm, annot = True, cmap = 'GnBu', fmt = 'd')
# 去除x轴和y轴标签
plt.xlabel('Real')
plt.ylabel('Predict')
# 显示图形
plt.show()
print('模型的准确率为:\n',metrics.accuracy_score(y_test, gnb_pred))
print('模型的评估报告:\n',metrics.classification_report(y_test, gnb_pred))

整体预测率为92.30%
并且可得预测率和覆盖率较高

# 计算正例的预测概率,而非实际的预测值,用于生成ROC曲线的数据
y_score = gnb.predict_proba(X_test)[:,1]
y_score
#fpr表示1-Specificity,tpr表示Sensitivity
fpr,tpr,threshold = metrics.roc_curve(y_test, y_score)
fpr,tpr,threshold
# 计算AUC的值
roc_auc = metrics.auc(fpr,tpr)
roc_auc
# 绘制面积图
plt.stackplot(fpr, tpr, color='steelblue', alpha = 0.5, edgecolor = 'black')
# 添加边际线
plt.plot(fpr, tpr, color='black', lw = 1)
# 添加对角线
plt.plot([0,1],[0,1], color = 'red', linestyle = '--')
# 添加文本信息
plt.text(0.5,0.3,'ROC curve (area = %0.2f)' % roc_auc)
# 添加x轴与y轴标签
plt.xlabel('1-Specificity')
plt.ylabel('Sensitivity')
# 显示图形
plt.show()

0.94>0.8,构建的分类器非常理想。

二、多项式贝叶斯分类器

判断蘑菇是否有毒

# 导入第三方包
import pandas as pd
# 读取数据
mushrooms = pd.read_csv(r'F:\mushrooms.csv')
# 数据的前5行
mushrooms.head(

所有字符均为字符型的离散值,做因子化处理

通过pandas模块的factorize函数,返回的是两个元素的元祖,第一个元素为转换成的数值,第二个元素为数值对应的字符水平

# 将字符型数据作因子化处理,将其转换为整数型数据
columns = mushrooms.columns[1:]
columns
for column in columns:
    mushrooms[column] = pd.factorize(mushrooms[column])[0]
mushrooms.head()

拆分数据

from sklearn import model_selection
# 将数据集拆分为训练集合测试集
Predictors = mushrooms.columns[1:]
X_train,X_test,y_train,y_test = model_selection.train_test_split(mushrooms[Predictors], mushrooms['type'], 
                                                                 test_size = 0.25, random_state = 10)
from sklearn import naive_bayes
from sklearn import metrics
import seaborn as sns
import matplotlib.pyplot as plt
# 构建多项式贝叶斯分类器的“类”
mnb = naive_bayes.MultinomialNB()
mnb
# 基于训练数据集的拟合
mnb.fit(X_train, y_train)
mnb.fit
# 基于测试数据集的预测
mnb_pred = mnb.predict(X_test)
mnb_pred
# 构建混淆矩阵
cm = pd.crosstab(mnb_pred,y_test)
cm
# 绘制混淆矩阵图
sns.heatmap(cm, annot = True, cmap = 'GnBu', fmt = 'd')
# 去除x轴和y轴标签
plt.xlabel('Real')
plt.ylabel('Predict')
# 显示图形
plt.show()
# 模型的预测准确率
print('模型的准确率为:\n',metrics.accuracy_score(y_test, mnb_pred))
print('模型的评估报告:\n',metrics.classification_report(y_test, mnb_pred))

整体预测准确率87%,无毒蘑菇的预测覆盖率92%,有毒蘑菇的预测覆盖率82%

from sklearn import metrics
# 计算正例的预测概率,用于生成ROC曲线的数据
y_score = mnb.predict_proba(X_test)[:,1]
fpr,tpr,threshold = metrics.roc_curve(y_test.map({'edible':0,'poisonous':1}), y_score)
# 计算AUC的值
roc_auc = metrics.auc(fpr,tpr)

# 绘制面积图
plt.stackplot(fpr, tpr, color='steelblue', alpha = 0.5, edgecolor = 'black')
# 添加边际线
plt.plot(fpr, tpr, color='black', lw = 1)
# 添加对角线
plt.plot([0,1],[0,1], color = 'red', linestyle = '--')
# 添加文本信息
plt.text(0.5,0.3,'ROC curve (area = %0.2f)' % roc_auc)
# 添加x轴与y轴标签
plt.xlabel('1-Specificity')
plt.ylabel('Sensitivity')
# 显示图形
plt.show()

当因变量为字符型的值时,子模块metrics中的函数roc_curve必须传入数值型的因变量,map理解为映射函数


如果自变量在特定y值下的概率不服从多项式分布,则预测效果不理想

一般多项式分类器用作文本分类的关于词语出现的次数等,例如一封邮件是否垃圾邮件,用户评论是否为正面

如果文本分类考虑词语是否会出现的0-1值,使用伯努利分类器

三、伯努利贝叶斯分类器

分析用户购买蚊帐之后评论的情绪

import pandas as pd
# 读入评论数据,sheetname指定需要读取表格中的第一个子表
evaluation = pd.read_excel(r'F:\Contents.xlsx',sheetname=0)
# 查看数据前10行
evaluation.head(10)

数据集包含4个字段,用户昵称,评价时间,评价内容,对应评价情绪

处理“脏”文本,例如数字、英文等

# 运用正则表达式,将评论中的数字和英文去除
evaluation.Content = evaluation.Content.str.replace('[0-9a-zA-Z]','')
evaluation.head(10)

下一步对文本进行切词,先要引入用户自定义的词库和停止词,利用词库的目的是将无法正常分割的词实现正常分割,例如“沙润句中金”切词为“沙”,“润”,“亲”,停止词的目的是将句中无意义的词语删除(”的“,”啊“,”我们“)

关于jieba库的用法:

#encoding=utf-8
import jieba

#全模式
text = "我来到北京清华大学"
seg_list = jieba.cut(text, cut_all=True)
print (u"[全模式]: ", "/ ".join(seg_list))

#精确模式
seg_list = jieba.cut(text, cut_all=False)
print (u"[精确模式]: ", "/ ".join(seg_list))

#默认是精确模式
seg_list = jieba.cut(text)
print (u"[默认模式]: ", "/ ".join(seg_list))

#新词识别 “杭研”并没有在词典中,但是也被Viterbi算法识别出来了
seg_list = jieba.cut("他来到了网易杭研大厦") 
print (u"[新词识别]: ", "/ ".join(seg_list))

#搜索引擎模式
seg_list = jieba.cut_for_search(text) 
print (u"[搜索引擎模式]: ", "/ ".join(seg_list))

回到正文:
通过调入第三方包jieba实现中文的切词,并在切词过程中加入自定义词库和删除停止词。

# 导入第三方包
import jieba
#encoding=utf-8
# 加载自定义词库
jieba.load_userdict(r'F:\1.txt')
# 读入停止词
with open(r'F:\mystopwords.txt', encoding='UTF-8') as words:
    stop_words = [i.strip() for i in words.readlines()]
# 构造切词的自定义函数,并在切词过程中删除停止词
def cut_word(sentence):
    words = [i for i in jieba.lcut(sentence) if i not in stop_words]
    # 切完的词用空格隔开
    result = ' '.join(words)
    return(result)
# 对评论内容进行批量切词
words = evaluation.Content.apply(cut_word)
# 前5行内容的切词效果
words[:10]

利用如上的切词结果,构造文档词条矩阵,矩阵的每一行代表一个评论内容,每一列代表切词后的词语,元素为词语在文档中出现的频次。

# 导入第三方包
from sklearn.feature_extraction.text import CountVectorizer
# 计算每个词在各评论内容中的次数,并将稀疏度为99%以上的词删除
counts = CountVectorizer(min_df = 0.01)
# 文档词条矩阵
dtm_counts = counts.fit_transform(words).toarray()
dtm_counts

为了避免下面的稀疏矩阵的列数过多,在构造词条矩阵时做了相应限制,表示词语所对应的文档数目必须在所有文档中至少占1%的比例


# 矩阵的列名称
columns = counts.get_feature_names()
columns

...

# 将矩阵转换为数据框--即X变量
X = pd.DataFrame(dtm_counts, columns=columns)
X.head()

转换为数据框后是一个庞大的稀疏矩阵,大部分值为0。

# 情感标签变量
y = evaluation.Type
y

...
拆分数据集

from sklearn import model_selection
from sklearn import naive_bayes
from sklearn import metrics
import matplotlib.pyplot as plt
import seaborn as sns
# 将数据集拆分为训练集和测试集
X_train,X_test,y_train,y_test = model_selection.train_test_split(X,y,test_size = 0.25, random_state=1)
# 构建伯努利贝叶斯分类器
bnb = naive_bayes.BernoulliNB()
# 模型在训练数据集上的拟合
bnb.fit(X_train,y_train)
# 模型在测试数据集上的预测
bnb_pred = bnb.predict(X_test)
# 构建混淆矩阵
cm = pd.crosstab(bnb_pred,y_test)
cm
# 绘制混淆矩阵图
sns.heatmap(cm, annot = True, cmap = 'GnBu', fmt = 'd')
# 去除x轴和y轴标签
plt.xlabel('Real')
plt.ylabel('Predict')
# 显示图形
plt.show()
# 模型的预测准确率
print('模型的准确率为:\n',metrics.accuracy_score(y_test, bnb_pred))
print('模型的评估报告:\n',metrics.classification_report(y_test, bnb_pred))
# 计算正例Positive所对应的概率,用于生成ROC曲线的数据
y_score = bnb.predict_proba(X_test)[:,1]
fpr,tpr,threshold = metrics.roc_curve(y_test.map({'Negative':0,'Positive':1}), y_score)
# 计算AUC的值
roc_auc = metrics.auc(fpr,tpr)

# 绘制面积图
plt.stackplot(fpr, tpr, color='steelblue', alpha = 0.5, edgecolor = 'black')
# 添加边际线
plt.plot(fpr, tpr, color='black', lw = 1)
# 添加对角线
plt.plot([0,1],[0,1], color = 'red', linestyle = '--')
# 添加文本信息
plt.text(0.5,0.3,'ROC curve (area = %0.2f)' % roc_auc)
# 添加x轴与y轴标签
plt.xlabel('1-Specificity')
plt.ylabel('Sensitivity')
# 显示图形
plt.show()

预测效果理想。

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

推荐阅读更多精彩内容