1、举例:一个学校有N名学生,其中男生占60%,女生占40%,男生全部传长裤,女生一半穿长裤,一半穿裙子,现在看见一个学生穿着长裤,看不清是男生还是女生。请问是女生的概率有大?
count(女生穿长裤的人数) = N * P(女生) * P(长裤| 女生)
count (穿长裤的总人数) = N * P(男生) * P(长裤 | 男生) + N * P(女生) * P(长裤 | 女生)
P(女生 | 长裤) = count(女生穿长裤的人数) / count(穿长裤的总人数)
= N * P(女生) * P(长裤| 女生) / ( N * P(男生) * P(长裤 | 男生) + N * P(女生) * P(长裤 | 女生) )
= P(女生) * P(长裤| 女生) / ( P(男生) * P(长裤 | 男生) + P(女生) * P(女生,长裤) )
= P(女生) * P(长裤| 女生) / P(长裤)
上述结果与N无关。
这其实就是贝叶斯公式:P(A | B) = P(A) * P(B | A) / P(B)
2、模型比较理论
最大似然:最符合观测数据( P(D|w) )的最有优势。
抛掷一枚硬币,观察到“正面朝上”,根据最大似然,应该猜测这枚硬币掷出正面朝上的概率为1,这样才能最大化P(D|w)的这个猜测 。
奥卡姆剃刀:P(w) 最大的模型有较大的优势。
如果平面上有N个点,近似构成一条直线,但绝不精确地位于一条直线上,我们可以使用一阶,二阶,甚至N-1阶多项式完美地通过N个数据点,哪个模型最靠谱?根据奥卡姆剃刀原则,越是高阶的多项式越不常见。
3、贝叶斯公式的应用
拼写检查,P(D|w),D是我们的输入单词,w是我们要预测的单词。P(w|D) = P(w) * P(D|w) / P(D),其中P(D)可以忽略。
代码自动补全;
垃圾邮件过滤。一封邮件D有N个单词组成,使用h+表示垃圾邮件,h-表示正常邮件,则
P(h+ | D) = P(h+) * P(D | h+) / P(D)
P(h- | D) = P(h-) * P(D | h-) / P(D)
其中P(D)可以忽略。
4、贝叶斯实现拼写检查
import re,collections
# 求解 argmaxc P(c|w) ->argmaxc P(w|c)*P(c)/P(w)
# 其中,P(c) 是文章中出现一个正确拼写词c的概率,即在英文文章中c出现的概率多大。
# P(w|c),表示用户想输入正确单词c的情况下,敲错成w的概率,因为这个是代表用户会以多大的概率把c敲错成w
# argmaxc,用来枚举所有可能的c并且选取概率最大的那个单词c
# 把语料库中的单词全部抽取出来,转成小写。并去除单词间的特殊符号。
def words(text):
return re.findall('[a-z]+', text.lower())
# 统计每个单词出现的个数
def train(features):
# defaultdict类的初始化函数接受一个类型作为参数,当所访问的键不存在的时候,可以实例化一个值作为默认值。
model = collections.defaultdict(lambda:1)
for f in features:
model[f] += 1
return model
words_num = train(words(open("/content/sample_data/big.txt").read()))
# print(len(words_num))
# 要是遇到从未见过的新词,比如说,一个词拼写完全正确,语料库中这个词,
# 从而这个词也永远不会出现在训练集中,于是返回出现这个单词的概率为0,
# 这样可不行,因为0代表永远不可能发生,我们期望使用一个很小的概率来代表这种情况lambda:1。
# 字母表
alphabet = 'abcdefghijklmnopqrstuvwxyz'
# P(D|w),D是我们的输入单词,w是我们要预测的单词。P(w|D) = P(w) * P(D|w) / P(D),其中P(D)可以忽略。
# P(D|w)使用编辑距离衡量
# 编辑距离:
# 两个单词之间的编辑距离定位为使用了几次插入(在一个词中插入一个单字母),删除(删除一个单字母),
# 交换(交换相邻连个字母),替换(把一个字母换成另一个字母)的操作将一个词变成另一个词。
def edits1(word):
n = len(word)
return set([word[0:i] + word[i+1:] for i in range(n)] + # deletion,删除一个单词
[word[0:i] + word[i+1] + word[i] +word[i+2:] for i in range(n-1)] + # transposition,交换一个单词
[word[0:i] + c + word[i+1:] for i in range(n) for c in alphabet] + # alternation,替换一个单词
[word[0:i] + c + word[i:] for i in range(n+1) for c in alphabet] # insertion,插入一个单词
)
# 与something编辑距离为2的单词有114324个!
# 优化,只返回计算的编辑距离形成的单词在单词表中有的单词
def known_edits2(word):
return set(e2 for e1 in edits1(word) for e2 in edits1(e1) if e2 in words_num)
def known(words):
return set(w for w in words if w in words_num)
def correct(word):
# 找出在词库中与输入单词最相近的单词,得出候选预测词
candidates = known([word]) or known(edits1(word)) or known_edits2(word) or [word]
print(candidates)
# 从候选预测词中选择一个出现罪数最多的作为待预测的词
return max(candidates, key=lambda w: words_num[w])
correct('corrr')
# print(known(['corrr']))
输出:(不同的语料库输出结果可能不一样)
'core'