机器学习系列七:朴素贝叶斯
一、算法原理
贝叶斯公式描述了两个相关的随机事件或随机变量之间的概率关系。贝叶斯分类器使用贝叶斯公式计算样本属于某一类的条件概率值,并将样本判定为概率值最大的那个类。
贝叶斯公式为:
我们把P(A)称为"先验概率"(Prior probability),即在B事件发生之前,我们对A事件概率的一个判断。
P(A|B)称为"后验概率"(Posterior probability),即在B事件发生之后,我们对A事件概率的重新评估。
P(B|A)/P(B)称为"可能性函数"(Likelyhood),这是一个调整因子,使得预估概率更接近真实概率。
这一结论可以推广到随机变量。分类问题中样本的特征向量取值x与样本属性y具有因果关系。因为样本属于y,所以具有特征值x。贝叶斯分类器是在已知样本的特征向量为x的条件下反推样本所属的类别。根据贝叶斯公式有:
只要知道特征向量的概率分布p(x),每一个类出现的概率p(y),以及每一个类样本的条件概率p(y|x),就可以计算出样本属于每一个类的概率p(y|x)。分类问题只要预测类别,比较样本属于每一个类的概率的大小,找出该值最大的那一个类即可,因此可以忽略p(x),因为它对所有类都是相同的。简化后分类器的判别函数为
贝叶斯和朴素贝叶斯的概念是不同的,区别就在于“朴素”二字,朴素贝叶斯对条件个概率分布做了条件独立性的假设。朴素贝叶斯分类器假设特征向量的分量之间相互独立。
二、算法实践
1.离散型特征
以在线社区留言为例。为了不影响社区的发展,我们要屏蔽侮辱性的言论,所以要构建一个快速过滤器,如果某条留言使用了负面或者侮辱性的语言,那么就将该留言标志为内容不当。过滤这类内容是一个很常见的需求。对此问题建立两个类型:侮辱类和非侮辱类,使用1和0分别表示。(来自《机器学习实战》转载自http://blog.csdn.net/c406495762 )
# -*- coding: UTF-8 -*-
import numpy as np
from functools import reduce"""
函数说明:创建实验样本Parameters:无
Returns:postingList - 实验样本切分的词条classVec - 类别标签向量
Author:Jack Cui
Blog:http://blog.csdn.net/c406495762
Modify:2017-08-11
"""
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 #返回实验样本切分的词条和类别标签向量"""
函数说明:将切分的实验样本词条整理成不重复的词条列表,也就是词汇表Parameters:dataSet - 整理的样本数据集
Returns:vocabSet - 返回不重复的词条列表,也就是词汇表
Author:Jack Cui
Blog:http://blog.csdn.net/c406495762
Modify:2017-08-11
"""
def createVocabList(dataSet):vocabSet = set([]) #创建一个空的不重复列表for document in dataSet: vocabSet = vocabSet | set(document) #取并集return list(vocabSet)"""
函数说明:根据vocabList词汇表,将inputSet向量化,向量的每个元素为1或0Parameters:vocabList - createVocabList返回的列表inputSet - 切分的词条列表
Returns:returnVec - 文档向量,词集模型
Author:Jack Cui
Blog:http://blog.csdn.net/c406495762
Modify:2017-08-11
"""
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 #返回文档向量"""
函数说明:朴素贝叶斯分类器训练函数Parameters:trainMatrix - 训练文档矩阵,即setOfWords2Vec返回的returnVec构成的矩阵trainCategory - 训练类别标签向量,即loadDataSet返回的classVec
Returns:p0Vect - 侮辱类的条件概率数组p1Vect - 非侮辱类的条件概率数组pAbusive - 文档属于侮辱类的概率
Author:Jack Cui
Blog:http://blog.csdn.net/c406495762
Modify:2017-08-12
"""
def trainNB0(trainMatrix,trainCategory):numTrainDocs = len(trainMatrix) #计算训练的文档数目numWords = len(trainMatrix[0]) #计算每篇文档的词条数pAbusive = sum(trainCategory)/float(numTrainDocs) #文档属于侮辱类的概率p0Num = np.zeros(numWords); p1Num = np.zeros(numWords) #创建numpy.zeros数组,p0Denom = 0.0; p1Denom = 0.0 #分母初始化为0.0for i in range(numTrainDocs):if trainCategory[i] == 1: #统计属于侮辱类的条件概率所需的数据,即P(w0|1),P(w1|1),P(w2|1)···p1Num += trainMatrix[i]p1Denom += sum(trainMatrix[i])else: #统计属于非侮辱类的条件概率所需的数据,即P(w0|0),P(w1|0),P(w2|0)···p0Num += trainMatrix[i]p0Denom += sum(trainMatrix[i])p1Vect = p1Num/p1Denom #相除 p0Vect = p0Num/p0Denom return p0Vect,p1Vect,pAbusive #返回属于侮辱类的条件概率数组,属于非侮辱类的条件概率数组,文档属于侮辱类的概率"""
函数说明:朴素贝叶斯分类器分类函数Parameters:vec2Classify - 待分类的词条数组p0Vec - 侮辱类的条件概率数组p1Vec -非侮辱类的条件概率数组pClass1 - 文档属于侮辱类的概率
Returns:0 - 属于非侮辱类1 - 属于侮辱类
Author:Jack Cui
Blog:http://blog.csdn.net/c406495762
Modify:2017-08-12
"""
def classifyNB(vec2Classify, p0Vec, p1Vec, pClass1):p1 = reduce(lambda x,y:x*y, vec2Classify * p1Vec) * pClass1 #对应元素相乘p0 = reduce(lambda x,y:x*y, vec2Classify * p0Vec) * (1.0 - pClass1)print('p0:',p0)print('p1:',p1)if p1 > p0:return 1else: return 0"""
函数说明:测试朴素贝叶斯分类器Parameters:无
Returns:无
Author:Jack Cui
Blog:http://blog.csdn.net/c406495762
Modify:2017-08-12
"""
def testingNB():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)) #训练朴素贝叶斯分类器testEntry = ['love', 'my', 'dalmation'] #测试样本1thisDoc = np.array(setOfWords2Vec(myVocabList, testEntry)) #测试样本向量化if classifyNB(thisDoc,p0V,p1V,pAb):print(testEntry,'属于侮辱类') #执行分类并打印分类结果else:print(testEntry,'属于非侮辱类') #执行分类并打印分类结果testEntry = ['stupid', 'garbage'] #测试样本2thisDoc = np.array(setOfWords2Vec(myVocabList, testEntry)) #测试样本向量化if classifyNB(thisDoc,p0V,p1V,pAb):print(testEntry,'属于侮辱类') #执行分类并打印分类结果else:print(testEntry,'属于非侮辱类') #执行分类并打印分类结果if __name__ == '__main__':testingNB()
2.连续型特征
如果特征向量的分量是连续型随机变量,可以假设它们服从正态分布(高斯分布)。根据训练样本集可以计算出正态分布的均值和方差,这可以通过最大似然估计得到。连续型随机变量不能计算它在某一点的概率,因为它在任何一点处的概率为0。我们可以直接用概率密度函数的值作为概率值,得到各类别的概率。
我们通过高斯贝叶斯模型对Iris数据集进行花的类别识别。该数据集包含Iris花的三个品种(Iris setosa, Iris virginica and Iris versicolor)各50个样本,每个样本还有4个特征参数(分别是萼片<sepals>的长宽和花瓣<petals>的长 宽,以厘米为单位)。
(来自《统计学习方法》的python实现)
import numpy as np
import pandas as pd
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from collections import Counter
import math#data
def create_data():iris = load_iris()df = pd.DataFrame(iris.data, columns=iris.feature_names)df['label'] = iris.targetdf.columns = ['sepal length', 'sepal width', 'petal length', 'petal width', 'label']#data = df.iloc[:100,:]data = np.array(df)#print (data)return data[:,:-1],data[:,-1]class NaiveBayes:def __init__(self):self.model = None#数学期望@staticmethoddef mean(X):return sum(X) / float(len(X))#标准差(方差)def stdev(self, X):avg = self.mean(X)return math.sqrt(sum([pow(x-avg,2) for x in X]) / float(len(X)))#概率密度函数def gaussian_probability(self, x, mean, stdev):exponent = math.exp(-(math.pow(x-mean, 2)/(2*math.pow(stdev,2))))return (1/ (math.sqrt(2*math.pi) * stdev)) * exponent#处理X_traindef summarize(self, train_data):summarizes = [(self.mean(i), self.stdev(i)) for i in zip(*train_data)]return summarizes#分类别求出数学期望和标准差def fit(self, X, y):labels = list(set(y))data = {label:[] for label in labels}for f, label in zip(X, y):data[label].append(f)self.model = {label: self.summarize(value) for label, value in data.items()}return 'guassianNB train done'#计算概率def calculate_probabilities(self, input_data):probabilities = {}for label, value in self.model.items():probabilities[label] = 1for i in range(len(value)):mean, stdev = value[i]probabilities[label] *= self.gaussian_probability(input_data[i], mean, stdev)return probabilities#类别def predict(self, X_test):label = sorted(self.calculate_probabilities(X_test).items(), key=lambda x: x[-1])[-1][0]return labeldef score(self, X_test, y_test):right = 0for X,y in zip(X_test, y_test):label = self.predict(X)if label == y:right += 1return right / float(len(X_test))if __name__ == '__main__':X,y = create_data()X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)model = NaiveBayes()model.fit(X_train, y_train)score = model.score(X_test, y_test)print(score)pre_label = model.predict([4.4, 3.2, 1.3, 0.2])print(pre_label)
3.sklearn实现
朴素贝叶斯是一类比较简单的算法,scikit-learn中朴素贝叶斯类库的使用也比较简单。在scikit-learn中,一共有3个朴素贝叶斯的分类算法类。分别是GaussianNB,MultinomialNB和BernoulliNB。其中GaussianNB就是先验为高斯分布的朴素贝叶斯,MultinomialNB就是先验为多项式分布的朴素贝叶斯,而BernoulliNB就是先验为伯努利分布的朴素贝叶斯。
官方英文文档地址:http://scikit-learn.org/dev/modules/generated/sklearn.naive_bayes.MultinomialNB.html
import numpy as np
import pandas as pd
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import GaussianNB, BernoulliNB, MultinomialNB #高斯模型、伯努利模型、多项式模型#data
def create_data():iris = load_iris()df = pd.DataFrame(iris.data, columns=iris.feature_names)df['label'] = iris.targetdf.columns = ['sepal length', 'sepal width', 'petal length', 'petal width', 'label']#data = df.iloc[:100,:]data = np.array(df)#print (data)return data[:,:-1],data[:,-1]if __name__ == '__main__':X,y = create_data()X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)clf = GaussianNB()clf.fit(X_train, y_train)score = clf.score(X_test, y_test)print(score)pre_label = clf.predict([[4.4, 3.2, 1.3, 0.2]])print(pre_label)
三、算法总结
朴素贝叶斯优点:
- 生成式模型,通过计算概率来进行分类,可以用来处理多分类问题。
- 对小规模的数据表现很好,适合多分类任务,适合增量式训练,算法也比较简单。
- 对数据的训练快,分类也快
朴素贝叶斯缺点:
- 对输入数据的表达形式很敏感。
- 由于朴素贝叶斯的“朴素”特点,所以会带来一些准确率上的损失。
- 需要计算先验概率,分类决策存在错误率。
应用场景:
- 文本分类/垃圾文本过滤/情感判别
- 多分类实时预测
- 推荐系统
四、面试题
1.什么是贝叶斯决策理论? 贝叶斯决策理论是主观贝叶斯派归纳理论的重要组成部分。贝叶斯决策就是在不完全情报下。对部分未知的状态用主观概率估计,然后用贝叶斯公式对发生的概率进行修正,最后利用期望值和修正概率做出最优决策(选择概率最大的类别)。其基本思想是:(1)已知类条件概率密度参数表达式和先验概率(2)利用贝叶斯公式转化为后验概率(3)根据后验概率大小进行决策分类
2.朴素贝叶斯算法的前提假设是什么? 朴素贝叶斯则是建立在两个前提假设上的:(1)特征之间相互独立(2)每个特征同等重要
3.什么是朴素贝叶斯的零概率问题? 零概率问题,就是在计算实例的概率时,如果某个量x,在训练集中未出现过,会导致整个实例的概率结果为0。可以使用拉普拉斯平滑解决,具体做法是给分子分母同时加上一个正数。如果特征分量的取值有k种情况,将分母加上k,每个类的分子加上1,这样可以保证所有类的条件概率加起来还是1。
4.当数据的属性是连续变量时,朴素贝叶斯算法如何处理? 当数据的属性是连续变量时,有两种方法可以计算属性的条件概率。(1)把一个连续的属性离散化,然后用相应的离散区间替换连续值。(2)假设连续变量服从某种概率分布,然后使用训练数据估计分布的参数,例如使用高斯分布。
5.朴素贝叶斯有哪几种常用的分类模型? 朴素贝叶斯的三个常用模型:高斯、多项式、伯努利
6.高度相关的特征对朴素贝叶斯有什么影响? 假设有两个特征高度相关,相当于该特征在模型中发挥了两次作用(计算两次条件概率),使得朴素贝叶斯获得的结果向该特征所希望的方向进行了偏移,影响了最终结果的准确性,所以朴素贝叶斯算法应先处理特征,把相关特征去掉。
机器学习系列七:朴素贝叶斯相关推荐
- 机器学习实战之朴素贝叶斯
机器学习实战之朴素贝叶斯 一.朴素贝叶斯算法概述 1.贝叶斯决策理论 2.条件概率 3.全概率公式 4.贝叶斯推断 5.朴素贝叶斯推断 二.实战 三.总结 1.朴素贝叶斯推断的一些优点: 2.朴素贝叶 ...
- 《机器学习实战》朴素贝叶斯
机器学习实战的朴素贝叶斯一章中的源文件老是提示 IndexError: range object index out of range 看源码里怎么都不会溢出啊,除非minLen为0:所以看了下测试集 ...
- 机器学习面试题——朴素贝叶斯
机器学习面试题--朴素贝叶斯 提示:这些知识点也是大厂笔试经常考的题目,我记得阿里和京东就考!!!想必在互联网大厂就会用这些知识解决实际问题 朴素贝叶斯介绍一下 朴素贝叶斯优缺点 贝叶斯公式 朴素贝叶 ...
- 机器学习:基于朴素贝叶斯对花瓣花萼的宽度和长度分类预测
机器学习:基于朴素贝叶斯对花瓣花萼的宽度和长度分类预测 作者:i阿极 作者简介:Python领域新星作者.多项比赛获奖者:博主个人首页
- 机器学习实验:朴素贝叶斯算法
机器学习实验:朴素贝叶斯算法 问题如下: 根据给出的算法naivebayes.py,实现: 1.将数据集文件naivebayes_data.csv中的数据替换成14天打球与天气数据: 2.预测样本{O ...
- 【机器学习算法笔记系列】朴素贝叶斯(NB)算法详解和实战
朴素贝叶斯(NB)算法概述 朴素贝叶斯(Naïve Bayes, NB)算法,是一种基于贝叶斯定理与特征条件独立假设的分类方法.朴素:特征条件独立:贝叶斯:基于贝叶斯定理.属于监督学习的生成模型,实现 ...
- python机器学习库sklearn——朴素贝叶斯分类器
分享一个朋友的人工智能教程.零基础!通俗易懂!风趣幽默!还带黄段子!大家可以看看是否对自己有帮助:点击打开 全栈工程师开发手册 (作者:栾鹏) python数据挖掘系列教程 文档贝叶斯分类器的相关的知 ...
- 机器学习理论学习:朴素贝叶斯
最近一直在看<统计学习方法>,打算先把理论搞明白,后续将着重用c++实现下自己ml库,计划就是这样,好好干吧.其实在平常中使用这个算法比较少,但他主要的优势是在少量,几十或几百张样本的情况 ...
- 垃圾邮件分类快速理解机器学习中的朴素贝叶斯(Naive Bayes)
贝叶斯方法是一个历史悠久,有着坚实的理论基础的方法,同时处理很多问题时直接而又高效,很多高级自然语言处理模型也可以从它演化而来.因此,学习贝叶斯方法,是研究自然语言处理问题的一个非常好的切入口. 其实 ...
- 【机器学习基础】朴素贝叶斯的算法实现
前言 本次我们将梳理下朴素贝叶斯(Naive Bayes)的相关内容. 本文约1.6k字,预计阅读10分钟. 概要 朴素贝叶斯算法是一种适用于二分类和多分类分类问题的「分类算法」.在贝叶斯概率框架下, ...
最新文章
- NandFlash系列之一:NorFlash与NandFlash对比
- MySQL返回多行错误怎么处理_结果包含多个行错误mysql
- Photoshop简单制作绿色暗调风景图
- 数据结构 稀疏矩阵的实现方法
- 网络编程模型 / Reactor
- Android XML文件中设置字体
- docker centos ssh
- mysql xdevapi_MySql Connector/C++8简介
- DIY 主机 所有AMD IntelCPU及主板
- 机器学习训练营_如何不运行学习代码训练营
- Centos7下更改docker镜像和容器的默认路径
- windows xp 创建 Oracle(11G)数据库实例时写入系统日志失败解决方案
- 2019年老电脑E5450+硬改775 无故死机故障排除记录
- 什么是 jsp,什么是Servlet?jsp 和Servlet 有什么区别?
- 不到90天的时间,备考数据库系统工程师还来得及吗?
- ip地址中保留地址讲解
- 图像处理: AlphaBlend
- 计算机怎么格式化电脑吗,电脑怎么格式化
- c语言 将数组转化成二叉树
- 干货:一个案例看懂“结巴”分词(Jieba),入行NLP必备