在此推出一个算法系列的科普文章。我们大家在平时埋头工程类工作之余,也可以抽身对一些常见算法进行了解,这不仅可以帮助我们拓宽思路,从另一个维度加深对计算机技术领域的理解,做到触类旁通,同时也可以让我们搞清楚一些既熟悉又陌生的领域——比如数据挖掘、大数据、机器学习——的基本原理,揭开它们的神秘面纱,了解到其实很多看似高深的领域,其实背后依据的基础和原理也并不复杂。而且,掌握各类算法的特点、优劣和适用场景,是真正从事数据挖掘工作的重中之重。只有熟悉算法,才可能对纷繁复杂的现实问题合理建模,达到最佳预期效果。
本系列文章的目的是力求用最干练而生动的讲述方式,为大家讲解由国际权威的学术组织the IEEE International Conference on Data Mining (ICDM) 于2006年12月评选出的数据挖掘领域的十大经典算法。它们包括:
1. C4.5(c4.5决策树算法)
2. k-Means(k均值算法)
3. SVM(支持向量机)
4. Apriori(先验算法)
5. EM(期望最大算法)
6. PageRank(google的网页排序算法)
7. AdaBoost(Adaptive Boosting自适应增强算法)
8. kNN(k近邻算法)
9. Naive Bayes(朴素贝叶斯)
10. CART(分类与回归树)
一点铺垫
本文作为本系列的第一篇,在介绍具体算法之前,先简单为大家铺垫几个数据挖掘领域的常见概念:
在数据挖掘领域,按照算法本身的行为模式和使用目的,主要可以分为分类(classification),聚类(clustering)和回归(regression)几种,其中:
-
分类 通常是在已经给定了几种类别和一部分属于这些类别的数据的前提下,寻找分类规律,从而对没有标注类别的数据进行类别划分的行为。而这些事先给出的已经分好类的示例数据通常被称之为训练集,而这种通过已经标注了输入与输出关系训练集寻找规律的学习行为,在机器学习领域称之为监督式学习(Supervised learning)。
-
聚类 与分类十分类似,都是以找到数据和类别之间的关系作为最终目的。不同的是,聚类一开始并没有给定的类别和训练集,而直接由算法找出其中潜在规律。聚类的目的在于把相似的东西聚在一起,而有时我们甚至并不关心这一类是什么。这种没有训练集作为参照而直接对输入数据进行建模的学习方式被称为无监督的学习(Unsupervised learning)。
-
回归 则是通过有限的输入数据,找出一个能描述数据潜在规律的函数,从而对未来的走势进行预测。
打几个不恰当的比方:
- 分类就好似垃圾归类,一共就三种垃圾桶,并告诉你哪几种垃圾扔进哪个桶,通过分析得知将来要扔的所有垃圾该往哪儿扔;
- 聚类就像生物划分界门纲目科属种,一开始根本不知道全世界的生物有多少种类,通过不断摸索找出这些类别;
- 而回归就像是在探索一个能描述一切的万物理论,不仅要能完美解释当前观察到的所有现象,还能对未来做出精确预测。
另外,还有一个经常有人问起的问题,就是数据挖掘和机器学习这两个概念的区别,这里一句话阐明我自己的认识:机器学习是基础,数据挖掘是应用。机器学习研制出各种各样的算法,数据挖掘根据应用场景把这些算法合理运用起来,目的是达到最好的挖掘效果。
当然,以上的简单总结一定不够准确和严谨,更多的是为了方便大家理解打的比方。如果大家有更精当的理解,欢迎补充和交流。
进入正题
好了,铺垫了这么多,现在终于进入正题!
作为本系列入门的第一篇,先为大家介绍一个容易理解又很有趣的算法——朴素贝叶斯。
先站好队,朴素贝叶斯是一个典型的有监督的分类算法。
贝叶斯定理
光从名字也可以想到,要想了解朴素贝叶斯,先要从贝叶斯定理说起。
贝叶斯定理是我们高中时代学过的一条概率学基础定理,它描述了条件概率的计算方式。不要怕已经把这些知识还给了体育老师,相信你一看公式就能想起来。
P(A|B)表示事件B已经发生的前提下,事件A发生的概率,叫做事件B发生下事件A的条件概率。其基本求解公式为:
其中,P(AB)表示A和B同时发生的概率,P(B)标识B事件本身的概率。
贝叶斯定理之所以有用,是因为我们在生活中经常遇到这种情况:我们可以很容易直接得出P(A|B),P(B|A)则很难直接得出,但我们更关心P(B|A)。
举个栗子,通过历次美国大选,我们可以得知,投票给共和党的选票有多大概率来自加州,但我们更关心的是,一张来自加州的选票,有多大概率会投给共和党
(当然,美国大选真正的投票机制并不是一人一票的简单投票制,这里只是为了示意)。
而贝叶斯定理就为我们打通从P(A|B)获得P(B|A)的道路。
下面不加证明地直接给出贝叶斯定理:
朴素贝叶斯的基本思路
有了贝叶斯定理这个基础,下面来看看朴素贝叶斯算法的基本思路。
朴素贝叶斯的核心思想就是,你不是要给我分类吗?我算出自己属于各个分类的条件概率,属于谁的概率最大,就归入哪一类。
你看,其思想就是这么的朴素。那么,属于每个分类的概率该怎么计算呢?下面我们先祭出形式化语言!
-
设
x = {a1, a2, ..., am}
为一个待分类项,而每个a为x的一个特征属性。 -
有类别集合
C = {y1, y2, ..., yn}
-
我们的目的是要计算以下值
P(y1|x), P(y2|x), ... ,P(yn|x)
-
如果
P(yk|x) = max{P(y1|x), P(y2|x), ... ,P(yn|x)}
则x属于yk
那么现在的关键就是如何计算第3步中的各个条件概率。我们可以这么做:
-
找到一个已知分类的待分类项集合,这个集合叫做训练样本集。
-
统计得到在各类别下各个特征属性的条件概率估计。即
P(a1|y1), P(a2|y1),...,P(am|y1); P(a1|y2), P(a2|y2),...,P(am|y2); ...; P(a1|yn), P(a2|yn),...,P(am|yn);
- 如果各个特征属性是条件独立的,则根据贝叶斯定理有如下推导:
因为分母对于所有类别为常数,因为我们只要将分子最大化皆可。又因为各特征属性是条件独立的,所以有:
别被形式化吓倒,我们来举个栗子
如果你也跟我一样,对形式化语言有严重生理反应,不要怕,直接跳过前面这一坨,我们通过一个鲜活的例子,用人类的语言再解释一遍这个过程。
以下这个例子转自博客http://www.ruanyifeng.com/blog/2013/12/naive_bayes_classifier.html
某个医院早上收了六个门诊病人,如下表。
症状 | 职业 | 疾病 |
---|---|---|
打喷嚏 | 护士 | 感冒 |
打喷嚏 | 农夫 | 过敏 |
头痛 | 建筑工人 | 脑震荡 |
头痛 | 建筑工人 | 感冒 |
打喷嚏 | 教师 | 感冒 |
头痛 | 教师 | 脑震荡 |
现在又来了第七个病人,是一个打喷嚏的建筑工人。请问他最有可能患有何种疾病?
本质上,这就是一个典型的分类问题,症状和职业是特征属性,疾病种类是目标类别
根据贝叶斯定理
P(A|B) = P(B|A) P(A) / P(B)
可得
P(感冒|打喷嚏x建筑工人)
= P(打喷嚏x建筑工人|感冒) x P(感冒)
/ P(打喷嚏x建筑工人)
假定"打喷嚏"和"建筑工人"这两个特征是独立的,因此,上面的等式就变成了
P(感冒|打喷嚏x建筑工人)
= P(打喷嚏|感冒) x P(建筑工人|感冒) x P(感冒)
/ P(打喷嚏) x P(建筑工人)
这是可以计算的。
P(感冒|打喷嚏x建筑工人)
= 0.66 x 0.33 x 0.5 / 0.5 x 0.33
= 0.66
因此,这个打喷嚏的建筑工人,有66%的概率是得了感冒。同理,可以计算这个病人患上过敏或脑震荡的概率。比较这几个概率,就可以知道他最可能得什么病。
再举个栗子
接下来,我们再举一个朴素贝叶斯算法在实际中经常被使用的场景的例子——文本分类器,通常会用来识别垃圾邮件。
首先,我们可以把一封邮件的内容抽象为由若干关键词组成的集合,这样是否包含每种关键词就成了一封邮件的特征值,而目标类别就是属于垃圾邮件或不属于垃圾邮件
假设每个关键词在一封邮件里出现与否的概率相互之间是独立的,那么只要我们有若干已经标记为垃圾邮件和非垃圾邮件的样本作为训练集,那么就可以得出,在全部垃圾邮件(记为Trash)出现某个关键词Wi的概率,即P(Wi|Trash)
而我们最重要回答的问题是,给定一封邮件内容M,它属于垃圾邮件的概率是多大,即P(Trash|M)
根据贝叶斯定理,有
P(Trash|M) = P(M|Trash) * P(Trash) / P(M)
我们先来看分子:
P(M|Trash)
可以理解为在垃圾邮件这个范畴中遇见邮件M的概率,而一封邮件M是由若干单词Wi独立汇聚组成的,只要我们所掌握的单词样本足够多,因此就可以得到
P(M|Trash) = P(W1|Trash) * P(W2|Trash) * ... P(Wn|Trash)
这些值我们之前已经可以得到了。
再来看分子里的另一部分P(Trash)
,这个值也就是垃圾邮件的总体概率,这个值显然很容易得到,用训练集中垃圾邮件数除以总数即可。
而对于分母来说,我们虽然也可以去计算它,但实际上已经没有必要了,因为我们要比较的P(Trash|M)
和P(non-Trash|M)
的分母都是一样的,因此只需要比较分子大小即可。
这样一来,我们就可以通过简单的计算,比较邮件M属于垃圾还是非垃圾二者谁的概率更大了。
朴素贝叶斯朴素在哪?
朴素贝叶斯的英文叫做Naive Bayes,直译过来其实是天真的贝叶斯,那么他到底天真在哪了呢?
这主要是因为朴素贝叶斯的基本假设是所有特征值之间都是相互独立的,这才使得概率直接相乘这种简单计算方式得以实现。然而在现实生活中,各个特征值之间往往存在一些关联,比如上面的例子,一篇文章中不同单词之间一定是有关联的,比如有些词总是容易同时出现。
因此,在经典朴素贝叶斯的基础上,还有更为灵活的建模方式——贝叶斯网络(Bayesian Belief Networks, BBN),可以单独指定特征值之间的是否独立。这里就不展开了,有兴趣的同学们可以做进一步了解。
优缺点
最后我们来对这个经典算法做个点评:
优点:
- 计算效率高
- 容易实现
- 计算复杂度不随特征值维度增加而增加,可以处理高维度问题
缺点:
- 对于特征值之间关系的假设过于单纯,并不适用于关联度较为复杂的模型
好了,对于朴素贝叶斯的介绍就到这里,不知道各位看完之后是否会对数据挖掘这个领域产生了一点兴趣了呢?
网友评论