【机器学习】贝叶斯分类三大实战项目:高斯模型进行疾病诊断、多项式模型进行文本分类、伯努利模型进行好/差评判别


手动反爬虫: 原博地址 https://blog.csdn.net/lys_828/article/details/122524155

 知识梳理不易,请尊重劳动成果,文章仅发布在CSDN网站上,在其他网站看到该博文均属于未经作者授权的恶意爬取信息

贝叶斯算法

Scikit-learn中朴素贝叶斯的分类算法:GaussianNB,MultinomialNB和BernoulliNB。其中GaussianNB就是先验为高斯分布的朴素贝叶斯;MultinomialNB是先验为多项式分布的朴素贝叶斯;BernoulliNB是先验为伯努利分布的朴素贝叶斯。

三种模型的区别:

  • (1)高斯模型:有些特征可能是连续型变量,比如人的身高,物体的长度,这些特征也可以直接转换成为离散的值。高斯模型假设这些特征的所有属于某个类别的观测值属于高斯分布。

  • (2)多项式模型:该模型常用于文本分类,特征是单词,值是单词出现的次数。

  • (3)伯努利模型:对于一个样本来说,其特征用的是全局的特征。在伯努利模型中,每个特征的取值是布尔型的,即True和False,或者是1和0。在文本分类中,就是一个特征有没有在一个文档中出现。

1 贝叶斯高斯模型

1.1 模块导入以及数据加载

导入需要使用的模块

import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import GaussianNB
from sklearn.metrics import accuracy_score
import matplotlib.pyplot as plt
import seaborn as sns

加载本地数据集

df = pd.read_csv('../data/Naive-Bayes-Classifier-Data.csv')
df.head()

输出结果如下。数据集为医疗数据,可用于疾病前期诊断。第一个字段为葡萄糖,第二个字段为血压,第三个为患病结果,患病被标记为1,未患病被标记为0。
请添加图片描述

1.2 划分数据

首先划分特征数据与标签数据

x = df.drop('diabetes',axis=1)
y = df['diabetes']

然后再划分训练集和测试集,为了保证执行结果一致,可以指定随机种子的赋值为一个固定值,比如这里指定是42。

x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=0.25,random_state=42)

代码执行结果如下。
请添加图片描述

1.3 模型创建与评估

模型创建及预测分为三步

#第一步:模型初始化
model = GaussianNB()
#第二步:模型训练
model.fit(x_train,y_train)
#第三步:模型预测
y_pred = model.predict(x_test)

代码实现结果如下。
请添加图片描述
进一步可以对预测的结果进行打印输出,也可以查看当前模型的得分

y_pred[:10]
accuracy = accuracy_score(y_test,y_pred)*100
accuracy

输出结果如下。
请添加图片描述
最后是对于分类的结果可以借助混淆矩阵配合热力图进行可视化。

from sklearn.metrics import confusion_matrix
cm = confusion_matrix(y_test,y_pred)
import seaborn as sn
plt.figure(figsize = (10,7))
sn.heatmap(cm, annot=True)
plt.xlabel('Predicted')
plt.ylabel('Truth')

最终输出结果如下。
请添加图片描述

2 贝叶斯多项式模型

2.1 模块导入与数据加载

导入需要使用的模块

import numpy as np
import pandas as pd

加载简单的新闻数据集

df = pd.read_csv('../data/sample_news.csv')
df.head()

输出结果如下。
请添加图片描述
简单阅览一下数据集中的数据,比如先看一下第一行的数据文本,还有分类的类别。

df.Title[0]
df.Category.unique()

输出过如下。其中类别的字母简写分别对应关系为:b- business, t- technology, e-entertainment。请添加图片描述
除了查看类别为b的具体文本信息外,也可以通过筛选查看其他类别信息,比如查看类别为t的文本信息,代码如下

df.Category=='t'
df[df.Category=='t'].Title[60]

输出结果如下。
请添加图片描述
数据整体概览,比如查看数据维度以及各分类的数据量

df.shape
df['Category'].value_counts()

输出结果如下。数据一共 65行2列,第一列是新闻内容,第二列是新闻分类,分别为:商业,娱乐,IT。每个分类的数据量不相同。
请添加图片描述

2.2 文本数据处理

对于文本型数据,需要对出现的字符编码后才可以进一步处理,应用到专门处理文字数据的nltk模块

2.2.1 模块与压缩包安装

nltk模块在导入后需要先加载一下stopwords和punkt两个压缩包,需要进行网络连接下载(这个过程可能需要搭载vpn),输出结果提示为True时,表示停用词下载完毕。
请添加图片描述
如果已经执行过一次程序后,再次运行,输出结果就会提醒已经安装成功,如下。请添加图片描述
前期工作整理好了后,可以简单的进行文本数据处理。核心思想在于:统计词频。

2.2.2 文本分词

准备一条简单的文本数据,然后导入nltk中的word_tokenize方法,直接就可以将文本数据进行分词处理。

data = "Ford Technologies is a Software Development company. Ford also provide trainings."
from nltk import word_tokenize
word_tokenize(data)

输出结果如下。
请添加图片描述

2.2.3 去停用词

需要注意,由于文本数据的特性,里面包含了大量常见的词语,比如is,the,a等无实义的词语,在这里统称为停用词,需要进行过滤掉。具体实现的方式就是直接调用nltk中的stopwords方法,里面包含了经常使用一些停用词。

from nltk.corpus import stopwords
stopWords = set(stopwords.words('english'))
stopWords
len(stopWords)

输出结果如下。进一步输出停用词的个数 ,一共内置有179个。请添加图片描述
有了停用词数据集,那么只需要在文本分词的基础上进行数据剔除,就可以获取剩下的文本数据。

for i in word_tokenize(data):
#     print(i)
    if i.lower() not in stopwords.words('english'):
        print(i)

输出结果如下。在停用词数据集中的信息已经被剔除,但是还要剔除标点符号。
请添加图片描述

2.2.4 去标点符号

在python中有专门处理此类问题的模块string,借助下面的punctuation属性就可以获得所有的标点符号。

import string
string.punctuation

输出结果如下。
请添加图片描述
进一步添加一条if语句进行筛选,就能得到相对简洁的文本数据。

for i in word_tokenize(data):
#     print(i)
    if i.lower() not in stopwords.words('english'):
        if i.lower() not in string.punctuation:
            print(i)

输出结果如下。
请添加图片描述

2.2.5 文本处理过程封装

由此整个文本处理的过程就完毕,进一步通过封装函数,将上述的三个步骤都放在一个函数中,直接调用,代码如下。

def text_cleaning(a):
    remove_punctuation = [char for char in a if char not in string.punctuation]
    remove_punctuation=''.join(remove_punctuation) 
    return [word for word in remove_punctuation.split() if word.lower() not in stopwords.words('english')]

进行简单的文本数据测试,运行结果如下。最终实现了文本分词,去停用词和去标点的操作。
请添加图片描述

2.3 文本词频

2.3.1 词向量编码

对于文本数据,如何确定每一个文本数据具体的内容,可以通过数值编码进行一一对应,借助sklearn下面的词向量计数器完成。

#第一步:导入词向量计数器
from sklearn.feature_extraction.text import CountVectorizer
#第二步:词向量计数器初始化
vectorizer = CountVectorizer()
#第三步:数据训练
vectorizer.fit(data_1)
#第四步:输出编码后的结果
vectorizer.vocabulary_
len(vectorizer.vocabulary_)

输出结果如下。请添加图片描述
如果再次运行这个词向量计数器,再次进行词编码。输出结果如下。最终的编码的键值对是不变的。请添加图片描述
由此可以总结:所有的单词,通过词向量转化都变成了对应的编码,fit 就是构建一个编码字典。

2.3.2 词向量转化

刚刚实现的是对于每一个单词的编码处理,但是要解决一个问题:如何表示这个单词,就需要利用刚刚的编码进行变换。

vector = vectorizer.transform(data_1)
print(vector)

输出结果如下。
请添加图片描述
结果解读:左侧括号的第一个元素代表python中词的个数,这里从0-3,表示一共有4个元素;然后第二个元素代表着词的编号,比如(0,1)代表着第一个元素是编号为1的词,(1,3)表示第二个元素是编号为3的词;最右边是对于每一个词的词频计数。

对照实际输出结果和原始词数据更容易进行理解,如下。
请添加图片描述
除了对一个句子进行词频计算,还可以针对多个句子,比如重新定义data_1,赋值的内容如下。

data_1 = ["Ford Technologies Ford is in LA.","Ford Technologies Ford is in LA."]
vectorizer.fit(data_1)
vector = vectorizer.transform(data_1)
print(vector)
vectorizer.vocabulary_

输出结果如下。注意留心红框中的编号。
请添加图片描述
其中关于fit和transform可以直接进行合并为一步,利用fit_transform方法,代码及结果输出如下。
请添加图片描述
此外还需要注意,对于传入的数据量不一致,对应的编码每一次运行后编码结果不一定是相同的,比如最开始的传入的data_1中经过数据清洗后只有4个元素,对应的la编号是2,但是之后传入的数据data_1是没有进行清洗的数据,里面有5个元素,其中的la编号为3,这一点需要特别留意一下。并不是每一次单词出现对应的编号都是相同,每次传入数据fit一次后就会有对应的编号,单词的编号不是固定不变。

2.4 案例应用

上面关于文本处理和词频计数内容都介绍完毕,接下来就是应用到真实的案例数据中。

df.head()
df.Title.apply(text_cleaning)

输出结果如下。初步对文本字段使用数据清洗函数,输出结果满足预期要求。
请添加图片描述

2.4.1 文本字段编码化

利用如下代码进行,其中analyzer参数中填写要进行数据处理的函数,fit后添加要被进行训练的文本字段。

bow_transformer = CountVectorizer(analyzer=text_cleaning).fit(df['Title'])

得到的结果是一个自动编码完成的字典数据,输出结果如下。
请添加图片描述

2.4.2 编码转换

对应2.3部分介绍的内容,编码完成后需要对单词进行编码转化从而实现词频计数。

title_bow = bow_transformer.transform(df['Title'])
print(title_bow)

输出结果如下。
请添加图片描述
对于输出结果进行核实,按照之前介绍的,括号中相同的元素代表着一个文本中的数据,比如提取第一行的数据。

df.Title.apply(text_cleaning)[0]

for a,b in dict(bow_transformer.vocabulary_).items():
    if b in [61,167,171,202,221,224,229,243,244]:
        print(a,b)

输出结果如下。检查输出编码和对应的单词是一一对应。
请添加图片描述

2.4.3 TF-IDF模型介绍

TF-IDF(term frequency–inverse document frequency)是一种用于信息检索与数据挖掘的常用加权技术。

TF是词频(Term Frequency),IDF是逆文本频率指数(Inverse Document Frequency)。

假设我们现在有一片长文叫做《量化系统架构设计》词频高在文章中往往是停用词,“的”,“是”,“了”等,这些在文档中最常见但对结果毫无帮助、需要过滤掉的词,用TF可以统计到这些停用词并把它们过滤。当高频词过滤后就只需考虑剩下的有实际意义的词。

但这样又会遇到了另一个问题,我们可能发现"量化"、“系统”、"架构"这三个词的出现次数一样多。这是不是意味着,作为关键词,它们的重要性是一样的?事实上系统应该在其他文章比较常见,所以在关键词排序上,“量化”和“架构”应该排在“系统”前面,这个时候就需要IDF,IDF会给常见的词较小的权重,它的大小与一个词的常见程度成反比。

当有TF(词频)和IDF(逆文档频率)后,将这两个词相乘,就能得到一个词的TF-IDF的值。某个词在文章中的TF-IDF越大,那么一般而言这个词在这篇文章的重要性会越高,所以通过计算文章中各个词的TF-IDF,由大到小排序,排在最前面的几个词,就是该文章的关键词。

具体的计算方式如下。
请添加图片描述

2.4.5 TF-IDF模型应用

利用示例的中文句子,演示TF-IDF如何使用,测试数据如下。

corpus = [
  "帮我 查下 明天 北京 天气 怎么样",
  "帮我 查下 今天 北京 天气 好不好",
  "帮我 查询 去 北京 的 火车",
  "帮我 查看 到 上海 的 火车",
  "帮我 查看 股票 的 新闻",
  "帮我 看看 有没有 北京 的 新闻",
  "帮我 搜索 上海 有 什么 好玩的",
  "帮我 找找 上海 东方明珠 在哪"
]

将语句中的内容进行分词处理后训练,对中文进行编码。

vectoerizer2 = CountVectorizer(min_df=1, max_df=1.0, token_pattern='\\b\\w+\\b')
vectoerizer2.fit(corpus)
vectoerizer2.vocabulary_

程序执行后,输出结果如下。
请添加图片描述

训练完成后,可以借助get_feature_names方法获得分词后各个特征的名称,也就是分词后的结果。

bag_of_words = vectoerizer2.get_feature_names()
print("Bag of words:")
print(bag_of_words)
print(len(bag_of_words))

输出结果如下。
请添加图片描述
除了获取分词的结果,也可以获取分词对应的编号,具体的方式就是使用字典的get方法。

print("index of `{}` is : {}".format('东方明珠',vectoerizer2.vocabulary_.get('东方明珠')))
print("index of `{}` is : {}".format('股票',vectoerizer2.vocabulary_.get('股票')))

输出结果如下。
请添加图片描述
fit获取是特征编码的字典,上面介绍了如何快速获取字典中的键值信息,接下来就是要进行transform的编码转化。

X = vectoerizer2.transform(corpus)
print("Vectorized corpus:")
print(X)

输出结果如下。为了展示方便,只进行部分输出结果的截取。
请添加图片描述
也可以按照原来的思路进行编码转换的核实。比如还是选取第一行的元素进行。

for a,b in dict(vectoerizer2.vocabulary_).items():
    if b in [5,8,11,12,16,16]:
        print(a,b)

输出结果如下。对比原corpus里面的第一句内容,可知编码转换无误。
请添加图片描述
TF-IDF应用只需要四步,详细代码操作如下。

#第一步:导入模块
from sklearn.feature_extraction.text import TfidfTransformer
#第二步:TF-IDF模型初始化
tfidf_transformer = TfidfTransformer()
#第三步:模型训练数据
tfidf_transformer.fit(X.toarray())
#第四步:获取转化后的数据
for idx, word in enumerate(vectoerizer2.get_feature_names()):
    print("{}\t{}".format(word, tfidf_transformer.idf_[idx]))

输出结果如下。最后面输出中,第一列为特征值,最后一列为特征经过TF-IDF模型后计算结果,此值越大说明在该文中这个值对应的特征值就越重要。
请添加图片描述

2.4.6 实例应用

简单测试完成之后,将TF-IDF模型应用到前面加载的数据集中。传入的数据样式是经过transform后的编码数据。

print(title_bow)
tfidf_transformer=TfidfTransformer().fit(title_bow)
print(tfidf_transformer)

输出结果如下。第一行的打印输出结果就是为了核实传入到TF-IDF模型中的数据是否为转化后的编码形式。
请添加图片描述
对于TF-IDF模型也是一样,在经过fit训练数据后,也是要进一步将数据进行转化。

title_tfidf=tfidf_transformer.transform(title_bow)
print(title_tfidf)
print(title_tfidf.shape)

输出结果如下。只展示部分输出,最后的shape为(65,256)。
请添加图片描述
获得到了每个词对应的权重,也就是概率,那么就可以利用贝叶斯模型进行建模。

from sklearn.naive_bayes import MultinomialNB
model = MultinomialNB()
model.fit(title_tfidf,df['Category'])
all_predictions = model.predict(title_tfidf)
print(all_predictions)

输出结果如下。注意对于贝叶斯多项式模型中fit的数据,用title_tfidf做特征集 df[‘Category’]做标签。
请添加图片描述
上述过程,直接使用了全部的数据导入模型,最后的预测结果和原来的标签数据一模一样,可以进一步采取测试集和训练集数据的划分。

from sklearn.model_selection import train_test_split
x_train,x_test,y_train,y_test = train_test_split(title_tfidf,df['Category'],test_size=0.25,random_state=42)
model2 = MultinomialNB()
model2.fit(x_train,y_train)
y_pred = model.predict(x_test)
y_pred[:10]

输出结果如下。
请添加图片描述
然后借助评分和混淆矩阵查看模型的预测结果。

from sklearn.metrics import accuracy_score
accuracy = accuracy_score(y_test,y_pred)*100
accuracy
from sklearn.metrics import confusion_matrix
cm = confusion_matrix(y_test,y_pred)
import matplotlib.pyplot as plt
import seaborn as sns
plt.figure(figsize = (10,7))
sns.heatmap(cm, annot=True)
plt.xlabel('Predicted')
plt.ylabel('Truth')

输出结果如下。即便是使用了训练集和测试集数据,最后经过分类的结果也是100%的正确率,说明样本的量相对较少了,也可以指定不同的随机种子,再次跑模型最后的得分就会不同。
请添加图片描述

2.5 模型预测

由于模型训练时候传入的数据类型就是已经经过编码后的数据,因此在进行模型预测时候传入的测试集数据也应该是经过处理好的数据类型。

x_val="Box Office: 'X-Men " # e
x_val2="IT Fed break news Stocks fall" # b
df2=pd.DataFrame({'title':[x_val]})
df2.head()
df2=df2.append({'title':[x_val2]}, ignore_index=True)
df2.head()
df2['title'].apply(text_cleaning)
title_bow = bow_transformer.transform(df2.title)
print(title_bow[:])

输出结果如下。
请添加图片描述
需要特别注意,在经过transform后要核实一下是不是对应正确的编码数据。
请添加图片描述
核实无误后,就可以对编码后的数据应用TF-IDF模型转化后获取对应分词的权重,最终可以将数据放在贝叶斯多项式模型中进行预测。

title_tfidf=tfidf_transformer.transform(title_bow)
print(title_tfidf)
for a,b in dict(bow_transformer.vocabulary_).items():
    if b in [102,32,131]:
        print(a,b)
val_predictions = model.predict(title_bow)
print(val_predictions)

输出结果如下。中间一步就是输出最大权重值对应的分词结果,往往就代表着这个句子的分类。最后核实模型分类结果无误。
请添加图片描述

3 贝叶斯伯努利模型

和多项式模型一样,都是用于做文本分类。只不过最后的分类只能是两种,0或者1。常见文本评价分类,好评还是差评。

3.1 模块导入与数据加载

导入需要使用的模块

import numpy as np
import pandas as pd

加载文本评论数据集

df = pd.read_csv('../data/Restaurant_Reviews.tsv',sep='\t')
df.head()

输出结果如下。
请添加图片描述
查看数据的维度和分类信息,代码及输出结果如下。
请添加图片描述

3.2 添加停用词

加载英文中常见停用词

from nltk.corpus import stopwords
stopWords = set(stopwords.words('english'))
print(stopWords)

输出结果如下。
请添加图片描述

3.3 文本数据清洗

之前封装过的函数,现在就可以直接拿过来使用。

import string
def text_cleaning(a):
    cleaning = [char for char in a if char not in string.punctuation]
    cleaning=''.join(cleaning)
    return [word for word in cleaning.split() if word.lower() not in stopwords.words('english')]

执行代码如下。
请添加图片描述

3.4 文本数据编码及转化

这个过程在前面贝叶斯多项式中有详细的介绍,下面直接给出代码。

from sklearn.feature_extraction.text import CountVectorizer
bow_transformer = CountVectorizer(analyzer=text_cleaning).fit(df['Review']) 
bow_transformer.vocabulary_
title_bow = bow_transformer.transform(df['Review'])
print(title_bow)

输出结果如下。
请添加图片描述
为了方便查看编码后的数据,可以转化为df形式。

X = title_bow.toarray()
print(X)
tokens= bow_transformer.get_feature_names()
dd=pd.DataFrame(data=title_bow.toarray(),columns=tokens)
dd

输出结果如下。通过输出的df数据结构,可以更加直观体会到数据的shape以及对应的数值。
请添加图片描述

3.5 数据集划分

特征数据和标签数据一目了然,不需要再多进行处理,接下来就是要进行训练集和测试集的划分。

from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(X, df.Liked,test_size=0.2, random_state=50)

输出结果如下。
请添加图片描述

3.6 模型对比

由于伯努利模型属于多项式模型中的一种特例,两种模型都可以适用于当前数据集,具体哪种模型好坏,可以通过实际的模型得分来判断,导入创建两个模型的模块。

# 使用伯努利模型
from sklearn.naive_bayes import BernoulliNB
# 使用多项式模型
from sklearn.naive_bayes import MultinomialNB

输出结果如下。
请添加图片描述
先进行伯努利模型的创建及应用,代码如下。

model = BernoulliNB().fit(x_train,y_train)  
prediction = model.predict(x_test)
print(prediction)
from sklearn.metrics import accuracy_score
accuracy_score(prediction,y_test)
from sklearn.metrics import confusion_matrix
cm = confusion_matrix(y_test,prediction)
import matplotlib.pyplot as plt
import seaborn as sns
plt.figure(figsize = (10,7))
sns.heatmap(cm, annot=True)
plt.xlabel('Predicted')
plt.ylabel('Truth')

输出结果如下。使用伯努利模型最后的得分为0.715。
请添加图片描述
接下来使用多项式模型,模型的分为0.77,代码及执行结果如下。
请添加图片描述

至此,关于贝叶斯算法中关于分类的三种模型就全部介绍完毕。

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lys_828

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值