机器学习:基于朴素贝叶斯实现单词拼写修正器(附Python代码)
Posted Mr.Winter`
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了机器学习:基于朴素贝叶斯实现单词拼写修正器(附Python代码)相关的知识,希望对你有一定的参考价值。
目录
0 写在前面
机器学习强基计划聚焦深度和广度,加深对机器学习模型的理解与应用。“深”在详细推导算法模型背后的数学原理;“广”在分析多个机器学习模型:决策树、支持向量机、贝叶斯与马尔科夫决策、强化学习等。
在机器学习强基计划4-3:详解朴素贝叶斯分类原理(附例题+Python实现)中我们学习了朴素贝叶斯的概念:采用属性独立性假设对类后验概率建模,本节再次使用这个理论实现一个有趣的应用——单词拼写修正器,并梳理一些朴素贝叶斯原理中的细节,以期固本强基。
1 语言中的贝叶斯公式
我们的目标是找到原拼写错误单词 w w w的修正单词 c c c,一个事实是,我们没有办法给出确定性的答案,例如
例1:错误单词
lates
应该被修正为late
、latest
还是lattes
…?
因此,我们要找的是一个 w w w所有潜在修正单词中可能性最大的那一个,用概率表示为
c ∗ = a r g m a x c ∈ c a n d i d a t e P ( c ∣ w ) c^*= argmax_c\\in candidate P(c|w) c∗=argmaxc∈candidateP(c∣w)
其中candidate
就是所有候选单词的集合。根据贝叶斯公式,有
c ∗ = a r g m a x c ∈ c a n d i d a t e P ( w ∣ c ) P ( c ) P ( w ) c^*= argmax_c\\in candidate \\fracP(w|c)P(c)P(w) c∗=argmaxc∈candidateP(w)P(w∣c)P(c)
因为 P ( w ) P(w) P(w)对每个候选单词 c c c都相同,因此可以忽略,所以重点关注
c ∗ = a r g m a x c ∈ c a n d i d a t e P ( w ∣ c ) P ( c ) c^*= argmax_c\\in candidate P(w|c)P(c) c∗=argmaxc∈candidateP(w∣c)P(c)
其中
-
P
(
w
∣
c
)
P(w|c)
P(w∣c):称为误差模型,表示的是作者想打出单词
c
c
c却误写成单词
w
w
w的概率,例如
P
(
t
e
h
∣
t
h
e
)
P(teh|the)
P(teh∣the)把
the
打成teh
的概率相对而言远大于 P ( t h e e e x y z ∣ t h e ) P(theeexyz|the) P(theeexyz∣the) -
P
(
c
)
P(c)
P(c):称为语言模型,表示的是单词
c
c
c出现的概率,例如搜索引擎提供用户输入的所有文本中,单词
the
的占了7%,那么 P ( t h e ) = 0.07 P(the) = 0.07 P(the)=0.07
一个很自然的问题是:为什么要把简单的表达式 P ( c ∣ w ) P(c|w) P(c∣w)用一个更复杂的 P ( w ∣ c ) P ( c ) P(w|c)P(c) P(w∣c)P(c)来代替?我相信这也是很多同学初学贝叶斯公式时的困惑,这里用实例说明。
答案很简单:后验概率 P ( c ∣ w ) P(c|w) P(c∣w)无法直接计算,但是将其拆成两个因子后计算相对简便,而且可以透过现象看到其中的本质。
例2:考虑一个错误拼写的单词
w="thew"
,以及两个候选修正c="the"
和c="thaw"
,哪个有更高的 P ( c ∣ w ) P(c|w) P(c∣w)?
c="thaw"
似乎更可能,因为从a
到e
只是一个很小的变化,但另一方面,c="the"
似乎可能性也很大,因为the
是一个非常常用的单词(生僻字出现概率低,自然不容易误写)。从我们正常的分析思路就可以看出,这个后验概率其实包含两个部分,一个是从单词
c
c
c误写成
w
w
w的可能性,一个是单词
c
c
c是否常见。所以贝叶斯公式抽丝剥茧地告诉了我们后验概率的内在逻辑。
2 朴素贝叶斯建模
2.1 单词异化
包含四个异化操作产生候选单词集合candidate
- 删除word中的某个字母
deletes
- word中相邻字母交换顺序
transposes
- word中字母突变(用新字母代替)
replaces
- word中在某位置插入新字母
inserts
'''
* @breif: 对单词进行异化操作,产生与原词有微小差异的新词
* @param[in]: word -> (str)原词汇
* @retval: 与原词有微小差异的新词
'''
def editsOnce(self, word):
# 字母表
letters = 'abcdefghijklmnopqrstuvwxyz'
# 将词汇分解为左右组合,例如tree分解为[(t,ree),(tr,ee),(tre,e),(tree, )]
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)
2.2 语言模型建模
搜集一大段文本作为数据集
接着直接计算词频作为语言模型
P
(
c
)
P(c)
P(c)
'''
* @breif: 查询词汇word的频率
* @param[in]: word -> (str)待查词文本
* @retval: 词汇word的频率p(word)
'''
def p(self, word):
self.wordsCnt = Counter(re.findall(r'\\w+', text.lower()))
self.wordsNum = sum(self.wordsCnt.values())
return self.wordsCnt[word] / self.wordsNum
2.3 误差模型建模
采用短路表达式划分优先级,即优先级为该词汇(在词典中)
>经过一次编辑
>经过二次编辑
>该词汇(不在词典中)
,若高优先级词汇存在会直接返回,相当于argmaxP(w|c)
的操作。
def candidates(self, word):
return (self.known([word]) or self.known(self.editsOnce(word))
or self.known(self.editsTwice(word)) or [word])
3 单词修正测试
首先做一个简单的测试:
def correction(self, word):
return max(self.candidates(word), key=self.p)
随便挑几个单词
print(c.correction('worl'))
>>> work
print(c.correction('traon'))
>>> train
print(c.correction('inteligent'))
>>> intelligent
效果还不错,接着拿个大的测试集来测试一下
trainPath = os.path.abspath(os.path.join(__file__, "../../data/big.txt"))
testPath = os.path.abspath(os.path.join(__file__, "../../data/spell_test.txt"))
c = WordsCorrector(trainPath)
c.predict(testPath)
>>> 75% of 270 correct (6% unknown) at 56 words per second
完整代码与数据集联系下方博主名片获取
🔥 更多精彩专栏:
以上是关于机器学习:基于朴素贝叶斯实现单词拼写修正器(附Python代码)的主要内容,如果未能解决你的问题,请参考以下文章
机器学习强基计划4-3:详解朴素贝叶斯分类原理(附例题+Python实现)
机器学习贝叶斯算法详解 + 公式推导 + 垃圾邮件过滤实战 + Python代码实现
机器学习:详解半朴素贝叶斯分类AODE原理(附Python实现)