广告
返回顶部
首页 > 资讯 > 后端开发 > Python >英文单词拼写纠错
  • 310
分享到

英文单词拼写纠错

英文单词 2023-01-31 00:01:08 310人浏览 泡泡鱼

Python 官方文档:入门教程 => 点击学习

摘要

在知乎上看到了一个问题“有哪些你喜欢的逻辑清晰,书写优雅的源代码呢?” 有人po出了大神Peter Norvig的‘Spelling Corrector’(拼写检查器)  by Http://norvig.com/spell-correc

在知乎上看到了一个问题“有哪些你喜欢的逻辑清晰,书写优雅的源代码呢?”

有人po出了大神Peter Norvig的‘Spelling Corrector’(拼写检查器) 

by Http://norvig.com/spell-correct.html

文章大意:2007年的一个星期,两位朋友(迪恩和比尔)独立告诉我,他们对谷歌的拼写纠正感到惊讶。输入类似spelling的搜索,Google会立即显示结果: 拼写。我认为Dean和Bill是高度成熟的工程师和数学家,他们对这个过程的运作方式有很好的直觉。但他们没有,并且想到它,为什么他们应该知道迄今为止他们的专长?

我认为他们和其他人可以从解释中受益。工业强度法术纠正器的全部细节非常复杂。但我认为,在横贯大陆的飞机旅行过程中,我可以编写和解释一个玩具拼写校正器,在大约半页代码中以每秒至少10个字的处理速度达到80%或90%的准确度。

源代码如下:

 1 import re
 2 from collections import Counter
 3 
 4 #==== 训练一个带有概率的词库 ====
 5 def Words(text): 
 6     return re.findall(r'\w+', text.lower())
 7 
 8 WORDS = Counter(words(open('d:\\big.txt').read()))
 9 
10 def P(word, N=sum(WORDS.values())): 
11     "Probability of `word`."
12     return WORDS[word] / N
13 
14 #==== 给定单词A,枚举所有可能正确的拼写 ====
15 def edits1(word):
16     "All edits that are one edit away from `word`."
17     letters    = 'abcdefghijklmnopqrstuvwxyz'
18     splits     = [(word[:i], word[i:])    for i in range(len(word) + 1)]
19     deletes    = [L + R[1:]               for L, R in splits if R]
20     transposes = [L + R[1] + R[0] + R[2:] for L, R in splits if len(R)>1]
21     replaces   = [L + c + R[1:]           for L, R in splits if R for c in letters]
22     inserts    = [L + c + R               for L, R in splits for c in letters]
23     return set(deletes + transposes + replaces + inserts)
24 
25 def edits2(word): 
26     "All edits that are two edits away from `word`."
27     return (e2 for e1 in edits1(word) for e2 in edits1(e1))
28 #==== 返回候选词  ====
29 def candidates(word): 
30     "Generate possible spelling corrections for word."
31     return (known([word]) or known(edits1(word)) or known(edits2(word)) or [word])
32 
33 def known(words): 
34     "The subset of `words` that appear in the dictionary of WORDS."
35     return set(w for w in words if w in WORDS)
36 
37 #==== 输出概率最大的纠正词  ====
38 def correction(word): 
39     "Most probable spelling correction for word."
40     return max(candidates(word), key=P)

其实自己没有其他博主的讲解是真的看不懂,甚至单词还有自己google翻译......我真是tcl......

 

 一些概率知识

拼写检查器的目的是找到最近似错误输入“w”的正确拼写,但是对于一个错误拼写,其正确的候选者有很多(例如:“lates”应该被纠正为“late”呢,还是“lattes”呢?)。因此我们可以采取概率的思路,在错误拼写w出现的条件下,选择所有可能的备选纠正单词c中概率最大的。 

 

由贝叶斯公式可得:  

由于P(w)P(w) 对于每个待选择的c都是一样大小的,因此我们就忽略这个因素,最终公式变形为: 

 

这个公式中由四个主要的部分:
选择机构:argmax 
我们选择备选单词中概率最高的单词作为输出。
备选模型:c∈candidatesc∈candidates 
这一部分告诉我们考虑哪些单词作为备选。
语言模型:P(c)
单词c出现在语料库中的概率。例如,在一个英文语料库中,有7%的单词是“the”,那么P(the)=0.07P(the)=0.07
错误模型: P(w|c)
当用户想输入C时,错输入成w的概率。例如,P(teh|the)P(teh|the)应该远大于P(theeexyz|the)P(theeexyz|the)。

我们用条件概率 P(w|c)P(w|c) 和先验概率P(c)P(c) 这两个便于考虑和学习的因素替代了后延概率P(c|w)P(c|w) ,这样问题更容易分析和解决。

 

python具体实现过程

1、选择机构 :Python的max函数实现 
2、备选模型 :通过一些简单的操作(edits),生成一个set作为备选单词库。如:删除一个字母(deletions),交换两个字母的位置(transposes),把一个字母替换成另一个字母(replacement),增加一个字母(insertion)。通过这几个常见的拼写错误,可以扩展出一系列的备选单词,形成一个set。

这是一个很大的set,因为对于一个长度为n的单词,会生成n个deletions,n-1个transpositions,26n个replacements,16(n+1)个insertions,总共是(54n+25)个可能性。例如:

>>> len(edits1('somthing'))
442

然而我们可以定义一个识别这些生成的备选单词正确性的模块,只匹配词典中存在的词。这个set将会变得很小,因为随机生成单词中,许多都是非法拼写的,并非真正存在。

def known(words): return set(w for w in words if w in WORDS)

>>> known(edits1('somthing'))
{'something', 'soothing'}

同样,我们考虑经过两步骤的简单操作(edits)后得到的纠错备选模型(例如,写错了两个字母,写掉了两个字母),经过两次简单操作的组和将会生成更多的备选单词,但是也仅有很少一部分是正确拼写的单词,例如:

def edits2(word): return (e2 for e1 in edits1(word) for e2 in edits1(e1))

>>> len(set(edits2('something'))
90902

>>> known(edits2('something'))
{'seething', 'smoothing', 'something', 'soothing'}

>>> known(edits2('somthing'))
{'loathing', 'nothing', 'scathing', 'seething', 'smoothing', 'something', 'soothing', 'sorting'}

经过edits2(w)处理的单词,与原始单词w的edit distance(不知道怎么翻译,翻译为编辑距离?) 为2。

 

3、语言模型 

我们通过统计在语料库中某个词(word)出现的频率来衡量一个词的先验概率P(word)P,这里我们使用一个语料库big.txt来构建我们的语言模型。这个语料库含有100万个单词,里面包含一本书和一些常见词汇的列表。定义函数 word 来把语料文本打碎成一个一个单词的形式,然后构建一个计数器counter,统计每个词的出现频率,概率P代表了每个词出现的概率:

def words(text): return re.findall(r'\w+', text.lower())

WORDS = Counter(words(open('big.txt').read()))

def P(word, N=sum(WORDS.values())): return WORDS[word] / N

通过一些简单的NLP操作,我们可以看到这里有32192个单词,所有单词一共出现了1115504次,’the’是出现概率最大的,一共出现了79808次:

>>> len(WORDS)
32192

>>> sum(WORDS.values())
1115504

>>> WORDS.most_common(10)
[('the', 79808),
 ('of', 40024),
 ('and', 38311),
 ('to', 28765),
 ('in', 22020),
 ('a', 21124),
 ('that', 12512),
 ('he', 12401),
 ('was', 11410),
 ('it', 10681),
 ('his', 10034),
 ('is', 9773),
 ('with', 9739),
 ('as', 8064),
 ('i', 7679),
 ('had', 7383),
 ('for', 6938),
 ('at', 6789),
 ('by', 6735),
 ('on', 6639)]

>>> max(WORDS, key=P)
'the'

>>> P('the')
0.07154434228832886

>>> P('outrivaled')
8.9645577245801e-07

>>> P('unmentioned')
0.0

定义出一个函数candidates(),根据优先级产生一个非空的候选单词序列:

优先级排序如下
1、原始单词
2、与原始单词的edit distance为1的单词(即经过一次编辑产生的那些拼写) 
3、与原始单词的edit distance为2的单词(即经过两次编辑产生的那些拼写) 
4、原始单词,即使那些单词是词典中没有的。

因此我们把条件概率模块替换成了这样一种优先级的排序。或许这其中还有很多不完善的地方,如根据什么别的语料库统计到,人们写单词写错的时候是写掉一个字母比多加一个字母常见,交换两个字母比写错一个字母常见等这些规则是我们在没学习也没数据的时候未知的,也是你在定义自己的拼写纠错器时,可以自己考虑的内容。因为我们现在只是一个玩具代码,所以我们采取了这样一个简单的优先级排序模式来替代这个重要的部分。

def correction(word): return max(candidates(word), key=P)

def candidates(word): 
    return known([word]) or known(edits1(word)) or known(edits2(word)) or [word]

 

模型评价

作者用一个牛津大学的数据集测评了自己的玩具代码,当你完善了自己的纠错模型之后,或许你也可以通过这个方式来测试一下你模型的准确率。测试的代码如下:

def unit_tests():
    assert correction('speling') == 'spelling'              # insert
    assert correction('korrectud') == 'corrected'           # replace 2
    assert correction('bycycle') == 'bicycle'               # replace
    assert correction('inconvient') == 'inconvenient'       # insert 2
    assert correction('arrainged') == 'arranged'            # delete
    assert correction('peotry') =='poetry'                  # transpose
    assert correction('peotryy') =='poetry'                 # transpose + delete
    assert correction('word') == 'word'                     # known
    assert correction('quintessential') == 'quintessential' # unknown
    assert words('This is a TEST.') == ['this', 'is', 'a', 'test']
    assert Counter(words('This is a test. 123; A TEST this is.')) == (
           Counter({'123': 1, 'a': 2, 'is': 2, 'test': 2, 'this': 2}))
    assert len(WORDS) == 32192
    assert sum(WORDS.values()) == 1115504
    assert WORDS.most_common(10) == [
     ('the', 79808),
     ('of', 40024),
     ('and', 38311),
     ('to', 28765),
     ('in', 22020),
     ('a', 21124),
     ('that', 12512),
     ('he', 12401),
     ('was', 11410),
     ('it', 10681)]
    assert WORDS['the'] == 79808
    assert P('quintessential') == 0
    assert 0.07 < P('the') < 0.08
    return 'unit_tests pass'

def spelltest(tests, verbose=False):
    "Run correction(wrong) on all (right, wrong) pairs; report results."
    import time
    start = time.clock()
    good, unknown = 0, 0
    n = len(tests)
    for right, wrong in tests:
        w = correction(wrong)
        good += (w == right)
        if w != right:
            unknown += (right not in WORDS)
            if verbose:
                print('correction({}) => {} ({}); expected {} ({})'
                      .fORMat(wrong, w, WORDS[w], right, WORDS[right]))
    dt = time.clock() - start
    print('{:.0%} of {} correct ({:.0%} unknown) at {:.0f} words per second '
          .format(good / n, n, unknown / n, n / dt))

def Testset(lines):
    "Parse 'right: wrong1 wrong2' lines into [('right', 'wrong1'), ('right', 'wrong2')] pairs."
    return [(right, wrong)
            for (right, wrongs) in (line.split(':') for line in lines)
            for wrong in wrongs.split()]

print(unit_tests())
spelltest(Testset(open('spell-testset1.txt'))) # Development set
spelltest(Testset(open('spell-testset2.txt'))) # Final test set

下载地址: spell-testset1  http://norvig.com/spell-testset1.txt

spell-testset2.txt   http://norvig.com/spell-testset1.txt

unit_tests pass
75% of 270 correct at 41 words per second
68% of 400 correct at 35 words per second
None

前人栽树,后人乘凉。感谢前人的经验分享与讲解,让后辈们受益颇多,也特此感谢博主irfan_lcmll的分享https://blog.csdn.net/qq_27879381/article/details/63351483

 

另附自动纠错GitHub其他开源代码https://github.com/phatpiglet/autocorrect

 

--结束END--

本文标题: 英文单词拼写纠错

本文链接: https://www.lsjlt.com/news/181844.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 英文单词拼写纠错
    在知乎上看到了一个问题“有哪些你喜欢的逻辑清晰,书写优雅的源代码呢?” 有人po出了大神Peter Norvig的‘Spelling Corrector’(拼写检查器)  by http://norvig.com/spell-correc...
    99+
    2023-01-31
    英文单词
  • 英文单词缩写----DXNRY – Dictionary 字典
    由于英文的字母太多,不方便的时候发短信很慢,所以外国人很多都在短信上输入 缩写 ,这样就节省了很多时间。花了好久才把这些 缩写 给整理出来,唯一在这里需要说明的是,不是所有的人都明白这些 缩写...
    99+
    2022-10-18
  • 怎么用Python编写一个拼写纠错器
    这篇文章主要介绍“怎么用Python编写一个拼写纠错器”,在日常操作中,相信很多人在怎么用Python编写一个拼写纠错器问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么用Python编写一个拼写纠错器”的疑...
    99+
    2023-06-04
  • Win10怎么开启英文输入法的纠错功能?win10开启英文输入法纠错功能的方法
      Win10怎么开启英文输入法的纠错功能?有些人对英文单词不熟悉,输入英文的时候总是会出错。其实Win10的英文输入法里有自动纠错的功能。就算你不小心拼错了单词,输入法也能帮你输入正确的字母。那么Win10如何开启英文...
    99+
    2023-05-19
    Win10 英文输入法 纠错
  • Linux 中纠正拼写错误的Bash 命令方法
    我知道你可以按下向上箭头来调出你运行过的命令,然后使用左/右键移动到拼写错误的单词,并更正拼写错误的单词,最后按回车键再次运行它,对吗?可是等等。还有一种更简单的方法可以纠正 GNU/linux 中拼写错误的 Bash ...
    99+
    2022-06-04
    linux 拼写错误 bash 命令
  • Linux中如何纠正拼写错误的Bash命令
    这篇文章主要介绍了Linux中如何纠正拼写错误的Bash命令,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。我知道你可以按下向上箭头来调出你运行过的命令,然后使用左/右键移动到...
    99+
    2023-06-09
  • css英文如何设置为单词首字母大写
    这篇文章主要介绍“css英文如何设置为单词首字母大写”,在日常操作中,相信很多人在css英文如何设置为单词首字母大写问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”css英文如...
    99+
    2022-10-19
  • 常用MySQL英文单词有哪些
    这篇文章主要介绍常用MySQL英文单词有哪些,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!学PHP涉及的所有MySQL英文单词sql:struct query languagehost:主机user:用户passwo...
    99+
    2023-06-29
  • 常用PHP英文单词有哪些
    这篇文章主要为大家展示了“常用PHP英文单词有哪些”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“常用PHP英文单词有哪些”这篇文章吧。学PHP涉及的常用PHP英文单词PHP: HyperText...
    99+
    2023-06-29
  • CSS怎么设置英文单词与单词的间距宽度
    这篇文章主要介绍“CSS怎么设置英文单词与单词的间距宽度”,在日常操作中,相信很多人在CSS怎么设置英文单词与单词的间距宽度问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”CS...
    99+
    2022-10-19
  • Python中文纠错的简单实现
    介绍 这篇文章主要是用 Python 实现了简单的中文分词的同音字纠错,目前的案例中只允许错一个字,自己如果有兴趣可以继续优化下去。具体步骤如下所示: 先准备一个文件,里...
    99+
    2022-11-12
  • C++如何从文件中提取英文单词
    本篇内容主要讲解“C++如何从文件中提取英文单词”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C++如何从文件中提取英文单词”吧!思路:打开文件读取每一行找到特殊的标点符号的位置,进行删除。根据...
    99+
    2023-07-02
  • html英文单词如何不换行显示
    本文小编为大家详细介绍“html英文单词如何不换行显示”,内容详细,步骤清晰,细节处理妥当,希望这篇“html英文单词如何不换行显示”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。...
    99+
    2022-10-19
  • PHP涉及的JS英文单词有哪些
    这篇文章主要介绍“PHP涉及的JS英文单词有哪些”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“PHP涉及的JS英文单词有哪些”文章能帮助大家解决问题。var:定义变量if:如果else:否则swit...
    99+
    2023-06-29
  • php涉及的CSS英文单词有哪些
    这篇文章主要讲解了“php涉及的CSS英文单词有哪些”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“php涉及的CSS英文单词有哪些”吧!学PHP涉及的所有CSS英文单词CSS(cascadi...
    99+
    2023-06-29
  • php涉及的HTML英文单词有哪些
    本篇内容主要讲解“php涉及的HTML英文单词有哪些”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“php涉及的HTML英文单词有哪些”吧!html超文本标记语言head 头部font 字体 字形...
    99+
    2023-06-29
  • 怎么用Python将所有的英文单词首字母变成大写
    本篇内容主要讲解“怎么用Python将所有的英文单词首字母变成大写”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么用Python将所有的英文单词首字母变成大写”吧!将英文单词首字母变成大写是非...
    99+
    2023-06-15
  • go语言题解LeetCode1160拼写单词示例详解
    目录题目描述思路分析AC 代码 别人用int[26] 解题思路代码c++几乎双百的哈希解法代码题目描述 1160. 拼写单词 - 力扣(LeetCode) 给...
    99+
    2022-12-30
    go题解拼写单词 go LeetCode1160
  • css 整个英文单词不换行怎么实现
    本教程操作环境:Windows10系统、CSS3版、DELL G3电脑css 整个英文单词不换行怎么实现?css中英文单词换行的问题单词换行的问题在项目中有时候会遇到英文很长的句子,然后当div剩下的部分不足以放下一个单词的时候,单词就会换...
    99+
    2023-05-14
    css
  • css整个英文单词不换行如何实现
    本篇内容介绍了“css整个英文单词不换行如何实现”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!css整个英文单词不换行的实现方法:1、通过c...
    99+
    2023-07-05
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作