问题
如果我们看到用户输入一个不在字典中的词,我们需要推测他实际想要输入的词
使用贝叶斯公式表示:
p(实际想要输入词|用户输入) = p(实际想要输入词) * p(用户输入|实际想要输入词) / p(用户输入)
p(实际输入词) 表示的是这个词在语料库中出现的词频
p(用户输入|实际想要输入) 实际想要输入的词被输成用户输入的概率,即实际输入词与用户输入的编辑距离
D表示用户实际输入的词,h表示用户实际想要输入的词
p(h|D) = p(D|h) * p(h) / p(D)
我们通过比较p(h1|D), p(h2|D)... 哪个概率最大,就是哪个h,即用户实际想要输入的词
由于p(D) 都是相同的,所以我们不进行考虑
p(h)表示一个先验概率,即词频里面这个词的词频或者tf-dif 表示的是词频/log(所有的文章/出现这个词的文章的次数+1)
代码:
第一步:对输入的语料数据进行分词操作
第二步: 使用collections,构建字典的词的词频
第三步: 对输入的单词,进行可能性的变形
第四步: 对输入的单词,进行可能性的二次变形
第五步: 构建known函数,判断当前词是否在词典中
第六步: 提取出在字典中,词频最大的词语(分阶段性的判断)
import re, collections # 1. 将数据读入,根据空格, 进行分词操作 def text(words): # 使用正则化,如果遇到的不是字母,就断开 return re.findall('[a-z]+', words.lower()) # 2.统计列表中每个词的词频 def collection(words): # 默认初始的词频次数为1 model = collections.defaultdict(lambda :1) for word in words: model[word] += 1 return model # 构造词频字典 Ncollection = collection(text(open('big.txt', encoding='utf-8').read())) # 用于替换和增加 alpha = 'abcdefghijklmnopqrstuvwxyz' #3. 对输入的词进行可能性变化输出,即编辑距离为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 alpha] + [word[0:i] + c + word[i:] for i in range(n+1) for c in alpha]) # 4.在第一次变形的基础上进行第二次变化,即编辑距离为2 def edits2(word): return [e2 for e1 in edits1(word) for e2 in edits1(e1)] # 5.判断词是否在词袋里面,返回存在的列表 def known(words): return [word for word in words if word in Ncollection] # 6. 根据结果判断词频最大的 def correct(word): # or的作用,如果满足条件即返回的不是空值就停止,否者继续向下执行 known_words = known([word]) or known(edits1(word)) or known(edits2(word)) or [word] # 求出词典中词频最大的词,该词在known_words里面 return max(known_words, key=lambda x:Ncollection[x]) print(correct('wort'))