【永利澳门游戏网站】机器学习实战笔记,python之朴素贝叶斯对展会数据分类

经过前面的步骤,现在编写代码实在简单,不过有两点要注意。其一是关键词并不是在每个类别都会出现,这样会导致P(keywordcategory)

0,进而导致整个后验概率为0,为了解决这个问题,可以引入拉普拉斯平滑,这样便确保不会出现为0的情况,具体代码中有介绍。其二是若每个调整因子的数值都很小,大家都知道很小的值相乘,会导致结果变得更小,这样子表现出各个分类结果的后验概率便会出现问题,这个问题便是下溢出问题,解决办法便是将其转化为对数,对数相乘便是对数相加,这样便很巧妙的解决了这个问题。好了,直接上代码,让我们看看分类的结果吧。

# -*-coding:utf-8-*-__author__ = 'howie'import jieba.analyseimport pandas as pdimport mathclass Pridict: """ 利用txt/中数据进行朴素贝叶斯算法训练 """ def __init__: # 初始化结果字典 self.resultData = {} def getKeyword(self, path): """ 通过结巴分词进行关键词提取 :param path: 待分词文件路径 相关参数可更改 也可不调用直接写 :return: keywordDic = {index:['word1','word2'...]} """ keywordDic = {} df = pd.read_csv for des in df.values: jieba.analyse.set_idf_path('txt/type_dict.txt') feature = jieba.analyse.extract_tags(des[15], 8) keywordDic[des[16]] = feature return keywordDic def idDic(self, keywordDic): """ 将每条待分类关键词替换成对应的单词向量 :param keywordDic:格式 keywordDic = {index:['word1','word2'...]} :return: keywordDic = {'1': ['12198', '16311', '6253', '8302']} """ with open('txt/id_word.txt', 'r', encoding='utf8') as of: lines = of.read().split for key, values in keywordDic.items(): id_word = [] for eachValue in values: id_word += [eachLine.split[0] for eachLine in lines if eachValue == eachLine.split[-1]] keywordDic[key] = id_word return keywordDic def calPro(self, keywordDic): """ 计算每一组待分类数据关键词对应概率总和 :param keywordDic:格式 keywordDic = {'1': ['12198', '16311', '6253', '8302']} :return: result = {'1': {'type1': -33.23204707236557, 'type3': -31.376043125934267, 'type3': -27.385192803356617...} """ result = {} # print(keywordDic) # 获取每个类别关键词出现概率 with open('txt/tf_id_word.txt', 'r', encoding='utf8') as of: lines = of.read().split[0:-1] # 循环待分类数据 for key, values in keywordDic.items(): result[key] = {} # 读取分类概率文件中读取每行数据 for eachLine in lines: valLen = len valPro = list(map(lambda x: '', [x for x in range(0, valLen)])) laplace = '' # 分类名称 该分类下关键词概率 lineData = eachLine.split # 该分类下每个关键词概率 eachLineData = lineData[-1].split # 循环每个待分类字典的关键字向量 for index,eachValue in enumerate: # 每个关键词对应的词向量以及词概率 得到所有关键词该分类下的概率列表 resPro = [eachPro.split[1] for eachPro in eachLineData if eachValue == eachPro.split[0]] # 防止待分类关键词概率为0,添加拉普拉斯平滑 laplace = str(1 / (valLen + len(eachLineData))) valPro[index] = (resPro[0] if resPro else laplace) valPrlLen = int(valLen / 2) # 处理关键词为空 增加限制条件,排除小概率分类影响后验概率大小 if valPro: if valPro.count <= valPrlLen: # 防止下溢出转化为对数相加 typePro = sum([math.log for x in valPro]) result[key][lineData[0]] = typePro else: # 将该待分类数据标记为None result[key] = None return result def resPro(self, result): """ 为各个分类乘上先验概率 提高分类成功率 :param result: 格式 result = {'1': {'type1': -33.23204707236557, 'type3': -31.376043125934267, 'type3': -27.385192803356617...} :return: resultData = {'1': {'type': -28.135469210164924}} """ for eachKey, eachVal in result.items(): # 初始化每个待分类数据字典 储存最可能分类的概率 self.resultData[eachKey] = {} # 初始化最终分类结果概率 allPro = {} if eachVal: # print with open('txt/type_pro.txt', 'r', encoding='utf8') as of: lines = of.read().split for line in lines: lineData = line.split # 乘上该分类概率 即先验概率 allPro = dict(allPro,**{key:(value + math.log(float(lineData[1]))) for key, value in eachVal.items() if key == lineData[0]}) # 返回各个分类对应后验概率最大值 largest = max(zip(allPro.values(),allPro.keys self.resultData[eachKey][largest[1]] = largest[0] else: # 无法分类 self.resultData[eachKey] = {'failed': None} return self.resultDatadef mainPri(keywordDic): pri = Pridict() dic = pri.idDic(keywordDic) result = pri.calPro resultData = pri.resPro return resultData

初步写好分类器,其实这才是任务的开始,分类器的最重要的是第二部分的数据提取,接下来需要通过不断地训练,让数据变得更加优雅美丽,从而让分类器的结果趋于完美,本人苦逼地调了一个星期,现在也就勉强能用。让我们看看分类器的分类效果:

永利澳门游戏网站 108.png

可以看到分类器给出的参考分类很有代表性,这一段就此结束,若有错误,敬请指出,谢谢。

贝叶斯决策论

在介绍贝叶斯决策论之前,先介绍两个概念:先验概率(prior
probability)和后验概率(posterior probability)。

直观上来讲, 先验概率
是指在事件未发生时,估计该事件发生的概率。比如投掷一枚匀质硬币,“字”朝上的概率。后验概率是指基于某个发生的条件事件,估计某个事件的概率,它是一个条件概率。比如一个盒子里面有5个球,两个红球,三个白球,求在取出一个红球后,再取出白球的概率。
在wiki上, 先验概率的定义为:A prior probability is a marginal
probability, interpreted as a description of what is known about a
variable in the absence of some evidence。 后验概率的定义为:The
posterior probability is the conditional probability of the variable
taking the evidence into account. The probability is computed from the
prior and the likelihood function via Baye’s theorem.

现在以分类任务为例。 首先假设有N种可能的类别标签, 即y={c1, c2, …,
cN}, λij
表示将一个真实标记为cj的样本误分类为ci时产生的损失。后验概率p(ci|x)表示将样本x分类给ci是的概率。那么将样本x分类成ci产生的条件风险(conditional
risk)为:

永利澳门游戏网站 2

其中,P(cj|x) 表示样本x分类成cj类的概率,λij
表示将真实cj类误分类为ci类的损失。所以这个公式就是将x属于其他类(除ci类外)的概率与对应的误分类为ci的损失乘积之和。

我们的目标是寻找一个判定标准,以最小化总体的风险。这个判定准则也叫做贝叶斯判定准则(Bayes
decision rule):
为最小化总体风险,只需要在每个样本上选择那个能使条件风险R(c|x)最小的类别标记,即

永利澳门游戏网站 3

此时,h称为贝叶斯最优分类器(Bayes optional
classifier),与之对应的总体风险R(h
)称之为贝叶斯风险(Bayes risk).
1-R(h*)反映了分类器所能达到的最好性能,即理论上限。

如果把λij定义为:

永利澳门游戏网站 4

那么风险函数可以改写为:

永利澳门游戏网站 5

那么贝叶斯最优分类器的公式可以改写为:

永利澳门游戏网站 6

为了最优化上面的函数,我们必须要知道后验概率p(c|x).但是在现实任务中,很难直接知道这个概率值,所以需要我们使用现有的训练数据估计出这个后验概率。这时候就需要使用贝叶斯公式:

永利澳门游戏网站 7

其中,P(c)是类先验概率,表示在样本空间中,各类样本所占的比例。P(x|c)表示样本x相对于类标签c的类条件概率。直接通过样本计数的方式计算会有点麻烦。原因如下:
假设样本共有d个属性,且属性值都是二值的。那么样本空间至少有2^d个不同的样例。但是在现实生活中,样本空间的个数会远远小于这个数。所以通过计数的方式,直接算出这个概率的方式是不可靠的。

极大似然估计
一般估计类条件概率使用的是极大似然估计。首先我们假设样本符合某个确定的概率分布形式,然后使用极大似然法估计这个分布的参数θ。公式如下:

永利澳门游戏网站 8

其中,Dc表示样本空间中c类组成的样本集和。所以对参数θ的最大似然估计为:

永利澳门游戏网站 9

永利澳门游戏网站 1001.png国内数据比较少,占四百多条,在类别上来看有所属行业这一列,所以比较好处理。国外数据就有些尴尬:永利澳门游戏网站 1102.png国外网站展会数据将近五万多条,跟分类有关的只有categories这一列数据,都是一些标签词,还偏少。现在需要将五万多条展会数据进行分类,如何解决这个问题,我觉得可以写个朴素贝叶斯分类器

引言

前面介绍的分类算法,我们都是期望这个分类算法能够给我们一个确定的分类。但是,有时候,分类器也像我们人类一样,对自己的判断并不是非常有把握。这时候,我们需要分类器告诉我们,它将样本x归为A类的“把握”有多大,即概率有多大。

本文介绍一个非常常见的基于概率框架的分类器:贝叶斯分类器。这个主题分为两个部分:这篇属于理论篇,下一篇文章属于实战篇。

这篇文章分四个部分:1. 贝叶斯决策论;2. 朴素贝叶斯分类器; 3.
半朴素贝叶斯分类器及4.贝叶斯网络

朴素贝叶斯分类器是利用样本数据来进行训练的,每个样本必须含有一组特征词以及对应的分类。

半朴素贝叶斯分类器

前面讲到,
为了降低估计后验概率P(c|x)的难度,朴素贝叶斯分类器采用了属性条件独立性假设,但是在现实任务中这个假设往往不成立。于是,人们放松了这个假设的限制,提出了半朴素贝叶斯分类器的假设(semi-naive
Bayes classifiers)的学习方法。其中, 独依赖估计(one-Dependent Estimator
ODE)是半朴素贝叶斯分类器的一种常用的策略。独依赖估计假设所有的属性都依赖于某一个属性。这里介绍三种基于独依赖估计的半朴素贝叶斯分类器。第一种是SPODE(Super-Parent
ODE),即假设所有的属性都依赖于同一个属性,这个属性也被称之为超父。超父属性的确定通过交叉验证的方式确定。第二种是TAN(Tree
Augmented navie
Bayes)。这种方法的做法是先计算任意两个属性之间的条件互信息(conditional
mutual
information),这样就可以建立一个完全连接图。基于这个图,就可以生成一棵最大带权生成树。这棵树之间的连接关系便是属性之间的依赖关系。最后一种是AODE(Averaged
One-Dependent
Estimator),这种方法的做法是使用每个节点作为超父属性来构造SPODE,然后将具有足够训练数据支撑的SPODE集成起来作为最终的结果。

发表评论

电子邮件地址不会被公开。 必填项已用*标注