zoukankan      html  css  js  c++  java
  • (含部分转载)贝叶斯推断应用之英文单词纠错

    本文参考资料来自:

    程序源码作者及来源:http://norvig.com/spell-correct.html

    中文翻译版:http://www.ruanyifeng.com/blog/2012/10/spelling_corrector.html

    这段程序比较有意思,可以实现英文单词的纠错,实现的思想也非常简单,但效果却比较不错

    举例,譬如用户想输入单词somebody,但却误输入成somebady,程序就可以帮你就纠正出来

    使用方法为 correction('你所输入的单词')

    就个人看来,程序有些可以改进的地方,比如提供单词库更大的文件(作者所提供的big.txt含有32198个单词),

    或者直接使用纯词典式的单词库;提供给用户更多的选项,而不仅仅是一个;算法的部分还可以进一步改进。

    程序主要思路:

    第一步,建立一个足够大的文本库。

    网上有一些免费来源,比如古登堡计划Wiktionary英国国家语料库等等。

    第二步,取出文本库的每一个单词,统计它们的出现频率。

    第三步,根据用户输入的单词,得到其所有可能的拼写相近的形式。

    所谓"拼写相近",指的是两个单词之间的"编辑距离"(edit distance)不超过2。也就是说,两个词只相差1到2个字母,只通过----删除、交换、更改和插入----这四种操作中的一种,就可以让一个词变成另一个词。

    第四步,比较所有拼写相近的词在文本库的出现频率。频率最高的那个词,就是正确的拼法。

    根据Peter Norvig(原作者)的验证,这种算法的精确度大约为60%-70%(10个拼写错误能够检查出6个。)虽然不令人满意,但是能够接受。毕竟它足够简单,计算速度极快。(本文的最后部分,将详细讨论这种算法的缺陷在哪里。)

    当然程序也不是万能的:

    (1)文本库必须有很高的精确性,不能包含拼写错误的词。

    如果用户输入一个错误的拼法,文本库恰好包含了这种拼法,它就会被当成正确的拼法。

    (2)对于不包含在文本库中的新词,没有提出解决办法。

    如果用户输入一个新词,这个词不在文本库之中,就会被当作错误的拼写进行纠正。

    (3)程序返回的是"编辑距离"为1的词,但某些情况下,正确的词的"编辑距离"为2。

    比如,用户输入reciet,会被纠正为recite(编辑距离为1),但用户真正想要输入的词是receipt(编辑距离为2)。也就是说,"编辑距离"越短越正确的规则,并非所有情况下都成立。

    (4)有些常见拼写错误的"编辑距离"大于2。

    这样的错误,程序无法发现。下面就是一些例子,每一行前面那个词是正确的拼法,后面那个则是常见的错误拼法。

    purple perpul
    curtains courtens
    minutes muinets
    successful sucssuful
    inefficient ineffiect
    availability avaiblity
    dissension desention
    unnecessarily unessasarily
    necessary nessasary
    unnecessary unessessay
    night nite
    assessing accesing
    necessitates nessisitates

    (5)用户输入的词的拼写正确,但是其实想输入的是另一个词。

    比如,用户输入是where,这个词拼写正确,程序不会纠正。但是,用户真正想输入的其实是were,不小心多打了一个h。

    (6)程序返回的是出现频率最高的词,但用户真正想输入的是另一个词。

    比如,用户输入ther,程序会返回the,因为它的出现频率最高。但是,用户真正想输入的其实是their,少打了一个i。也就是说,出现频率最高的词,不一定就是用户想输入的词。

    (7)某些词有不同的拼法,程序无法辨别。

    比如,英国英语和美国英语的拼法不一致。英国用户输入'humur',应该被纠正为'humour';美国用户输入'humur',应该被纠正为'humor'。但是,我们的程序会统一纠正为'humor'。

    关于算法思想的介绍可以参见以上的中文翻译版以及原版

    附上原作者提供的big.txt(为福尔摩斯探案集)地址:http://norvig.com/big.txt

    以下为源码:

    import re
    from collections import Counter
    
    def words(text):
        return re.findall(r'w+', text.lower())
    
    WORDS = Counter(words(open('big.txt').read()))
    
    def P(word, N=sum(WORDS.values())):
        "Probability of `word`."
        return WORDS[word] / N
    
    def correction(word):
        "Most probable spelling correction for word."
        return max(candidates(word), key=P)
    
    def candidates(word):
        "Generate possible spelling corrections for word."
        return (known([word]) or known(edits1(word)) or known(edits2(word)) or [word])
    
    def known(words):
        "The subset of `words` that appear in the dictionary of WORDS."
        return set(w for w in words if w in WORDS)
    
    def edits1(word):
        "All edits that are one edit away from `word`."
        letters    = 'abcdefghijklmnopqrstuvwxyz'
        splits     = [(word[:i], word[i:])    for i in range(len(word) + 1)]
        deletes    = [L + R[1:]               for L, R in splits if R]
        transposes = [L + R[1] + R[0] + R[2:] for L, R in splits if len(R)>1]
        replaces   = [L + c + R[1:]           for L, R in splits if R for c in letters]
        inserts    = [L + c + R               for L, R in splits for c in letters]
        return set(deletes + transposes + replaces + inserts)
    
    def edits2(word):
        "All edits that are two edits away from `word`."
        return (e2 for e1 in edits1(word) for e2 in edits1(e1))
    
  • 相关阅读:
    将Nginx添加到windows服务中
    springboot使用redis管理session
    GIT常用命令
    阻止360、谷歌浏览器表单自动填充
    谈谈对Spring IOC的理解
    同一个Nginx服务器同一端口配置多个代理服务
    LeetCode 653. Two Sum IV
    109. Convert Sorted List to Binary Search Tree(根据有序链表构造平衡的二叉查找树)
    108. Convert Sorted Array to Binary Search Tree(从有序数组中构造平衡的BST)
    LeetCode 236. Lowest Common Ancestor of a Binary Tree(二叉树求两点LCA)
  • 原文地址:https://www.cnblogs.com/lomooo/p/6358279.html
Copyright © 2011-2022 走看看