数据挖掘笔记八:贝叶斯

在概率论里面,贝叶斯可是鼎鼎大名,所以贝叶斯是基于概率的另一种分类器。

朴素贝叶斯

如果根据上面的贝叶斯公式,去计算一百条数据,条条数据十个属性,那么按照贝叶斯算法,每条数据的各个概率再联合另外的属性,另外的数据去计算,计算量会很大,如果是十万百万的数据是根本没有可能算完的。

我们知道在贝叶斯里面,如果两个事件相互独立,那么算起来就简单多了, P( A 交 B ) = P( A ) * P( B ) 。

而 Naive Bayesian(中文译朴素贝叶斯,为数不多的翻译的好听的词),实际上就是做了这样一个假设,假设所有数据里的各种属性是独立的,那么就可以运用独立事件的特性。可能结果并没有标准的贝叶斯那么精确,但计算量一下子降低 N 个指数级别!

算法

朴素贝叶斯主要有两种算法实现,一种基于伯努力模型(二项分布模型),一种基于多项式,如果属性满足伯努力分布当然是可以用伯努力模型了,但一般不满足,不做研究,直接从公式入手。

还是上次的数据,使用贝叶斯换着来玩的话,过程应该是以下这样子:

  1. 计算第一个属性的条件概率,即P ( 工作类型 | 年收入 )已知年收入的情况下的概率,说明:这里的计算的是概率密度,对于连续型变量,没有值的,可以使用分布图上的密度值来代替结果~,也就不用一个一个算了。
    • 计算 P(个体 | 年收入高)
    • 计算 P(个体 | 年收入低)
    • 计算 P(自由职业 | 年收入高)
    • 计算 P(自由职业 | 年收入低)
    • 计算 P(责任公司 | 年收入高)
    • 计算 P(责任公司 | 年收入低)
    • …… 计算出所有属性对应的年收入高,低
  2. 按第一步,计算出其它属性。得到所有属性对于年收入高低的密度值
  3. 没有第三,已经完成了!
  4. 预测:
    假设数据为 [个体,男,美国] ,那么:
    年收入高的密度 = P (工作类型 | 年收入高) x P (性别 | 年收入高) x P (国籍 | 年收入高)
    即 P (个体 | 年收入高) x P (男 | 年收入高) x P (美国 | 年收入高)
    相应的说,年收入低的密度即为 P (个体 | 年收入低) x P (男 | 年收入低) x P (美国 | 年收入低)
    所谓的预测,就是我们选择可能性大的。所以做个排序,最大的就是结果了。

代码

直接用SkLearn其实很简单,核心是以下四行代码,其中arr_x,arr_y是我把数据预处理后的数据和label数组,由于预处理方法很长也没什么价值就不帖了,将结果提交上去,准确率居然可以达到85%。

1
2
3
4
from sklearn import naive_bayes
clf = naive_bayes.GaussianNB() # 高斯分布
clf.fit(arr_x, arr_y)
res_arr = clf.predict(testing_arr)

贝叶斯这种算法最主要的有点应该是性能当不错,后续维护起来也不需要经常重算,算好一个模型后,有大量新数据导入时再更新基础概率,这样一条新的数据基本可以不需要什么计算就分好类了。

贝叶斯网络

由于朴素贝叶斯做了一个假设,所有事件都是相互独立的,导致本来一些息息相关的属性在计算过程中以独立事件计算,产生一些误差。

比如很多时候我们采集人的信息,比如年龄学历收入这些属性是有内部关系的,贝叶斯网络定义包括一个有向无环图(DAG)和一个条件概率表集合。

DAG中每一个节点表示一个随机变量,可以是可直接观测变量或隐藏变量,而有向边表示随机变量间的条件依赖;条件概率表中的每一个元素对应DAG中唯一的节点,存储此节点对于其所有直接前驱节点的联合条件概率。

小结

贝叶斯是个人最喜欢的算法这一,从计算性能、模型维护都是妥妥的简单,而且概率又有一定的可解释性。

在使用 SkLearn 之前,个人也造过轮子,根据贝叶斯算法的原理自己实现了一个,支持标量,但最后的结果还是不如转换了数据之后的 SkLearn, 后续有空优化了再贴出来。