赞
踩
使用每个词作为特征并观察它们是否出现,这样得到的特征数目会有多少呢?针对的是哪一种人类语言呢?当然不止一种语言。据估计,仅在英语中,单词的总数就有500 000①之多。为了能进行英文阅读,估计需要掌握数千单词。
朴素贝叶斯的一般过程
(1) 收集数据:可以使用任何方法。本章使用RSS源。
(2) 准备数据:需要数值型或者布尔型数据。
(3) 分析数据:有大量特征时,绘制特征作用不大,此时使用直方图效果更好。
(4) 训练算法:计算不同的独立特征的条件概率。
(5) 测试算法:计算错误率。
(6) 使用算法:一个常见的朴素贝叶斯应用是文档分类。可以在任意的分类场景中使用朴
素贝叶斯分类器,不一定非要是文本。
假设词汇表中有1000个单词。要得到好的概率分布,就需要足够的数据样本,假定样本数为
N。前面讲到的约会网站示例中有1000个实例,手写识别示例中每个数字有200个样本,而决策树
示例中有24个样本。其中,24个样本有点少,200个样本好一些,而1000个样本就非常好了。约
会网站例子中有三个特征。由统计学知,如果每个特征需要N个样本,那么对于10个特征将需要
N10个样本,对于包含1000个特征的词汇表将需要N1000个样本。可以看到,所需要的样本数会随
着特征数目增大而迅速增长。
如果特征之间相互独立,那么样本数就可以从N1000减少到1000×N。所谓独立(independence)
指的是统计意义上的独立,即一个特征或者单词出现的可能性与它和其他单词相邻没有关系。举
个例子讲,假设单词bacon出现在unhealthy后面与出现在delicious后面的概率相同。当然,我们知
道这种假设并不正确,bacon常常出现在delicious附近,而很少出现在unhealthy附近,这个假设正
是朴素贝叶斯分类器中朴素(naive)一词的含义。朴素贝叶斯分类器中的另一个假设是,每个特征同等重要①。其实这个假设也有问题。 如果要判断留言板的留言是否得当,那么可能不需要看
完所有的1000个单词,而只需要看10~20个特征就足以做出判断了。尽管上述假设存在一些小的
瑕疵,但朴素贝叶斯的实际效果却很好。
到目前为止,你已经了解了足够的知识,可以开始编写代码了。如果还不清楚,那么了解代
码的实际效果会有助于理解。下一节将使用Python来实现朴素贝叶斯分类器,实现中会涉及利用
Python进行文本分类的所有相关内容。
#P(know|knon) = P(knon|know) * P(know)
#P(knob|knon) = P(knon|knob) * P(knob)
#P(?|床前明月光) = P(床前明月光|?)P(?)
#简化,一次编辑距离
#1.统计词频
#2.计算编辑距离
import re from collections import Counter import collections alphabet = 'abcdefghijklmnopqrstuvwxyz' all_alpha = open("big.txt").read() #英语分词 words = re.findall('[A-Za-z]+', all_alpha) #print(words) #print(Counter(words)){} #统计词频 count_dict = collections.defaultdict(lambda :1) for w in words: count_dict[w.lower()] += 1 #knon ---> non kon knn kno #knon ---->nkon konn knno #交换距离 #knon ----> kaon kbon kcon............ #knon ---->aknon bknon......kanon kbnon kcnon........ def edit1(word): n = len(word) delete_distance = [(word[0:i] + word[i+1:]) for i in range(n)] switch_distance = [word[0:i] + word[i + 1] + word[i] + word[i + 2:] for i in range(n - 1)] alert_distance = [word[0:i] + c + word[i + 1:] for i in range(4) for c in alphabet] insert_distance = [word[0:i]+c+word[i:] for i in range(4) for c in alphabet] return set(delete_distance + switch_distance + alert_distance + insert_distance) candiates = edit1("knon") correcr_words = [w for w in candiates if w in count_dict] print("knon的矫正结果是:",max(candiates,key=lambda x:count_dict[x]))
class SpellCheck(object): """ 使用贝叶斯进行错词矫正,假定P(knon|know)是一次编辑距离错误的概率,所有一次编辑距离错误的概率是等价的 P(know) 该单词在语料库中的词频,由于是同一个语料库,直接比较分子,分子是该单词出现的次数 #P(know|knon) = P(knon|know) * P(know) #P(knob|knon) = P(knob|know) * P(knob) """ def __init__(self, file_name): """ 初始还参数 :param file_name: 语料库文件的名字 """ content = open(file_name).read() self.words = re.findall('[A-Za-z]+',content) self.alphabet = 'abcdefghijklmnopqrstuvwxyz' self.count_dict = collections.defaultdict(lambda: 1) def fit(self): """ 训练过程就是统计语料库中各个词的词频 :return: """ for w in self.words: self.count_dict[w.lower()] += 1 # def edit2(self, words): # return [edit1(w) for w in words] def edit1(self,word): """ 生成一次编辑距离 :param word: :return: """ n = len(word) #一次删除距离 delete_distance = [(word[0:i] + word[i + 1:]) for i in range(n)] #一次交换距离 switch_distance = [word[0:i] + word[i + 1] + word[i] + word[i + 2:] for i in range(n - 1)] #一次修改距离 alert_distance = [word[0:i] + c + word[i + 1:] for i in range(4) for c in alphabet] #一次添加距离 insert_distance = [word[0:i] + c + word[i:] for i in range(4) for c in alphabet] #set去重,返回结果 return set(delete_distance + switch_distance + alert_distance + insert_distance) def known(self,words): """ 判断单词是否拼写正确,所谓的正确,及在语料库中存在该单词 :param words: :return: """ return set([w for w in words if w in self.count_dict]) def predict(self, word): """ 对每一个单词进行拼写检查 :param word: 需要检查的单词 :return: """ #先检测单词是否拼写正确,如果拼错,检测一次编辑距离,否则返回单词本身 canditates_spell = self.known([word]) or self.known(self.edit1(word)) or [word] print(canditates_spell) print(self.count_dict['abc']) return max(canditates_spell,key=lambda x:self.count_dict[x]) sp = SpellCheck("big.txt") sp.fit() print("sp算法的预测结果是:", sp.predict("knon"))
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。