小项目--贝叶斯实现拼写检查

求解: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

猜你喜欢

转载自blog.csdn.net/fenfenxhf/article/details/82953810