AI智能
改变未来

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


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

[code]# 导入算法包以及数据集from sklearn.datasets import load_irisfrom sklearn.model_selection import train_test_splitfrom sklearn.metrics import classification_report,confusion_matrixfrom 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))

输出结果为:

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

二、语句情感分类 

导入库并下载数据: 

[code]import numpy as npimport mathdef 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#返回实验样本切分的词条和类别标签向量

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

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

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

[code]def setOfWords2Vec(vocabList, inputSet):returnVec = [0] * len(vocabList)#创建一个其中所含元素都为0的向量for word in inputSet:#遍历每个词条if word in vocabList:#如果词条存在于词汇表中,则置1returnVec[vocabList.index(word)] = 1else: 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操作来避免数据下溢。

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

[code]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   #分母初始化为2for 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#返回属于侮辱类的条件概率数组,属于非侮辱类的条件概率数组,文档属于侮辱类的概率

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

[code]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 1else:return 0def 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,\'属于非侮辱类\')#执行分类并打印分类结果

测试:

 

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

 三、垃圾邮件分类

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

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

首先导入库和数据:

[code]import osimport pandas as pdfrom sklearn.feature_extraction.text import TfidfVectorizerfrom sklearn.model_selection import train_test_split,cross_val_scorefrom sklearn.naive_bayes import MultinomialNB,BernoulliNB,GaussianNBfrom sklearn.metrics import classification_report,confusion_matriximport matplotlib.pyplot as pltdef 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 datasetdataset = getdata()

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

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

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

[code]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))

结果如下:

 

 

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

[code]%matplotlib inlineplt.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()

最终画图如下:

 

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

 

 

 

 

 

 

赞(0) 打赏
未经允许不得转载:爱站程序员基地 » 机器学习之朴素贝叶斯:Naive Bayesian(二、算法案例)