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 ...
随机推荐
- NHibernate学习笔记(3)-实体反射到数据库
一.开发环境 NHiberate版本:4.0.4 开发工具:VS2013 数据库:SQLServer2012 二.开发流程 1.编写领域类与映射文件 namespace Domain { public ...
- 在中间层 .NET 应用程序中通过授权管理器使用基于角色的安全
基于角色的安全是从 Windows NT 的第一个版本开始在 Windows 平台上发展而来的.使用角色,操作系统可以通过检查称为 BUILTIN\Administrators 的组的安全上下文做出一 ...
- Angular——依赖注入
基本介绍 1.AngularJS采用模块化的方式组织代码,将一些通用逻辑封装成一个对象或函数,实现最大程度的复用,这导致了使用者和被使用者之间存在依赖关系. 2.所谓依赖注入是指在运行时自动查找依赖关 ...
- java设计模式之代理模式模式总结
定义:代理模式这种设计模式是一种使用代理对象来执行目标对象的方法并在代理对象中增强目标对象方法的一种设计模式. 解读定义: 1.代理对象和目标对象有共同的接口: 2.使用代理对象执行目标对象中的方法: ...
- windows服务器监控多个tomcat运行状态
第一步,修改tomcat默认的进程名 因为所有的tomcat项目的进程名默认都叫java.exe,所以需要修改tomcat容器bin目录下的setclasspath.bat.注释掉:(在set前加上 ...
- Expectation-Maximization(EM) 算法
Expectation-Maximization 算法是统计学中用来给带隐含变量的模型做最大似然(和最大后验概率)的一种方法.EM 的应用特别广泛,经典的比如做概率密度估计用的 Gaussian Mi ...
- Tomcat环境的搭建
一.Tomcat的简单介绍 大家应该知道平时所说的C/S和B/S系统架构:C/S架构是基于客户端C和服务端S的,B/S架构是基于浏览器B和S服务端的,B/S架构中的server就是web服务器. To ...
- Spring框架系列(四)--IOC控制反转和DI依赖注入
背景: 如果对象的引用或者依赖关系的管理由具体对象完成,代码的耦合性就会很高,代码测试也变得困难.而IOC可以很好的解决这个问题,把这 些依赖关系交给框架或者IOC容器进行管理,简化了开发. IOC是 ...
- JDBC插入数据时中文变为问号的解决方法
JDBC插入数据时中文变为问号的解决方法 制作人:全心全意 出现中文变问号的代码: String url = "jdbc:mysql://localhost:3306/test"; ...
- python3 的 zip
准备放弃生命中这4个小时,然后翻开了python,人生苦短,音乐和python才味甘 1. zip 可以看到zip两个列表,返回一个元组的列表,但是它是个可迭代的对象,得用list才能调用显示: 2 ...