介绍
朴素贝叶斯是监督学习分类算法
分类方法:比如已知一个数据集由两类数据(类A,类B)组成,对于一个数据x,如果x属于A的概率大于x属于B的概率,那么x属于A类。
如何计算相关概率:使用条件概率进行分类
条件概率
在事件B发生的条件下事件A发生的概率\(p(A|B)\)
\(p(A|B)=\frac{p(A \cap B)}{p(B)}\)
\(p(A \cap B)=p(A|B){p(B)}\)
\(p(A \cap B)=p(B|A){p(A)}\)
所以可得贝叶斯公式
\(P(A | B)=\frac{P(A) P(B | A)}{P(B)}\)
其中先验概率p(A)后验概率p(A|B)
所以通过贝叶斯公式求得\(p(x|A)\)与\(p(a|B)\)的值进行比较,因为公式中p(x)都是相同的,所以实际只需要分别计算\(P(A) P(x | A)\)和\(P(B) P(x | B)\)比较即可
朴素的含义
在此算法中,是假定每一个属性是独立的,所以对于\(p(w_{i}|B)\)可由\(p(w_{1}|B)p(w_{2}|B)···p(w_{n}|B)\)得到
朴素贝叶斯实现方式
一种是贝努利模型(只考虑出不出现),一种是多项式模型(考虑属性出现的次数)
一篇贝叶斯算法的推导文章https://www.cnblogs.com/liuwu265/p/4685361.html
示例
采用多项式模型
比如有已知3篇文章
第一篇文章包含love,it,love是A类
第二篇文章包含it,dirty,ugly是B类
第三篇文章包含not,ugly是B类
现在第四篇文章包含love未知类,要判断它的类
1、统计词集
即将所有文章的词都加在这个集合中为{love,it,dirty,not,ugly}
2、转化为词向量
如第一篇文章有2个love,1个it
[[2 1 0 0 0 ]
[0 1 1 0 0]
[0 0 0 1 1]]
类别向量为[A,B,B]
3、计算类别概率
p(A)=\(\frac{1}{3}\)p(B)=\(\frac{2}{3}\)
每一个类中各词在该类所占的比例如第一行为\(p(w_{i}|A)\)
[[\(\frac{2}{3}\) \(\frac{2}{3}\) 0 0 0]
[0 \(\frac{1}{5}\) \(\frac{1}{5}\) \(\frac{1}{5}\) \(\frac{2}{5}\)]]
4、进行判断
对于第四篇也转换为向量为
[1 0 0 0 0 ]
计算\(P(A) P(x | A)\)为\(\frac{1}{3}(\frac{2}{3}\times 1+0+0+0+0)=\frac{2}{9}\)
和\(P(B) P(x | B)\)为\(\frac{2}{3}(0\times1 +0+0+0+0)=0\)
比较大小所以是A类
对垃圾邮件过滤程序
以下是对垃圾邮件分类的程序实例,数据来自《机器学习项目实战》第四章所附资源
import random import numpy as np import math import re # 用于统计所有的单词,输入从所有文档中提取的单词,输出这些文档的词集 def wordList(dataSet): # 字典的值不可重复,所以采用字典 wordSet = set([]) for i in dataSet: wordSet = wordSet | set(i) return list(wordSet) # 对每一篇文档的词,用于统计其是否在词集中,若在词集中次数加1,输入每一篇文档的词,输出词次数的向量 def signWord(wordVec, dataSet): signVec = np.zeros(len(wordVec)) for word in dataSet: if word in wordVec: signVec[wordVec.index(word)] += 1 return signVec # 训练函数,对于每一类,计算该类文档在所有文档中的比例(即每一类的概率),计算每一类的所有词(即属性)所占该类词集的比例(即已知这一类的情况下,该词的概率) # 输入包含文档的一个数组,每一列代表一个文档,输入每一个文档所对应的的属性的数组,返回每一类的所有词所占该类词集的比例(以数组形式输出,每一行代表一类)和每一类的概率(以字典形式输出,键为类名,值为比列) def train(trainData, trainCategory): numDoc, numWord = np.shape(trainData) # 得到数组的行数和列数,其实分别代表文档的个数,和词集所包含词的个数 # 用于统计每个类的个数 classCount = {} for key in trainCategory: classCount[key] = classCount.get(key, 0) + 1 # 用于计算每个类的概率 p_class = {} for key in classCount: p_class[key] = classCount[key] / len(trainCategory) p_num = np.ones((len(p_class), numWord)) # 防止下溢出初始化时不用0 p_sum = np.ones(len(p_class)) + 1 # 生成一个包含类名的列表 keys = list(p_class) # 遍历每一个文档 for i in range(numDoc): # 对每一个文档,查看是属于哪一个类 for j in range(len(p_class)): if trainCategory[i] == keys[j]: # 用于统计,该类中每个词的个数,对应的词上加上对应的词的个数 p_num[j] += trainData[i] # 用于统计该类所有的词数 p_sum[j] += sum(trainData[i]) break p_sum = p_sum.repeat(numWord).reshape(np.shape(p_num)) # 将其扩展为和p_num一样的形状,便于数组间计算 return np.log(p_num / p_sum), p_class # 防止下溢出,采用log # 分类函数,输出测试数据和train()输出的p和p_class,计算测试数据在每一类的概率,选择概率最大的,返回对应的类名 def classfy(testData, p, p_class): keys = list(p_class) classArrary = np.sum(testData * p, axis=1) classList = [] for i in range(len(p_class)): classList.append(classArrary[i] + math.log(p_class[keys[i]])) return keys[classList.index(max(classList))] # 用于提取文档的内容 def getData(str): # 去除任何非单词字符 data = re.split('\W+', str) return [word.lower() for word in data if len(word) > 0] # 对50封邮件的分类测试 def trainData(): wordsList = [] # 用于存放词集 docList = [] # 用于存放每篇文档的每个词,每一行代表一篇文档 classList = [] # 用于,存放每篇文档所对应的类别 for i in range(1, 26): str = getData( open(r'C:\Users\Desktop\我的文件\机器学习实战\machinelearninginaction\Ch04\email\ham\%d.txt' % i, encoding='utf8', errors='ignore').read()) # 对于一些识别不了的词,用errors='ignore'忽略 docList.append(str) wordsList.extend(str) classList.append(1) str = getData( open(r'C:\Users\Desktop\我的文件\机器学习实战\machinelearninginaction\Ch04\email\spam\%d.txt' % i, encoding='utf8', errors='ignore').read()) docList.append(str) wordsList.extend(str) classList.append(0) wordVec = wordList(wordsList) trainSet = list(range(50)) # 存放用于训练的文档的在docList中的序号 testSet = [] # 存放用于测试的文档的在docList中的序号 # 随机选取测试文档序号 for i in range(10): randIndex = int(random.uniform(0, len(trainSet))) testSet.append(trainSet[randIndex]) del (trainSet[randIndex]) # 进行训练 trainData = [] trainClass = [] for doc in trainSet: trainData.append(signWord(wordVec, docList[doc])) trainClass.append(classList[doc]) p, p_class = train(np.array(trainData), np.array(trainClass)) # 进行测试 errorCount = 0 for doc in testSet: testWordVec = signWord(wordVec, docList[doc]) if classfy(np.array(testWordVec), p, p_class) != classList[doc]: errorCount += 1 # 输出识别错误的概率 print(errorCount / len(testSet)) trainData()
来源:https://www.cnblogs.com/Qi-Lin/p/12274001.html