21行python代码实现拼写检查器
引入
大家在使用谷歌或者百度搜索时,输入搜索内容时,谷歌总是能提供很好的拼写检查,比方你输入 speling,谷歌会立即返回 spelling。
前几天,看到http://norvig.com/spell-correct.html这篇文章,于是翻译过来。再加上自己的理解,有了以下的博文。
以下是用21行python代码实现的一个简易可是具备完整功能的拼写检查器。
代码
import re, collections
def words(text): return re.findall('[a-z]+', text.lower())
def train(features):
model = collections.defaultdict(lambda: 1)
for f in features:
model[f] += 1
return model
NWORDS = train(words(file('big.txt').read()))
alphabet = 'abcdefghijklmnopqrstuvwxyz'
def edits1(word):
splits = [(word[:i], word[i:]) for i in range(len(word) + 1)]
deletes = [a + b[1:] for a, b in splits if b]
transposes = [a + b[1] + b[0] + b[2:] for a, b in splits if len(b)>1]
replaces = [a + c + b[1:] for a, b in splits for c in alphabet if b]
inserts = [a + c + b for a, b in splits for c in alphabet]
return set(deletes + transposes + replaces + inserts)
def known_edits2(word):
return set(e2 for e1 in edits1(word) for e2 in edits1(e1) if e2 in NWORDS)
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=NWORDS.get)
correct函数是程序的入口,传进去错误拼写的单词会返回正确。如:
>>> correct("cpoy")
'copy'
>>> correct("engilsh")
'english'
>>> correct("sruprise")
'surprise'
除了这段代码外,作为机器学习的一部分,肯定还应该有大量的样本数据。准备了big.txt作为我们的样本数据。
背后原理
上面的代码是基于贝叶斯来实现的,其实谷歌百度实现的拼写检查也是通过贝叶斯实现。只是肯定比这个复杂多了。
首先简单介绍一下背后的原理,假设读者之前了解过了。能够跳过这段。
给一个词,我们试图选取一个最可能的正确的的拼写建议(建议也可能就是输入的单词)。有时也不清楚(比方lates应该被更正为late或者latest?),我们用概率决定把哪一个作为建议。我们从跟原始词w相关的全部可能的正确拼写中找到可能性最大的那个拼写建议c:
argmaxc P(c|w)
通过贝叶斯定理。上式能够转化为
argmaxc P(w|c) P(c) / P(w)
以下介绍一下上式中的含义:
- P(c|w)代表在输入单词w 的情况下,你本来想输入 单词c的概率。
- P(w|c)代表用户想输入单词c却输入w的概率,这个能够我们觉得给定的。
- P(c)代表在样本数据中单词c出现的概率
- P(w)代表在样本数字中单词w出现的概率
能够确定P(w)对于全部可能的单词c概率都是一样的。所以上式能够转换为
argmaxc P(w|c) P(c)
我们全部的代码都是基于这个公式来的,以下分析具体代码实现:
代码分析
利用words()函数提取big.txt中的单词
def words(text): return re.findall('[a-z]+', text.lower())
re.findall(‘[a-z]+’是利用python正則表達式模块,提取全部的符合’[a-z]+’条件的。也就是由字母组成的单词。(这里不具体介绍正則表達式了。有兴趣的同学能够看 正則表達式简单介绍。text.lower()是将文本转化为小写字母。也就是“the”和“The”一样定义为同一个单词。
利用train()函数计算每一个单词出现的次数然后训练出一个合适的模型
def train(features):
model = collections.defaultdict(lambda: 1)
for f in features:
model[f] += 1
return model
NWORDS = train(words(file('big.txt').read()))
这样NWORDS[w]代表了单词w在样本中出现的次数。假设有一个单词并没有出如今我们的样本中该怎么办?处理方法是将他们的次数默认设为1。这里通过collections模块和lambda表达式实现。collections.defaultdict()创建了一个默认的字典,lambda:1将这个字典中的每一个值都默认设为1。
(lambda表达式能够看lambda简单介绍
如今我们处理完了公式argmaxc P(w|c) P(c)中的P(c),接下来处理P(w|c)即想输入单词c却错误地输入单词w的概率,通过 “edit distance“--将一个单词变为还有一个单词所须要的编辑次数来衡量,一次edit可能是一次删除,一个交换(两个相邻的字母)。一次插入。一次改动。以下的函数返回一个将c进行一次编辑全部可能得到的单词w的集合:
def edits1(word):
splits = [(word[:i], word[i:]) for i in range(len(word) + 1)]
deletes = [a + b[1:] for a, b in splits if b]
transposes = [a + b[1] + b[0] + b[2:] for a, b in splits if len(b)>1]
replaces = [a + c + b[1:] for a, b in splits for c in alphabet if b]
inserts = [a + c + b for a, b in splits for c in alphabet]
return set(deletes + transposes + replaces + inserts)
相关论文显示。80-95%的拼写错误跟想要拼写的单词都仅仅有1个编辑距离,假设觉得一次编辑不够,那我们再来一次
def known_edits2(word):
return set(e2 for e1 in edits1(word) for e2 in edits1(e1) if e2 in NWORDS)
同一时候还可能有编辑距离为0次的即本身就拼写正确的:
def known(words):
return set(w for w in words if w in NWORDS)
我们假设编辑距离1次的概率远大于2次的,0次的远大于1次的。以下通过correct函数先选择编辑距离最小的单词。其相应的P(w|c)就会越大。作为候选单词。再选择P(c)最大的那个单词作为拼写建议。
def correct(word):
candidates = known([word]) or known(edits1(word)) or known_edits2(word) or [word]
return max(candidates, key=NWORDS.get)
21行python代码实现拼写检查器的更多相关文章
- python 拼写检查代码(怎样写一个拼写检查器)
原文:http://norvig.com/spell-correct.html 翻译:http://blog.youxu.info/spell-correct.html 怎样写一个拼写检查器 Pete ...
- 如何写一个拼写检查器-by Peter Norvig
本文原著:Peter Norvig 中文翻译:徐宥 上个星期, 我的两个朋友 Dean 和 Bill 分别告诉我说他们对 Google 的快速高质量的拼写检查工具感到惊奇. 比如说在搜索的时候键入 ...
- 200行PYTHON代码实现贪吃蛇
200行Python代码实现贪吃蛇 话不多说,最后会给出全部的代码,也可以从这里Fork,正文开始: 目前实现的功能列表: 贪吃蛇的控制,通过上下左右方向键: 触碰到边缘.墙壁.自身则游戏结束: 接触 ...
- 15行python代码,帮你理解令牌桶算法
本文转载自: http://www.tuicool.com/articles/aEBNRnU 在网络中传输数据时,为了防止网络拥塞,需限制流出网络的流量,使流量以比较均匀的速度向外发送,令牌桶算法 ...
- 一个 11 行 Python 代码实现的神经网络
一个 11 行 Python 代码实现的神经网络 2015/12/02 · 实践项目 · 15 评论· 神经网络 分享到:18 本文由 伯乐在线 - 耶鲁怕冷 翻译,Namco 校稿.未经许可,禁止转 ...
- 200行Python代码实现2048
200行Python代码实现2048 一.实验说明 1. 环境登录 无需密码自动登录,系统用户名shiyanlou 2. 环境介绍 本实验环境采用带桌面的Ubuntu Linux环境,实验中会用到桌面 ...
- 40多行python代码开发一个区块链。
40多行python代码开发一个区块链?可信吗?我们将通过Python 2动手开发实现一个迷你区块链来帮你真正理解区块链技术的核心原理.python开发区块链的源代码保存在Github. 尽管有人认为 ...
- [Swift]LeetCode966.元音拼写检查器 | Vowel Spellchecker
Given a wordlist, we want to implement a spellchecker that converts a query word into a correct word ...
- 30行Python代码实现人脸检测
参考OpenCV自带的例子,30行Python代码实现人脸检测,不得不说,Python这个语言的优势太明显了,几乎把所有复杂的细节都屏蔽了,虽然效率较差,不过在调用OpenCV的模块时,因为模块都是C ...
随机推荐
- PS技巧汇总
一.gif图流程 1:素材图片a 图片b 2:窗口--->时间轴/动画 3:复制所选帧--->设置帧延迟 4:文件--->存储为WEB格式--->gif格式 二.批处理--- ...
- CF811C Vladik and Memorable Trip
思路: 令dp[i]表示前i个的最大舒适度.则如果区间[j, i](1 < j <= i)满足条件,有如下转移:dp[i] = max(dp[i], dp[j - 1] + cur).其中 ...
- 93. [NOIP2001] 数的划分
问题描述 将整数n分成k份,且每份不能为空,任意两种方案不能相同(不考虑顺序). 例如:n=7,k=3,下面三种分法被认为是相同的. 1,1,5; 1,5,1; 5,1,1; 问有多少种不同的分法. ...
- 全面介绍Android Studio中Git 的使用(一)
来源 :http://blog.csdn.net/gao_chun/article/details/49817229/
- 微信关于网页授权access_token和普通access_token的区别
微信官网网址:https://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html#.E9.99.84.EF.BC.9A.E6. ...
- 腾讯云 LNMP+wordpress 搭建个人网站
折腾了好几个小时才弄好(php nginx略知一二),其实一点都不难! 以此记录一下,献给首次搭建的朋友们!! 1)准备工作:(因为个人用的ubuntu16.04 LTS系统 所以这是debian版 ...
- java多线程(线程通信-等待换新机制-代码优化)
等待唤醒机制涉及方法: wait():让线程处于冻结状态,被wait的线程会被存储到线程池中. noticfy():唤醒同一个线程池中一个线程(任意也可能是当前wait的线程) notifyAll() ...
- 【sqli-labs】 less64 GET -Challenge -Blind -130 queries allowed -Variation3 (GET型 挑战 盲注 只允许130次查询 变化3)
双括号整型 http://192.168.136.128/sqli-labs-master/Less-64/?id=1)) or ((1
- (转)版本管理工具介绍——SVN篇(二)
http://blog.csdn.net/yerenyuan_pku/article/details/72620498 上一篇文章我介绍了一下SVN,以及SVN服务器的安装,相信大家都安装了,接下来我 ...
- RabbitMQ系列(六)--面试官问为什么要使用MQ,应该怎么回答
如果简历中有写到使用过RabbitMQ或者其他的消息中间件,可能在MQ方面的第一个问题就是问:为什么要使用MQ 面试官期望的回答 1.项目中有什么业务场景需要用到MQ 2.但是用了MQ,会带来很多问题 ...