求解:argmaxc P(c|w) -> argmaxc P(w|c)P©/P(w)
P©:文章中出现一个正确拼写词c的概率,也就是语料库中c出现的概率有多大
P(w|c):在用户想键入c的情况下敲成w的概率,也就是用户会以多大的概率把c敲错成w
argmaxc:用来枚举所有可能的c并且选取概率最大的
import re #正则表达式
from collections import defaultdict #
#定义一个函数将文本中所有的单词抽取出来,转换成小写并去除特殊字符
def words(text):
return re.findall("[a-z]+",text.lower())
#定义词频函数
def wordsFrequency(word):
#定义一个字典
model = defaultdict(lambda:1) #定义一个字典默认值为1,因为当我们遇到没有见过的新词,因为语料库没有这个词则返回的概率为0
#就是表示不能发生事件,而在我们的概率模型中我们期望用一个很小的概率代替这种情况,所以初始的词频都为1
print(type(model)) #<class 'collections.defaultdict'>
for w in word:
model[w] += 1 #如果语料库出现了这个词则加一
return model
nwords = wordsFrequency(words(open(r'big.txt').read()))
#print(nwords)
alphabet = "abcdefghijklmnopqrstuvwxyz"
#print(len(alphabet))
#编辑距离
#两个词之间的编辑距离定义为使用了几次插入(插入一个单字母)、删除、交换、替换的操作从一个词变到另一个词
def edits1(word): #返回所有与单词w编辑距离为1(做一次操作)的集合
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) for c in alphabet])
#与something编辑距离为2(做两个操作,如替换两个字母)的单词居然达到了114324个
def edits2(word): #编辑距离为2的集合
return set(e2 for e1 in edits1(word) for e2 in edits1(e1))
#按照编辑距离来算数据量太大,我们需要优化,只返回在语料库中出现的的词"smoothing","something","soothing"
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])
correctword = correct("morw")
print(correctword) #more