1. 程式人生 > >小專案--貝葉斯實現拼寫檢查

小專案--貝葉斯實現拼寫檢查

求解:argmaxc P(c|w) -> argmaxc P(w|c)P©/P(w)
P©:文章中出現一個正確拼寫詞c的概率,也就是語料庫中c出現的概率有多大
P(w|c):在使用者想鍵入c的情況下敲成w的概率,也就是使用者會以多大的概率把c敲錯成w
argmaxc:用來列舉所有可能的c並且選取概率最大的

import re #正則表示式
from collections import defaultdict #

#定義一個函式將文字中所有的單詞抽取出來,轉換成小寫並去除特殊字元
def words(text):
    return re.findall("[a-z]+",text.lower())

#定義詞頻函式
def wordsFrequency(word):
    #定義一個字典
    model = defaultdict(lambda:1) #定義一個字典預設值為1,因為當我們遇到沒有見過的新詞,因為語料庫沒有這個詞則返回的概率為0
    #就是表示不能發生事件,而在我們的概率模型中我們期望用一個很小的概率代替這種情況,所以初始的詞頻都為1
    print(type(model)) #<class 'collections.defaultdict'>

    for w in word:
        model[w] += 1 #如果語料庫出現了這個詞則加一
    return model

nwords = wordsFrequency(words(open(r'big.txt').read()))
#print(nwords)

alphabet = "abcdefghijklmnopqrstuvwxyz"
#print(len(alphabet))

#編輯距離
#兩個詞之間的編輯距離定義為使用了幾次插入(插入一個單字母)、刪除、交換、替換的操作從一個詞變到另一個詞
def edits1(word): #返回所有與單詞w編輯距離為1(做一次操作)的集合
    n = len(word)
    #刪除、交換、替換、插入
    return set([word[0:i]+word[i+1:] for i in range(n)] +
               [word[0:i]+word[i+1]+word[i]+word[i+2:] for i in range(n-1)] +
               [word[0:i]+c+word[i+1:] for i in range(n) for c in alphabet] +
               [word[0:i]+c+word[i:] for i in range(n) for c in alphabet])

#與something編輯距離為2(做兩個操作,如替換兩個字母)的單詞居然達到了114324個
def edits2(word): #編輯距離為2的集合
    return set(e2 for e1 in edits1(word) for e2 in edits1(e1))

#按照編輯距離來算資料量太大,我們需要優化,只返回在語料庫中出現的的詞"smoothing","something","soothing"
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=lambda w:nwords[w])

correctword = correct("morw")
print(correctword) #more