Python 21行輕鬆搞定拼寫檢查器

2021-09-20 04:31:08 字數 4398 閱讀 8957

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)

代表在輸入單詞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())

是利用python正規表示式模組,提取所有的符合

』[a-z]+』

條件的,也就是由字母組成的單詞。(這裡不詳細介紹正規表示式了,有興趣的同學可以看 正規表示式簡介)。

是將文字轉化為小寫字母,也就是「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

表示式實現。

建立了乙個預設的字典,

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)

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)

我們假設編輯距離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)

原文發布時間為:2018-09-12

python專欄

」,了解相關資訊可以關注「

python專欄」。

Python 21點小遊戲

建立一副撲克牌 建立莊家 計算機 和玩家 我 發牌 莊家1張,玩家2張 玩家根據自己的牌面與莊家的牌面來選擇是否要牌?詢問方式 如果玩家要牌,則繼續發牌,發牌後判斷是否爆牌。如果爆牌,則玩家負 如果玩家停牌,則莊家開始要牌。如果莊家小於17點,無條件要牌 如果牌面 17,21,無條件停牌 如果莊家大...

輕鬆搞定python系列

輕鬆搞定python 變數與數 算 輕輕鬆鬆搞定python 輕鬆搞定python 字串與序列 輕鬆搞定python 字典與集合變數引用 輕鬆搞定python 流程控制與函式 程式或者叫 本質上就是一堆讓計算機幹活的指令,每一條指令就是乙個幹活步驟。指令讓計算機幹什麼就幹什麼,沒有指令,計算機就不知...

重新學習python21

0,將fun a函式轉換為lambda表示式 def fun a x,y 3 return x y a fun a 5,print a b fun a 5,5 print b lambda表示式 lambda x,y 3 x y 1,lambda表示式 轉化為 一般函式 3 利用lambda表示式 ...