利用贝叶斯公式实现单词拼写纠正器

Odessa ·
更新时间:2024-09-21
· 987 次阅读

下面总结几个我在学习贝叶斯公式的时候能够对我的理解有所帮助的要点,首先引用一句话:

“概率论只不过把常识用数学公式表达了出来”——拉普拉斯

贝叶斯公式将人的思维方式用数学公式表达出来,所以贝叶斯公式在机器学习中的应用则是将人的思维赋予机器。
先抄一遍贝叶斯公式:
在这里插入图片描述
贝叶斯公式的直观理解就是,展示了先验概率跟后验概率之间的数学关系,那么什么是先验概率,后验概率又是什么呢?后验概率就是一个在已知结果的情况下,对这个结果的可能原因的概率推测,是一种事后的原因推测,所以叫后验,式中左边需要求解的P(A|B)就是后验概率,而当中的A可能存在多种基本事件,对于每个A都有一个后验概率值。相对应的先验概率就是在事件发生前对基本事件的概率预测,比如说我口袋里有四颗球,2颗白色,2颗黑色,我下一次从中抓一个球是黑色的概率就是1/2,这个是在我试验发生之前的预测,所以这个1/2就是先验概率。公式当中的P(A)就是一个先验概率,另外在公式中出现的P(B|A)就是类条件概率,这个就暂时按照条件概率这么理解吧。大多时候,后验概率都是一个比较难求解的值,所以贝叶斯公式就提供一种数学表达式,利用先验概率求解后验概率。

回到我们的例子当中,单词拼写纠正就是对已经写错了的单词,推测输入人想要输入的正确单词,这就是我们的后验概率P(A|B),原因是想输入A单词,结果是不小心输入了B单词。我们在推测他想输入的词的时候,这个正确的单词存在多种情况,所以A存在A1,A2,A3…多个事件,只不过每个事件都可以用公式求出后验概率,最终后验概率最大的那个事件作为纠正的结果。这个就是纠正器的整体思路。

展开这个贝叶斯公式之后,不管存在多少个可能事件A,他们的分母都是P(B),所以我们比较分子的大小就可以了。P(A)是先验概率,他的值就是下一个输入单词是A的概率,我们抛去主观原因,但从概率论的角度计算,它的概率就是已经输入的单词中,A出现的频率。分子中的P(B|A)的直观理解就是想输入正确的A,结果输入了错误的B的概率,这个很难量化,输错成某个单词的概率跟键盘的位置有关,又跟某人的手残程度有关,但是我们能够确定的是做一次修改的概率肯定远远大于做两次修改的概率(一次修改就是单词中对字母只做一次修改,修改包括增加、删除、替换、移动,这里移动只考虑邻近字母相互换位置,实际中也只存在这种错误)。所以如果有做一次修改就能变成正确单词,就绝对不会让做两次修改才能正确的单词作为它的纠正结果。那么对于只做一次就修正正确的单词,他的后验概率就只需要比较P(A)这个先验概率了,而P(A)可以根据词库中出现的单词频率得到。

最终得到思路:

读取词库,计算词频 汇总单词经过一次修改之后的单词集合 单词经过两次修改之后的单词集合 逐个比较,如果存在一次修正正确单词集合,则挑出该集合中最大词频单词;如果二次修正才能正确,挑出该集合中最大词频的单词 计算词频 import collections import re #读取语料库 file = open(r'big.txt','r') text = file.read() #正则表达式提取所有英文单次 words = re.findall('\w+',text.lower()) #英文单次计数 counter = collections.Counter(words) print(max(counter,key=counter.get),counter[max(counter,key=counter.get)]) 一次纠正的单词集合 #定义一次纠正可能得到的单词集合 def first_transformation(word): #26个字母构成的列表 letters = [chr(i) for i in range(97,123)] m = len(word) edit_word = [] for i in range(m): if i < m - 2: edit_word.append(word[0:i] + word[i+1] + word[i] + word[i+2:]) #移动,只考虑相邻两个之间的交换位置 edit_word.append(word[0:i] + word[i+1:]) #删除 for letter in letters: edit_word.append(word[0:i] + letter + word[i+1:]) #替换 edit_word.append(word[0:i] + letter + word[i:]) #增加 elif i == m - 2: edit_word.append(word[0:i] + word[i+1] + word[i]) #移动 edit_word.append(word[0:i] + word[i+1:]) #删除 for letter in letters: edit_word.append(word[0:i] + letter + word[i+1:]) #替换 edit_word.append(word[0:i] + letter + word[i:]) #增加 else: for letter in letters: edit_word.append(word[0:i] + letter + word[i:]) #增加 edit_word.append(word[0:i] + letter) #替换 edit_word.append(word[0:i]) #删除 return edit_word 二次纠正形成的单词集合 #二次纠正形成的单词集合 def second_transformation(word): edit2_word = [] first = first_transformation(word) for j in first: edit2_word.extend(first_transformation(j)) return edit2_word 逐个比较 #如果输入单词能在语料库中找到,则返回原单词 def itself(word): correct = set() if word in counter.keys(): correct.add(word) return correct #取备选集合跟语料库字典中的交集 def intersect(words): set_1 = set(counter.keys()) set_2 = set(words) correct_word = set_1.intersection(set_2) return correct_word #纠正器 def correct(word): correction = itself(word) or intersect(first_transformation(word)) or intersect(second_transformation(word)) frequency = {} if len(correction) == 0: return word else: for predict_word in correction: frequency[predict_word] = counter.setdefault(predict_word,0) return max(frequency,key=frequency.get)

最终的结果是即使需要修改两次也能找出正确单词,只不过准确率取决于词库当中的词频。
在这里插入图片描述
总结了这么多贝叶斯公式的要点,下面再扯一扯似然函数跟最大似然估计。假如把f(X|θ)当做一个θ固定的概率密度函数,那么反过来θ–>f(X|θ)就是认为X是固定的似然函数。似然函数一般写成L(θ|X)=f(X|θ)。

最大似然估计就是在θ的定义域中,似然函数取得最大值时θ的大小。意思就是后验概率取得最大值时,θ的取值

最大似然估计就是最符合实际情况的θ的取值。就是说结果已经发生了,既然能发生这个结果,那么发生这个结果的可能性一定要尽可能的大,所以一定是当前的后验概率取得最大值的θ取值作为最优解。


作者:宝藏杰罗米



贝叶斯 单词

需要 登录 后方可回复, 如果你还没有账号请 注册新账号