什么是贝叶斯算法
- 正向概率:假设袋子里有N个白球,M个黑球,那出黑球的概率有多大
- 逆向改率:假设不知道黑白球的分布,摸出一个或者多个球,观察后推测球的分布
- 正向概率容易求,而逆向概率却很难求,贝叶斯算法就是把逆向概率转换为正向概率来进行求解
- 公式 P(A|B)=P(B|A)P(A)P(B)
算法推理
男生占了60%,女生占了40%,男生总是穿长裤,女生则一半穿长裤一半穿裙子
正向概率:随机选取一个学生,他(她)穿长裤的概率和穿裙子的概率是多大
逆向概率:迎面走来一个穿长裤的学生,你只看得见他(她)穿的是否长裤,
而无法确定他(她)的性别,你能够推断出他(她)是女生的概率是多大吗?假设学校里面人的总数是 U 个
- 对面穿长裤的是女生的概率 P(Girl|Pants)=穿长裤女生的数量穿长裤的数量
- 穿长裤的女生 P(Pants|Girl)=U*P(Girl)*P(Pants|Girl)
- 所以穿长裤的数量=U*P(Pants)
- 所以 P(Girl|Pants)=U∗P(Girl)∗P(Pants|Girl)U∗P(Pants)
- 约去U等于 P(Girl|Pants)=P(Girl)∗P(Pants|Girl)P(Pants) ,也就是叶贝斯公式
朴素叶贝斯算法
- 假设所有的条件都是独立的,这样做虽然和实际情况有些差别,但是可以大量的减少计算量。
- 垃圾邮件过滤案例
- 如果词之间不是独立的,那么计算方式就是P(d1|h+) * P(d2|d1, h+) * P(d3|d2,d1, h+) * ..
- 假设词都是对的,计算方式简化为:P(d1|h+) * P(d2|h+) * P(d3|h+) *…
代码实现 - 拼写纠错
计算公式
- argmaxc P(c|w)=argmax P(w|c)P(c)/P(w)
- P(c|w):用户敲成w实际是c的概率
- P(c):文章中出现该单词的概率
- P(w|c):用户原本输入c的情况下,敲成w的概率,用距离算法表示
- argmax:枚举所有可能取最大值
# 获取数据
import re # 正则表达式
import collections
# 转小写后,返回a-z的所有内容
def words(text): return re.findall('[a-z]+',text.lower())
# 统计词频
def train(featrues):
# 获取一个字典,该字典如写入一个新的key,默认调用匿名函数lamdba:1,也就是默认值是1
dc = collections.defaultdict(lambda: 1)
for f in featrues:
dc[f] += 1
return dc
# 读取big.txt
data = words(open('big.txt').read())
# 统计词频
NWORDS = train(data)
alphabet ='abcdefghijklmnopqrstuvwxyz'
# 单词距离算法,距离为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]+word[i:] for i in range(n) for c in alphabet] # 插入一个字母
)
# 单词距离算法,距离为2
def 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)
# 贝叶斯,由于P(w)都是一样的,可以不计算。
def correct(word):
# 先取P(w|c)较大,即单词距离最近的
candidates = known([word]) or known(edits1(word)) or edits2(word) or [word]
# 再获取词频最大的的值
return max(candidates,key = lambda w:NWORDS[w])
#测试
correct('lovv')