贝叶斯算法原理是通过贝叶斯公式将正向概率转换为逆向概率和先验概率之积
正向概率:袋子中有N个白球,n个黑球,摸个球是黑球的概率
逆向概率:并不知道黑球和白球的比例,先摸几个球,以结果推测袋中黑白球的比例
贝叶斯公式: ρ ( A ∣ B ) = P ( B ∣ A ) P ( A ) P ( B ) \rho(A | B)=\frac{P(B | A) P(A)}{P(B)} ρ(A∣B)=P(B)P(B∣A)P(A) P ( A i ∣ B ) = P ( B ∣ A i ) P ( A j ) ∑ j = 1 n P ( B ∣ A i ) P ( A j ) P\left(A_{i} | B\right)=\frac{P\left(B | A_{i}\right) P\left(A_{j}\right)}{\sum_{j=1}^{n} P\left(B | A_{i}\right) P\left(A_{j}\right)} P(Ai∣B)=∑j=1nP(B∣Ai)P(Aj)P(B∣Ai)P(Aj)
以拼写检查为例解释贝叶斯算法:
所求: P(猜测想输入的词 | 实际输入)
求解过程:1、猜测想输入的词有多个可能性:h1,h2,h3等,每一个可能性都会对应一个条件概率 P(hn | D),统一称它们为P(h | D)
2、根据贝叶斯公式: P ( h ∣ D ) = P ( h ) ∗ P ( D ∣ h ) / P ( D ) P(h | D)=P(h)^{*} P(D | h) / P(D) P(h∣D)=P(h)∗P(D∣h)/P(D)
3、式中 P ( h ) P(h) P(h)包含着 P ( h 1 ) P(h1) P(h1)、 P ( h 2 ) P(h2) P(h2)、 P ( h 3 ) P(h3) P(h3)等情况,表示hn这个词在语料库中出现的先验概率, P ( D ∣ h ) P(D | h) P(D∣h)代表想输入h单输入成D的概率, P ( D ∣ h ) P(D | h) P(D∣h)可以通过两个词之间的编辑距离来衡量
4、由于每个词的 P ( D ) P(D) P(D)值一样,所以忽略该值并比较其余值,即 P ( h ∣ D ) ∝ P ( h ) ∗ P ( D ∣ h ) P(h | D) \propto P(h)^{*} P(D | h) P(h∣D)∝P(h)∗P(D∣h),比较每一个词的 P ( h ∣ D ) P(h | D) P(h∣D)得出 P ( h ∣ D ) P(h | D) P(h∣D)最大的词
先验概率的意义:一般来说出现某个内容的概率的高低
以垃圾邮件为例解释贝叶斯分类器
需求:给定一封邮件,判定他是否属于垃圾邮件
D表示这封邮件的内容,h-表示垃圾邮件,h-表示正常邮件
过程:
1、 P ( h + ∣ D ) = P ( h + ) ∗ P ( D ∣ h + ) / P ( D ) P(h+| D)=P(h+) * P(D | h+) / P(D) P(h+∣D)=P(h+)∗P(D∣h+)/P(D) P ( h − ∣ D ) = P ( h − ) ∗ P ( D ∣ h − ) / P ( D ) P(h-| D)=P(h-) * P(D | h-) / P(D) P(h−∣D)=P(h−)∗P(D∣h−)/P(D)
2、 P ( h + ) P(h+) P(h+)、 P ( h − ) P(h-) P(h−)通过一个垃圾邮件库中正常邮件数 / 总邮件数,或者垃圾邮件数 / 总邮件数来确定
3、D中有N个单词d1,d2,d3,…,所以 P ( D ∣ h + ) = P ( d 1 , d 2 , . . , d n ∣ h + ) P(D | h+)=P(d 1, d 2, . ., d n | h+) P(D∣h+)=P(d1,d2,..,dn∣h+), P ( D ∣ h − ) = P ( d 1 , d 2 , . . , d n ∣ h − ) P(D | h-)=P(d 1, d 2, . ., d n | h-) P(D∣h−)=P(d1,d2,..,dn∣h−),这代表垃圾邮件中出现跟目标邮件一摸一样的邮件的概率
4、根据朴素贝叶斯假设:特征之间是独立的,互不影响的,将式子简化为 P ( d 1 , d 2 , … , d n ∣ h + ) = P ( d 1 ∣ h + ) ∗ P ( d 2 ∣ d 1 , h + ) ∗ P ( d 3 ∣ d 2 , d 1 , h + ) ∗ . . . \mathrm{P}(\mathrm{d} 1, \mathrm{d} 2, \ldots, \mathrm{d} \mathrm{n} | \mathrm{h}+)= \mathrm{P}(\mathrm{d} 1 | \mathrm{h}+)^{*} \mathrm{P}(\mathrm{d} 2 | \mathrm{d} 1, \mathrm{h}+)^{*} \mathrm{P}(\mathrm{d} 3 | \mathrm{d} 2, \mathrm{d} 1, \mathrm{h}+)^{*}... P(d1,d2,…,dn∣h+)=P(d1∣h+)∗P(d2∣d1,h+)∗P(d3∣d2,d1,h+)∗... P ( d 1 , d 2 , … , d n ∣ h − ) = P ( d 1 ∣ h − ) ∗ P ( d 2 ∣ d 1 , h − ) ∗ P ( d 3 ∣ d 2 , d 1 , h − ) ∗ . . . \mathrm{P}(\mathrm{d} 1, \mathrm{d} 2, \ldots, \mathrm{d} \mathrm{n} | \mathrm{h}-)= \mathrm{P}(\mathrm{d} 1 | \mathrm{h}-)^{*} \mathrm{P}(\mathrm{d} 2 | \mathrm{d} 1, \mathrm{h}-)^{*} \mathrm{P}(\mathrm{d} 3 | \mathrm{d} 2, \mathrm{d} 1, \mathrm{h}-)^{*}... P(d1,d2,…,dn∣h−)=P(d1∣h−)∗P(d2∣d1,h−)∗P(d3∣d2,d1,h−)∗...
5、比较计算结果 P ( d 1 , d 2 , … , d n ∣ h + ) \mathrm{P}(\mathrm{d} 1, \mathrm{d} 2, \ldots, \mathrm{d} \mathrm{n} | \mathrm{h}+) P(d1,d2,…,dn∣h+)和 P ( d 1 , d 2 , … , d n ∣ h − ) \mathrm{P}(\mathrm{d} 1, \mathrm{d} 2, \ldots, \mathrm{d} \mathrm{n} | \mathrm{h}-) P(d1,d2,…,dn∣h−)得出结果
import re
from collections import Counter
#将数据全部转换为小写并去除特殊字符
def words(text):
return re.findall(r'\w+', text.lower())
#读取现有数据库且计数
WORDS = Counter(words(open('big.txt').read()))#Counter类可以返回一个字典,键为被计数对象,值为计数结果
#计算比例
def P(word, N=sum(WORDS.values())):
return WORDS[word] / N
#计算编辑距离为1的词
#编辑距离:一个词变为另一个词需要几次编辑(删去字母、增加字母、交换字母位置、加入一个字母)
def edits1(word):
letters = 'abcdefghijklmnopqrstuvwxyz'
splits = [(word[:i], word[i:]) for i in range(len(word) + 1)]
deletes = [L + R[1:] for L, R in splits if R]
transposes = [L + R[1] + R[0] + R[2:] for L, R in splits if len(R) > 1]
replaces = [L + c + R[1:] for L, R in splits if R for c in letters]
inserts = [L + c + R for L, R in splits for c in letters]
return set(deletes + transposes + replaces + inserts)
#计算编辑距离为2的词
def edits2(word):
return (e2 for e1 in edits1(word) for e2 in edits1(e1))
#要求编辑距离的结果词处于语料库中
def known(words):
return set(w for w in words if w in WORDS)
#返回候选词
def candidates(word):
return (known([word]) or known(edits1(word)) or known(edits2(word)) or [word])#return or的结构:双True选左边
#选取候选词中出现比例最大的那个词作为最终返回词
def correction(word):
return max(candidates(word), key=P)#注意这里max函数制定了key,表示所有词带入P函数,并比较P函数的返回值
print(correction("dore"))