问题:
贝叶斯算法想解决什么问题
运用贝叶斯的例子
解决问题的过程是怎么样的
如何用贝叶斯解决拼写纠错
如何用贝叶斯解决错误邮件过滤
如何用贝叶斯解决新闻分类,有哪几种方法,方法如何
贝叶斯算法,就是求逆概的算法,那逆概又是什么呢
我们通常知道的求概率像是一下这种的:
黑球有10个,白球有5个,问抽一次求,是黑球的概率是多少,是白球的概率是多少
这是我们初高中学到的概率
那逆概是怎样的呢:
同样的抽球,但是我们并不知道他们事先有多少个,我们不断去抽,发现黑球出现了100次,白球出现了50次,那么可能球的比例就是1:2,这就是逆概。
贝叶斯算法的公式就是:P(A|B)=P(B|A)*P(A)/P(B)
(P(A|B)就是在B的条件下,A发生的概率)
我们可以这样来理解,现在男生都穿裤子,女生有一部分人穿裤子,一部分穿裙子
A:是女生, B:穿裤子的人
那么现在问题就是:我们知道有一个穿裤子的人,那么她是女生的概率是多大呢(这就是P(A|B))
那我们需要知道穿裤子的人的总数(即P(B)*总人数)、女生的人数(P(A)*总人数)和女生中穿裤子的比例是多少(P(B|A))
就有
P(一个穿裤子的人她是女生的概率)=女生的人数*女生中穿裤子的比例 / 穿裤子的人的总数
总人数在这里可以约掉,即和总人数是没有关系的。
所以贝叶斯转换了需要求的概率,大大降低了求解难度。
贝叶斯的例子:
拼写纠错、拼写检查器、新闻分类,其中拼写纠错和拼写检查器类似
拼写纠错和拼写检查器:
作用就是当你想输入the,但是你输错了,输成了tha,那我们猜测你想要打的是什么,帮你修改
现在很多的输入法都有这样的功能,你可以尝试打一个成语,然后其中一个字的拼音打错,会帮你自动修改成正确的。
那是怎样识别的呢?大致如下
首先我们需要有语料库,知道哪些是正确的单词,正确的单词是怎样的,哪些单词是很常用的,哪些单词没那么常用(这也是我们的先验条件)
然后我们需要对你打错的单词进行猜测,比如, 你输入了tha,这不是正常单词,那有可能是什么,
the、than等等都有可能吧(就需要得到一个可能的单词库)。那么哪一个更可能呢,这时候我们的先验条件起作用了,哪些单词的词频大,也就意味着越有优势,越有可能是想输入的单词,那么也就需要语料库的比对了(奥卡姆剃刀)
简单的话就是直接用词频,也就是哪个词更常用就用哪个。
复杂的话,就需要对上下文语义来理解。(可用gensim的word2vec)
之后我们就可以猜测是想输入哪个单词了。
更加详细的如下,
首先我们获得的语料库,要么直接用别人的,要么自己获取
自己获取就需要用多篇文章,对其进行分词,将每个单词都收录进我们的语料库
文章越多,语料库就越大,猜测词的准确性也就越可能准确(这里用的是词频来决定)
网上有很多种方式可以自行查找pythoon 分词,这里用的是正则表达式+都转换为小写
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
形成自己的语料库的同时,我们把词频也统计了,每个词的默认初始值都是1,同时如果有新的单词出现,那么避免它的数量是0
有了自己的语料库之后,那我们需要对可能的单词进行猜测(也就是对输入的单词进行变形),再用猜测的单词和语料库匹配,把所有可能的单词都找出来
alphabet = 'abcdefghijklmnopqrstuvwxyz'
#w\c 输入是错的单词,找出可能的错的单词,即错的单词的set
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] + # alteration
[word[0:i]+c+word[i:] for i in range(n+1) for c in alphabet]) # insertion
#编辑距离为1
这里的编辑距离为1也就是一个单词中某个单词仅有一个字母发生了变化,增删交换
那么也有可能是编辑距离为2的
def known_edits2(word):
return set(e2 for e1 in edits1(word) for e2 in edits1(e1) if e2 in NWORDS)
#编辑距离为2
也就是再进行一次编辑距离为1的方法
这样就差不多包含了所有可能的单词(本来大多数就可能编辑距离为1,编辑距离为2的单词大多都变了形)
然后就是输入单词,将输入单词进行和我们的语料库来匹配
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=lambda w: NWORDS[w]) #candiates得到set结构,
这里相当于先和语料库匹配一次,成功了就不做后面的匹配。那如果和语料库没有匹配成功的话,会先对输入的单词做编辑距离为1 的变形,然后用变形的结果 和语料库比对,找出所有可能的正确的单词,再选择里面词频最大的一个。编辑距离为2同理。
那么根据词频作为筛选条件,而不是用根据上下文语义的话,会有一点纠错失误,
比如 输入单词为tess , 我们想要的是 test ,但是由于语料库和词频的影响,有可能改成 less ,和我们希望的结果出现偏差。
但是也完成了基本的拼写纠错的功能。
新闻分类
基于贝叶斯算法进行的新闻分类任务有两种,
一种是使用无监督学习的LDA 主题模型 ,另一种是有监督的学习,使用的是sklearn中的模型
两种不同的学习,最后的结果其实也是不一样的,虽然都是分类,但是类表现的结果不一样
而且,无监督只能对现有的数据进行分类,说是分类,其实更像一种聚类,它很像k-means算法
有监督学习因为有训练模型那么可以去预测分类。
而无论是哪种,首先都需要先进行文章获取,然后将文章分词,
中文的分词我们可以使用jieba的节吧分词器(还有其他分词器,大多需要收费,进行学习使用节吧分词器即可)
将文章分完词以后,文章会分解成我们了解的词,之后我们需要进行清洗——使用停用词表
因为文章的一些词,是大量出现,但是对于我们总结文章的主题和对文章的分类是没有什么意义的,或者说没有起到很大的作用,反而会是扰乱我们的想要的结果,例如,各种符号,程度词,还有会大量重复的网络用语(赞,楼主好人)等等,需要看数据来源来知道哪些词是没有意义的
停用词表我们可以使用哈工大的停用词表或者是四川大学机器智能实验库停用词库
使用完停用词后,我们数据经过了清洗会好很多,会提高分类的效果
如果你想看一下清洗后一些数据的情况,我们可以使用词云wordcloud进行可视化的观察
先统计好词频,然后排序选择前几个(词频较大的那几个)进行可视化观察,词频越大的词字体会越大
又或者你希望能够看一下每个文章它的关键词是什么,那么可以直接使用节吧的关键词提取(基于tf 词频)
也可以使用tf-idf ,tf-idf 是比tf 更合理的关键词提取方式,不仅仅考虑到tf 词频,还考虑到idf 逆文档频率,即该词的独特性,该词不会像中国那样,会在很多篇文章中出现。因此仅使用tf的话是有可能把中国当做文章的关键词,而td-idf的话就不会。
然后首先来讲述LDA主题模型——无监督的贝叶斯算法使用
LDA需要用到gensim库(里面也包含了word2vec),数据格式要求是list of list
LDA其实很像K—Means 算法,我们只需要指定我们想要划分为多少类,然后我们把中文进行映射,变成词袋(以计算机能够理解的方式——给每个词一个ID,然后一篇文章就能用向量来表示),之后模型就把我们的数据划分多少类
而每一类的表示是这一类中词频较大的哪几个中文,而不是我们理解的是时尚类,还是经济类,也就是没有我们所想要的标签(这是在有监督学习才会有的,无监督学习没有,只能帮你划分类,每个类都是相近的数据)
相近的数据可以用余弦函数来找到(但如果同样用词频来组成一个向量,那么这个向量表达的含义其实会少了上下文语义的影响)
更详细的的LDA主题模型的解释可以看参考文章
有监督的学习——使用sklearn.naive_bayes的 MultinomialNB进行模型的训练
需要的数据格式是string list
同样要经过数据的清洗,然后因为这是有监督的模型,所以带有label ,label也同样需要转换为数字ID,以便于让计算机读懂
其次,需要将其分为训练集和测试集
然后对分好词的文章,使用向量构造器构造出合适的向量,有两种稍有差异的向量构造器
一个是CountVectorizer,另一个是TfidfVectorizer
前者是只要该文章有某个词就相应位置为1,没有就为0;后者是计算了tf-idf值,而不是单单为1或为0.
比较两者使用的情况,可能会是后者表现更好一点(tf-idf更能凸显同一类文章的位置)
然后就是使用模型MultinomialNB来进行模型训练,之后就是测试。
参考文章:
LDA主题模型 https://blog.csdn.net/qq_39422642/article/details/78730662