阅读更多

0顶
0踩

编程语言

原创新闻 21行Python代码实现拼写检查器

2016-01-25 16:40 by 副主编 mengyidan1988 评论(0) 有3984人浏览
引入

大家在使用谷歌或者百度搜索时,输入搜索内容时,谷歌总是能提供非常好的拼写检查,比如你输入 speling,谷歌会马上返回 spelling。
下面是用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)


本文转自:CSDN博客
来自: CSDN
0
0
评论 共 0 条 请登录后发表评论

发表评论

您还没有登录,请您登录后再发表评论

相关推荐

  • ValidationSummary 控件

    ValidationSummary控件是用于显示验证所有验证错误摘要的控件,当我们将验证控件的 Display属性设置 None 的时候,验证错误信息就在这里显示。ValidationSummary控件有三个常见属性:属性名 说明 DisplayMode 指定显示模式,有 BulletList、 List、 SingleParagraph 三种模式 ShowMessageBox ...

  • [asp.net] 验证控件

    .aspx ,aspx.cs public void ValidateName(Object sender, ServerValidateEventArgs args) { SqlConnection myConn = new SqlConnection("Data Source=(local);Initial Catalog=Csharp;Integrated Security

  • 在表单提交前进行数据验证

    点击表单中的提交按钮,默认就会提交表单,如果要在表单提交之前做一些校验,那么就可以用jQuery的submit方法。也就是jQuery的submit的方法执行顺序,在表单的提交之前。:return false不往下执行请求form的action,return true继续往下执行请求form的action。

  • 密码框点击眼睛显示隐藏

    密码框点击眼睛显示隐藏

  • form表单提交,jQuery对输入内容进行验证

    企业名称

  • 表单js验证实例

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <...

  • 验证身份证号是否正确的代码

    我们要验证身份证号是否正确,就得先了解身份证号的含意。身份证号都代表什么意思?1、号码的结构公民身份号码是特征组合码,由十七位数字本体码和一位校验码组成。排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。2、地址码(前六位数)表示编码对象常住户口所在县(市、旗、区)的行政区划代码,按GB/T2260的规定执行。3、出生日期码(第七位至十四位)表示编码对象出

  • ASP.NET验证控件验证文本框输内容不符后如何自动清空文本框

    <br />我一个菜鸟 在用asp.net CompareValidator 验证控件验证文本框输入的不是日期格式后,验证控件给出提示“日期格式不对”没有问题。<br />但我想实现验证控件给出提示后,文本框原来输入的不正确的日期格式变为空,就是验证控件给出提示后,文本框自动清空,这样客户就可以根据提示重新填写了。<br />请各位高手指点如何实现。<br /> 

  • 【ASP.NET】RSA加密,前端加密,后端解密,有效哦!

    一、相关JS包和引用BIN文件,下载链接: https://download.csdn.net/download/u012949335/20389382 二、前端如下: &lt;div class="from"&gt; &lt;div class="from-group"&gt; &lt;input type="text" class="inputtext width280" id="UserId" name="

  • 了解form表单提交前验证,看这就够了

    可以使用form表单的onsubmit方法,在提交表单之前,对表单或者网页中的数据进行检验。 onsubmit指定的方法返回true,则提交数据;返回false不提交数据。 第一种写法: &lt;!DOCTYPE html&gt; &lt;html&gt; &lt;head&gt; &lt;meta http-equiv="Content-Type" content="te...

  • 判断form表单里面的元素属性是否有数据_Flask表单验证

    wtf WTForms 1.什么是WTFormsWeb 网页一个重要的功能就是和客户端用户进行交互.在前端HTML 提供了一个form 标签,它是用于提供数据交互的接口.form 可以采用GET和POST 方式以Http请求消息的形式提交给后端服务器脚本(一般都是POST).在后端服务器基本必须捕捉用于提交的form 并做出验证判断.所以后端也相当于从新创建了表单.WTForms 提供了...

  • 如何给input type="password"的输入框赋默认值?

    google_ad_client = "pub-2048279401139630";google_ad_slot = "8856771542";google_ad_width = 728;google_ad_height = 90;document.write("");        最近做一个项目的时候,遇到这样的需求,就是用户登录之后要能在密码输入框里面显示密码,大家都知道,直接给 inp

Global site tag (gtag.js) - Google Analytics