21行Python代碼實(shí)現(xiàn)拼寫檢查器
引入
大家在使用谷歌或者百度搜索時(shí),輸入搜索內(nèi)容時(shí),谷歌總是能提供非常好的拼寫檢查,比如你輸入 speling,谷歌會(huì)馬上返回 spelling。
下面是用21行python代碼實(shí)現(xiàn)的一個(gè)簡易但是具備完整功能的拼寫檢查器。
代碼
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函數(shù)是程序的入口,傳進(jìn)去錯(cuò)誤拼寫的單詞會(huì)返回正確。如:
>>> correct("cpoy")
'copy'
>>> correct("engilsh")
'english'
>>> correct("sruprise")
'surprise'
除了這段代碼外,作為機(jī)器學(xué)習(xí)的一部分,肯定還應(yīng)該有大量的樣本數(shù)據(jù),準(zhǔn)備了big.txt作為我們的樣本數(shù)據(jù)。
背后原理
上面的代碼是基于貝葉斯來實(shí)現(xiàn)的,事實(shí)上谷歌百度實(shí)現(xiàn)的拼寫檢查也是通過貝葉斯實(shí)現(xiàn),不過肯定比這個(gè)復(fù)雜多了。
首先簡單介紹一下背后的原理,如果讀者之前了解過了,可以跳過這段。
給一個(gè)詞,我們試圖選取一個(gè)最可能的正確的的拼寫建議(建議也可能就是輸入的單詞)。有時(shí)也不清楚(比如lates應(yīng)該被更正為late或者latest?),我們用概率決定把哪一個(gè)作為建議。我們從跟原始詞w相關(guān)的所有可能的正確拼寫中找到可能性最大的那個(gè)拼寫建議c:
argmaxc P(c|w)
通過貝葉斯定理,上式可以轉(zhuǎn)化為
argmaxc P(w|c) P(c) / P(w)
下面介紹一下上式中的含義:
- P(c|w)代表在輸入單詞w 的情況下,你本來想輸入 單詞c的概率。
- P(w|c)代表用戶想輸入單詞c卻輸入w的概率,這個(gè)可以我們認(rèn)為給定的。
- P(c)代表在樣本數(shù)據(jù)中單詞c出現(xiàn)的概率
- P(w)代表在樣本數(shù)字中單詞w出現(xiàn)的概率
可以確定P(w)對(duì)于所有可能的單詞c概率都是一樣的,所以上式可以轉(zhuǎn)換為
argmaxc P(w|c) P(c)
我們所有的代碼都是基于這個(gè)公式來的,下面分析具體代碼實(shí)現(xiàn)
代碼分析
利用words()函數(shù)提取big.txt中的單詞
def words(text): return re.findall('[a-z]+', text.lower())
re.findall(‘[a-z]+'是利用python正則表達(dá)式模塊,提取所有的符合'[a-z]+'條件的,也就是由字母組成的單詞。(這里不詳細(xì)介紹正則表達(dá)式了,有興趣的同學(xué)可以看 正則表達(dá)式簡介。text.lower()是將文本轉(zhuǎn)化為小寫字母,也就是“the”和“The”一樣定義為同一個(gè)單詞。
利用train()函數(shù)計(jì)算每個(gè)單詞出現(xiàn)的次數(shù)然后訓(xùn)練出一個(gè)合適的模型
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在樣本中出現(xiàn)的次數(shù)。如果有一個(gè)單詞并沒有出現(xiàn)在我們的樣本中該怎么辦?處理方法是將他們的次數(shù)默認(rèn)設(shè)為1,這里通過collections模塊和lambda表達(dá)式實(shí)現(xiàn)。collections.defaultdict()創(chuàng)建了一個(gè)默認(rèn)的字典,lambda:1將這個(gè)字典中的每個(gè)值都默認(rèn)設(shè)為1。
現(xiàn)在我們處理完了公式argmaxc P(w|c) P(c)中的P(c),接下來處理P(w|c)即想輸入單詞c卻錯(cuò)誤地輸入單詞w的概率,通過 “edit distance“--將一個(gè)單詞變?yōu)榱硪粋€(gè)單詞所需要的編輯次數(shù)來衡量,一次edit可能是一次刪除,一個(gè)交換(兩個(gè)相鄰的字母),一次插入,一次修改。下面的函數(shù)返回一個(gè)將c進(jìn)行一次編輯所有可能得到的單詞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)
相關(guān)論文顯示,80-95%的拼寫錯(cuò)誤跟想要拼寫的單詞都只有1個(gè)編輯距離,如果覺得一次編輯不夠,那我們再來一次
def known_edits2(word): return set(e2 for e1 in edits1(word) for e2 in edits1(e1) if e2 in NWORDS)
同時(shí)還可能有編輯距離為0次的即本身就拼寫正確的:
def known(words): return set(w for w in words if w in NWORDS)
我們假設(shè)編輯距離1次的概率遠(yuǎn)大于2次的,0次的遠(yuǎn)大于1次的。下面通過correct函數(shù)先選擇編輯距離最小的單詞,其對(duì)應(yīng)的P(w|c)就會(huì)越大,作為候選單詞,再選擇P(c)最大的那個(gè)單詞作為拼寫建議
def correct(word): candidates = known([word]) or known(edits1(word)) or known_edits2(word) or [word] return max(candidates, key=NWORDS.get)
以上就是本文的全部內(nèi)容,希望對(duì)大家學(xué)習(xí)python程序設(shè)計(jì)有所幫助。
相關(guān)文章
Python自定義聚合函數(shù)merge與transform區(qū)別詳解
這篇文章主要介紹了Python自定義聚合函數(shù)merge與transform區(qū)別詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-05-05
Python使用pathlib進(jìn)行文件系統(tǒng)操作
pathlib?是?Python?的一個(gè)標(biāo)準(zhǔn)庫,它提供了一個(gè)面向?qū)ο蟮奈募到y(tǒng)路徑操作接口,本文主要介紹了Python使用pathlib進(jìn)行文件系統(tǒng)操作的相關(guān)知識(shí),有需要的可以了解下2024-11-11
Python使用Selenium時(shí)遇到網(wǎng)頁<body>劃不動(dòng)的問題解決方法
如果在使用 Selenium 時(shí)遇到網(wǎng)頁的 <body> 劃不動(dòng)的問題,這通常是因?yàn)轫撁娴臐L動(dòng)機(jī)制(例如,可能使用了一個(gè)具有固定高度的容器或自定義的滾動(dòng)條)導(dǎo)致無法通過簡單的 JavaScript 實(shí)現(xiàn)滾動(dòng),可以通過以下方法來解決該問題2024-10-10
Centos7下源碼安裝Python3 及shell 腳本自動(dòng)安裝Python3的教程
這篇文章主要介紹了Centos7下源碼安裝Python3 shell 腳本自動(dòng)安裝Python3的相關(guān)知識(shí),本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-03-03
10招!看骨灰級(jí)Pythoner玩轉(zhuǎn)Python的方法
這篇文章主要介紹了10招!看骨灰級(jí)Pythoner如何玩轉(zhuǎn)Python,需要的朋友可以參考下2019-04-04
Python pywifi ERROR Open handle fai
這篇文章主要介紹了Python pywifi ERROR Open handle failed問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-06-06
python安裝TA-Lib庫報(bào)錯(cuò)問題的解決方法
TaLib是一個(gè)Python金融指數(shù)處理庫,包含了很多技術(shù)分析里的常用參數(shù)指標(biāo),例如MA、SMA、WMA、MACD、ATR等,這篇文章主要給大家介紹了關(guān)于python安裝TA-Lib庫報(bào)錯(cuò)問題的解決方法,需要的朋友可以參考下2024-01-01
健身房被搭訕?用python寫了個(gè)小米計(jì)時(shí)器助人為樂
今天教大家Python圖形界面開發(fā)的相關(guān)知識(shí),文章圍繞著如何實(shí)現(xiàn)一個(gè)小米手機(jī)上的秒表計(jì)時(shí)器功能展開,文中有非常詳細(xì)的代碼示例,需要的朋友可以參考下2021-06-06

