前言

  之前在处理毕设的tweet发言数据集的时候,就发现了很多关键单词错误,那时就很zz的手动google翻译,然后手动修改的,在今天的购XX的笔试中,发现最后一题就是单词纠错器的实现,并且给了利用Bayes定理构建的思路,因此就尝试了一下,写出来了一个很简单的,但是距离交卷的时候交不上了,就放弃提交最后一题了,emmm,另说一句,笔试很难,nlp的道路还得慢慢走才行呀。

构建单词纠错器

原理

  纠错器的原理,利用Bayes定理来定义就是这样一个公式$$P(c|w)=\frac{P(w|c)\bullet P(c)}{P(w)}$$

  • $P(c)$:文章出现正确拼写词c的概率,程序中直接用词频表示
  • $P(w|c)$:用户把词c错敲成w的概率

实现步骤

  总共的步骤应为以下几步:

  • 统计语料中的所有单词以及其出现次数
  • 然后将单词变形,可以分为改变1位和改变2位,改变一位是可以删除、插入、替换、调换顺序等,改变两位字母就是先改变1位,再对改变后的单词改变一次,递归一下。(这里不进行3及其以上的迭代是因为写错3个的几率太小了!)
  • 接着判断新造的单词中,哪些单词是正确的单词。
  • 最后根据正确的单词中,选择在语料中频率最大的那个单词即可。

单词纠错器的实现

源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
from collections import Counter
import re

class WordCorrector():
def __init__(self):
self.ZIMU = list('abcdefghijklmnopqrstuvwxyz')
self.FILENAME="corpus.txt"
self.WORDSCOUNT=self.counts()

def counts(self):
# 统计语料中的所有单词和其出现的次数
with open(self.FILENAME,"r",encoding="utf-8") as f:
data=f.read()
words=re.findall("[a-z]+",data.lower())
return Counter(words)

def change_one(self, word):
length = len(word)
# 删除单词内每一个字母生成一组新的单词
new_words = [word[0:i] + word[i + 1:] for i in range(length)]
# 修改单词内的每一个字母成为其他词,生成新的一组单词
new_words += [word[0:i] + c + word[i + 1:] for i in range(length) for c in self.ZIMU]
# 在单词中的每一个间隔位中插入字母
new_words += [word[0:i] + c + word[i:] for i in range(length + 1) for c in self.ZIMU]
# 调换单词内字母位置
new_words += [word[0:i] + word[i + 1] + word[i] + word[i + 2:] for i in range(length - 1)]
return set(new_words)

def change_two(self, word):
# 将单词变换一个位数后,在变换一个位数,最后将原单词+变化一位的单词+变化两位的单词
return set(word_two for word_one in self.change_one(self.WORDSCOUNT) \
for word_two in self.change_one(word_one) \
if word_two in self.WORDSCOUNT)

def is_true_words(self, word):
# 判断word中的所有单词是否在语料中
return set(w for w in word if w in self.WORDSCOUNT)

def correct(self, word):
Possible_words= self.is_true_words([word]) \
or self.is_true_words(self.change_one(word)) \
or self.is_true_words(self.change_two(word)) \
or [word]
# 取概率最大的正确单词,即词频最多的
return max(Possible_words, key=lambda w: self.WORDSCOUNT[w])

if __name__ == '__main__':
WC = WordCorrector()
n=input("请输入单词:")
while(n):
print("猜你输入词:"+WC.correct(n))
print("*"*20+"NEXT"+"*"*20)
n=input("请输入单词:")

输出

1
2
3
4
5
6
7
8
请输入单词:hepl
猜你输入词:help
********************NEXT********************
请输入单词:leanr
猜你输入词:learn
********************NEXT********************
请输入单词:hlelo
猜你输入词:hello

源码及环境请见:https://github.com/netycc/Using-Bayes-Theorem-to-Construct-Word-Corrector

参考博客

贝叶斯定理拼写检查中的应用
Google研发总监Peter Norvig源码