朴素贝叶斯算法与垃圾短信识别
·
Liam
关于朴素贝叶斯算法的介绍可谓前人之述备矣,在此不多加阐述。只要了解概率论中的全概率公式即可。这里主要结合一个具体例子进行分析,同时也是我的机器学习作业。
在运用之前要知道我们待处理问题的基本模型:
输入:一条样本
模型:训练样本(大量带标签的文本信息)
输出:布尔型答案(是垃圾短信/不是垃圾短信)
作为输入的样本需进行分词处理,即是把一条“尊敬的客户,您的手机将要爆炸,请充值话费。”变成“尊敬的
客户
您的
手机
将要
爆炸
请
充值
话费
”。
若设 $X$ 为词向量(统计量),$x_i$ 为第 $i$ 个词向量(样本), $y_j$ 代表分类结果。另设 $X^m$ 代表词向量中的第 $m$ 个元素,不难得:
此时假设所有样本互相独立(即所谓“朴素”),又有:
此时的分类器显然只用关心那些分母最大的取值($argmax$ 与 $max$ 区别在于前者关心输入即 $y_j$S):
最终,用极大似然估计思想实现上式关键部分:
如何解决某特征值为 0 的问题呢?在分子分母引入一个 $\lambda$ 即可,取个好听的名字叫拉普拉斯平滑因子。
代码实现:
from numpy import *
from functools import reduce
adClass = 1#广告、垃圾标识
def loadDataSet():
wordsList = [
['周六', '公司', '一起', '聚餐', '时间'],
['优惠', '返利', '打折', '优惠', '金融', '理财'],
['喜欢', '机器学习', '一起', '研究', '欢迎', '贝叶斯', '算法', '公式'],
['公司', '发票', '税点', '优惠', '增值税', '打折'],
['北京', '今天', '雾霾', '不宜', '外出', '时间', '在家', '讨论', '学习'],
['招聘', '兼职', '日薪', '保险', '返利']
]
classVec = [0, 1, 0, 1, 0, 1]
return wordsList, classVec
def doc2VecList(docList):
a = list(reduce(lambda x, y: set(x) | set(y), docList))
return a
def words2Vec(vecList, inputWords):
resultVec = [0] * len(vecList)
for word in inputWords:
if word in vecList:
resultVec[vecList.index(word)] = 1
return array(resultVec)
def trainNB(trainMatrix, trainClass):
numTrainClass = len(trainClass)
numWords = len(trainMatrix[0])
# 初始化概率向量,使用拉普拉斯平滑
p0Num = ones(numWords) # 非垃圾邮件类的词频统计
p1Num = ones(numWords) # 垃圾邮件类的词频统计
p0Words = 2.0 # 非垃圾邮件类的总词数
p1Words = 2.0 # 垃圾邮件类的总词数
# 统计词频
for i in range(numTrainClass):
if trainClass[i] == 1:
p1Num += trainMatrix[i]
p1Words += sum(trainMatrix[i])
else:
p0Num += trainMatrix[i]
p0Words += sum(trainMatrix[i])
p0Vec = log(p0Num / p0Words)
p1Vec = log(p1Num / p1Words)
pClass1 = sum(trainClass) / float(numTrainClass)
return p0Vec, p1Vec, pClass1
def classifyNB(testVec, p0Vec, p1Vec, pClass1) :
p1 = sum(testVec * p1Vec) + log (pClass1)
p0 = sum(testVec * p0Vec) + log(1 - pClass1)
if p0 > p1:
return 0
return 1
def printClass(words, testClass):
if testClass == adClass:
print(words, 'ad')
else:
print(words, 'notad')
def tNB() :
docList, classVec = loadDataSet()
allWordsVec = doc2VecList (docList)
trainMat = list (map(lambda x: words2Vec (allWordsVec,x), docList))
p0V, p1V, pClass1 = trainNB (trainMat, classVec)
testWords = ['公司','聚餐','讨论','贝叶斯']
testVec = words2Vec (allWordsVec,testWords)
testClass = classifyNB(testVec, p0V, p1V, pClass1)
printClass (testWords, testClass)
testWords = ['公司','保险','金融']
testVec = words2Vec (allWordsVec, testWords)
testClass = classifyNB(testVec, p0V, p1V, pClass1)
printClass (testWords, testClass)
if __name__ == '__main__':
tNB()