原创文章,如需转载请保留出处
本博客为唐宇迪老师python数据分析与机器学习实战课程学习笔记
一.贝叶斯算法概述
1.1贝叶斯简介:
1.2贝叶斯要解决的问题
1.3 为什么使用贝叶斯
1.4 举个例子
假设男生占60%,女生占40%。男生总是穿长裤,女生则一半穿长裤一半穿裙子
二.贝叶斯推导实例
假设学校里面人的总数是U个
穿长裤的(男生):U * P(Boy)* P(Pants | Boy)
求解:穿长裤的人里面有多少女生?
化简:
P(Girl | Pants) =P(Girl)* P(Pants | Girl) / [ P(Boy)* P(Pants | Boy) + P(Girl)* P(Pants | Girl)]
分母其实就是P(Pants)
分子其实就是P(Pants,Girl)
贝叶斯公式:
P(A | B) = P(B | A)P(A) / P(B)
三.贝叶斯拼写纠错实例
3.1 拼写纠正实例
3.2 解决问题
用户实际输入的单词为D(D代表Data,即观测数据)
3.3 解决问题
用户实际输入的单词记为D(D代表Data,即观测数据)
3.4 解决问题
四.垃圾邮件过滤实例
4.1 模型比较理论1
4.2 模型比较理论2
4.3 问题
五.贝叶斯实现拼写检查器
5.1 实现一个简单的拼写检查器
import re, collections
def words(text): return re.findall('[a-z]+',text.lower())
def train(features):
model = collections.defaultdict(lambda: 1)
for f in features:
model[f] += 1
return model
NWORDS = train(words(open('big.txt').read()))
alphabet = 'abcdefghijklmnopqrstuvwxyz'
def edits1(word):
n = len(word)
return set([word[0:i]+word[i+1:] for i in range(n)] +
[word[0:i]+word[i+1]+word[i]+word[i+2:] for i in range(n-1)] +
[word[0:i]+c+word[i+1:] for i in range(n) for c in alphabet] +
[word[0:i]+c+word[i:] for i in range(n+1) for c in alphabet] )
def know_edits2(word):
return set(e2 for e1 in edits1(word) for e2 in edits1(e1) if e2 in NWORDS)
def known(words): return set(w for w in words if w in NWORDS)
def correct(word):
candidates = known([word]) or known(edits1(word)) or known_edits2(word) or [word]
return max(candidates,key=lambda w: NWORDS[w])
测试:
correct('morw')
‘more’
correct('appl')
‘apply’
5.2 求解
argmaxc P(c|w) ->argmaxc P(w|c)P©/P(w)
#把语料中的单词全部抽取出来,转成小写,并且去除单词中间的特殊符号
def words(text): return re.findall('[a-z]+',text.lower())
def train(features):
model = collections.defaultdict(lambda: 1)
for f in features:
model[f] += 1
return model
NWORDS = train(words(open('big.txt').read()))
要是遇到我们从来没有见过的新词怎么办,假如说一个词拼写完全正确,但是语料库中没有包含这个词,从而这个词也永远不会出现在训练集中,于是,我们就要返回出现这个词的概率是0。这个情况不太妙,因为概率为0这个代表了这个事件绝对不可能发生,而在我们的概率模型中,我们期望用一个很小的概率来代表这种情况。lambda:1
5.3 编辑距离
两个词之间的编辑距离定义为使用了几次插入(在词中插入一个单字母),删除(删除一个单字母),交换(交换相邻两个字母),替换(把一个字母换成另外一个)的操作从一个词变成另一个词。
#返回所有与单词w编辑距离为1的集合
def edits1(word):
n = len(word)
return set([word[0:i]+word[i+1:] for i in range(n)] +
[word[0:i]+word[i+1]+word[i]+word[i+2:] for i in range(n-1)] +
[word[0:i]+c+word[i+1:] for i in range(n) for c in alphabet] +
[word[0:i]+c+word[i:] for i in range(n+1) for c in alphabet] )
与something编辑距离为2的单词居然达到了114324个
优化:在这些编辑距离小于2的词中间,只把那些正确的词作为候选词,只能返回3个单词:‘smoothing’,‘something’,‘soothing’
#返回所有与单词w编辑距离为2的集合
#在这些编辑距离小于2的词中间,只把那些正确的词作为候选词
def know_edits2(word):
return set(e2 for e1 in edits1(word) for e2 in edits1(e1) if e2 in NWORDS)
正常来说把一个元音拼成另一个的概率要大于辅音(因为人常常把hello打成hallo这样);把单词的第一个字母拼错的概率会相对小,等等,但是为了简单起见,选择了一个简单的方法:编辑距离为1的正确单词比编辑距离为2的优先级高,而编辑距离为0的正确单词优先级比编辑距离为1的高。
def known(words): return set(w for w in words if w in NWORDS)
#如果know(set)非空,candidate就会选择这个集合,而不继续计算后面的
def correct(word):
candidates = known([word]) or known(edits1(word)) or known_edits2(word) or [word]
return max(candidates,key=lambda w: NWORDS[w])