机器学习之朴素贝叶斯:Naive Bayesian(二、算法案例)

一、鸢尾花数据集朴素贝叶斯实现

# 导入算法包以及数据集
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report,confusion_matrix
from sklearn.naive_bayes import MultinomialNB,BernoulliNB,GaussianNB

# 载入数据
iris = load_iris()
x_train,x_test,y_train,y_test = train_test_split(iris.data, iris.target,test_size=0.3,random_state=1) 
mul_nb = MultinomialNB()
mul_nb.fit(x_train,y_train)
print('多项式模型:')
print('多项式模型准确率',mul_nb.score(x_test,y_test))
print(classification_report(mul_nb.predict(x_test),y_test))
print(confusion_matrix(mul_nb.predict(x_test),y_test))
ber_nb = BernoulliNB()
ber_nb.fit(x_train,y_train)
print('伯努利模型:')
print('伯努利模型准确率',ber_nb.score(x_test,y_test))
print(classification_report(ber_nb.predict(x_test),y_test))
print(confusion_matrix(ber_nb.predict(x_test),y_test))
gau_nb = GaussianNB()
gau_nb.fit(x_train,y_train)
print('高斯模型:')
print('高斯模型准确率',gau_nb.score(x_test,y_test))
print(classification_report(gau_nb.predict(x_test),y_test))
print(confusion_matrix(gau_nb.predict(x_test),y_test))

输出结果为:

机器学习之朴素贝叶斯:Naive Bayesian(二、算法案例)_第1张图片

机器学习之朴素贝叶斯:Naive Bayesian(二、算法案例)_第2张图片

机器学习之朴素贝叶斯:Naive Bayesian(二、算法案例)_第3张图片

由于鸢尾花的特征为花瓣和花萼的长度和宽度,均为连续数值,所以最适用于高斯模型,最终的准确率也可以看出高斯模型最优。伯努利模型表现最差,因为它适合处理二元均匀分布,与高斯分布差距太大,所以分类准确率也惨不忍睹。

二、语句情感分类 

导入库并下载数据: 

import numpy as np
import math

def loadDataSet():
	postingList=[['my', 'dog', 'has', 'flea', 'problems', 'help', 'please'],#切分的词条
				['maybe', 'not', 'take', 'him', 'to', 'dog', 'park', 'stupid'],
				['my', 'dalmation', 'is', 'so', 'cute', 'I', 'love', 'him'],
				['stop', 'posting', 'stupid', 'worthless', 'garbage'],
				['mr', 'licks', 'ate', 'my', 'steak', 'how', 'to', 'stop', 'him'],
				['quit', 'buying', 'worthless', 'dog', 'food', 'stupid']]
	classVec = [0,1,0,1,0,1] #类别标签向量,1代表侮辱性词汇,0代表不是
	return postingList,classVec#返回实验样本切分的词条和类别标签向量

统计所有文本中出现过的词汇,构建词集:

def createVocabList(dataSet):
	vocabSet = set([])#创建一个空的不重复列表
	for document in dataSet:
		vocabSet = vocabSet | set(document) #取并集
	return list(vocabSet)

将每句话转换成一个向量,与刚才建立的向量对应,1代表该词汇出现过,0代表没出现 :

def setOfWords2Vec(vocabList, inputSet):
	returnVec = [0] * len(vocabList)#创建一个其中所含元素都为0的向量
	for word in inputSet:#遍历每个词条
		if word in vocabList:#如果词条存在于词汇表中,则置1
			returnVec[vocabList.index(word)] = 1
		else: print("the word: %s is not in my Vocabulary!" % word)
	return returnVec#返回文档向量

例如,上述数据集的词集向量为: 那么对于postingList的第一个例子来说,['my', 'dog', 'has', 'flea', 'problems', 'help', 'please']对应的词集向量为:

[0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]

反过来,由词集向量和词汇表,也可以得到相应的样本。

 由于数据下溢(数据值太小默认等于0)和极大似然估计导致未出现词汇的概率为0,都会导致最终的概率为0所以要采用拉普拉斯平滑操作来弥补极大似然导致的概率为0,用取log操作来避免数据下溢。

这个函数的目的是求在侮辱类和非侮辱类的条件下每个词汇出现的概率 :

def trainNB0(trainMatrix,trainCategory):
	numTrainDocs = len(trainMatrix)#计算训练的文档数目
	numWords = len(trainMatrix[0])#计算每篇文档的词条数
	pAbusive = sum(trainCategory)/float(numTrainDocs)#文档属于侮辱类的概率
	p0Num = np.ones(numWords); p1Num = np.ones(numWords)#创建numpy.ones数组,拉普拉斯平滑
	p0Denom = 2; p1Denom = 2   #分母初始化为2
	for i in range(numTrainDocs):
		if trainCategory[i] == 1:#统计属于侮辱类的条件概率所需的数据,即P(w0|1),P(w1|1),P(w2|1)···
			p1Num += trainMatrix[i]
			p1Denom += sum(trainMatrix[i])  # 该词条的总的词数目   这压样求得每个词条出现的概率 P(w1),P(w2), P(w3)...
		else:#统计属于非侮辱类的条件概率所需的数据,即P(w0|0),P(w1|0),P(w2|0)···
			p0Num += trainMatrix[i]
			p0Denom += sum(trainMatrix[i])
	p1Vect = np.log(p1Num/p1Denom)#相除
	p0Vect = np.log(p0Num/p0Denom)
	return p0Vect,p1Vect,pAbusive#返回属于侮辱类的条件概率数组,属于非侮辱类的条件概率数组,文档属于侮辱类的概率

计算测试样本的词集向量,然后据此计算最终为侮辱类和非侮辱类的概率,根据概率大小,返回结果:

def classifyNB(vec2Classify, p0Vec, p1Vec, pClass1):
    p1 = sum(vec2Classify*p1Vec)  + np.log(pClass1)  #相乘后取log等于分别取log后相加
    p0 = sum(vec2Classify*p0Vec)  + np.log(1 - pClass1)
    print('p0:',p0)
    print('p1:',p1)
    if p1>p0:
        return 1
    else:
        return 0


def testingNB(testVec):
    listOPosts,listClasses = loadDataSet()#创建实验样本
    myVocabList = createVocabList(listOPosts)#创建词汇表
    trainMat=[]
    for postinDoc in listOPosts:
        trainMat.append(setOfWords2Vec(myVocabList, postinDoc))#将实验样本向量化
    p0V,p1V,pAb = trainNB0(np.array(trainMat),np.array(listClasses))#训练朴素贝叶斯分类器
    thisDoc = np.array(setOfWords2Vec(myVocabList, testVec))#测试样本向量化
    if classifyNB(thisDoc,p0V,p1V,pAb) == 1:
        print(testVec,'属于侮辱类')#执行分类并打印分类结果
    else:
        print(testVec,'属于非侮辱类')#执行分类并打印分类结果
 

测试:

机器学习之朴素贝叶斯:Naive Bayesian(二、算法案例)_第4张图片 

个人觉得,之所以或出现概率为0,主要是因为为了方便操作,运用矩阵整体进行操作这样便会把0带进去,如果每次计算都把测试数据中出现的词的条件概率单独取出来相乘,就不会出现为0的情况了。

 三、垃圾邮件分类

数据集:分类邮件 提取码:cuwq

数据集包括25个垃圾邮件和25个非垃圾邮件。 

首先导入库和数据:

import os
import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.model_selection import train_test_split,cross_val_score
from sklearn.naive_bayes import MultinomialNB,BernoulliNB,GaussianNB
from sklearn.metrics import classification_report,confusion_matrix
import matplotlib.pyplot as plt


def getdata():
    ham = []#非垃圾邮件读取,共25个
    for i in range(1,26):
        file_path = 'email/ham/%d.txt'%(i)
        data = open(file_path,encoding='gbk',errors='ignore').read()
        ham.append([data,'ham'])
    df1 = pd.DataFrame(ham)
    spam = []#非垃圾邮件读取,共25个
    for i in range(1,26):
        file_path = 'email/spam/%d.txt'%(i)
        data = open(file_path,encoding='gbk',errors='ignore').read()
        spam.append([data,'spam'])
    df2 = pd.DataFrame(spam)
    data = pd.concat([df1,df2],ignore_index=True)  
    return dataset

dataset = getdata()

由于邮件是文本信息,我们要将它转换为能够处理的向量信息,就需要用到 sklearn中的TfidfVectorizer函数,它可以把文本转换为向量。

tf = TfidfVectorizer()
tf.fit(dataset[0])
data_tf = tf.transform(dataset[0])
#data_tf = tf.fit_transform(dataset[0])

划分训练集和测试集并用多项式模型和伯努利模型测试:

xtrain,xtest,ytrain,ytest=train_test_split(data_tf,dataset[1],test_size=0.2)
mnb = MultinomialNB()
mnb.fit(xtrain,ytrain)
print("多项式模型:")
print(mnb.score(xtest,ytest))
print(classification_report(mnb.predict(xtest),ytest))
print(confusion_matrix(mnb.predict(xtest),ytest))


print("伯努利模型:")
bnb = BernoulliNB()
bnb.fit(xtrain,ytrain)
print(bnb.score(xtest,ytest))
print(classification_report(bnb.predict(xtest),ytest))
print(confusion_matrix(bnb.predict(xtest),ytest))

结果如下:

机器学习之朴素贝叶斯:Naive Bayesian(二、算法案例)_第5张图片 

机器学习之朴素贝叶斯:Naive Bayesian(二、算法案例)_第6张图片 

进行10次10折交叉验证并画图:

%matplotlib inline
plt.rcParams['font.sans-serif']=['simhei']#在画图中显示中文
mnbs = []
bnbs = []
for i in range(10):
    mnb_s = cross_val_score(mnb,data_tf,dataset[1],cv=10).mean()
    mnbs.append(mnb_s)
    bnb_s = cross_val_score(bnb,data_tf,dataset[1],cv=10).mean()
    bnbs.append(bnb_s)
plt.plot(range(1,11),mnbs,label="多项式朴素贝叶斯")
plt.plot(range(1,11),bnbs,label="伯努利朴素贝叶斯")
plt.legend()
plt.show()

最终画图如下:

机器学习之朴素贝叶斯:Naive Bayesian(二、算法案例)_第7张图片 

可以看到多项式模型要略优于伯努利模型。 

 

 

 

 

 

 

你可能感兴趣的:(机器学习,机器学习)