漫谈 Clustering (1): k-means
好久没有写 blog 了,一来是 blog 下线一段时间,而租 DreamHost 的事情又一直没弄好;二来是没有太多时间,天天都跑去实验室。现在主要折腾 Machine Learning 相关的东西,因为很多东西都不懂,所以平时也找一些资料来看。按照我以前的更新速度的话,这么长时间不写 blog 肯定是要被闷坏的,所以我也觉得还是不定期地整理一下自己了解到的东西,放在 blog 上,一来梳理总是有助于加深理解的,二来也算共享一下知识了。那么,还是从 clustering 说起吧。
Clustering 中文翻译作“聚类”,简单地说就是把相似的东西分到一组,同 Classification (分类)不同,对于一个 classifier ,通常需要你告诉它“这个东西被分为某某类”这样一些例子,理想情况下,一个 classifier 会从它得到的训练集中进行“学习”,从而具备对未知数据进行分类的能力,这种提供训练数据的过程通常叫做 supervised learning (监督学习),而在聚类的时候,我们并不关心某一类是什么,我们需要实现的目标只是把相似的东西聚到一起,因此,一个聚类算法通常只需要知道如何计算相似 度就可以开始工作了,因此 clustering 通常并不需要使用训练数据进行学习,这在 Machine Learning 中被称作 unsupervised learning (无监督学习)。
举一个简单的例子:现在有一群小学生,你要把他们分成几组,让组内的成员之间尽量相似一些,而组之间则差别大一些。最后分出怎样的结果,就取决于你对于“相似”的定义了,比如,你决定男生和男生是相似的,女生和女生也是相似的,而男生和女生之间则差别很大”,这样,你实际上是用一个可能取两个值“男”和“女”的离散变量来代表了原来的一个小学生,我们通常把这样的变量叫做“特征”。实际上,在这种情况下,所有的小学生都被映射到了两个点的其中一个上,已经很自然地形成了两个组,不需要专门再做聚类了。另一种可能是使用“身高”这个特征。我在读小学候,每周五在操场开会训话的时候会按照大家住的地方的地域和距离远近来列队,这样结束之后就可以结队回家了。除了让事物映射到一个单独的特征之外,一种常见的做法是同时提取 N 种特征,将它们放在一起组成一个 N 维向量,从而得到一个从原始数据集合到 N 维向量空间的映射——你总是需要显式地或者隐式地完成这样一个过程,因为许多机器学习的算法都需要工作在一个向量空间中。
那么让我们再回到 clustering 的问题上,暂且抛开原始数据是什么形式,假设我们已经将其映射到了一个欧几里德空间上,为了方便展示,就使用二维空间吧,如下图所示:
从数据点的大致形状可以看出它们大致聚为三个 cluster ,其中两个紧凑一些,剩下那个松散一些。我们的目的是为这些数据分组,以便能区分出属于不同的簇的数据,如果按照分组给它们标上不同的颜色,就是这个样子:
那么计算机要如何来完成这个任务呢?当然,计算机还没有高级到能够“通过形状大致看出来”,不过,对于这样的 N 维欧氏空间中的点进行聚类,有一个非常简单的经典算法,也就是本文标题中提到的 k-means 。在介绍 k-means 的具体步骤之前,让我们先来看看它对于需要进行聚类的数据的一个基本假设吧:对于每一个 cluster ,我们可以选出一个中心点 (center) ,使得该 cluster 中的所有的点到该中心点的距离小于到其他 cluster 的中心的距离。虽然实际情况中得到的数据并不能保证总是满足这样的约束,但这通常已经是我们所能达到的最好的结果,而那些误差通常是固有存在的或者问题本身的不可分性造成的。例如下图所示的两个高斯分布,从两个分布中随机地抽取一些数据点出来,混杂到一起,现在要让你将这些混杂在一起的数据点按照它们被生成的那个分布分开来:
由于这两个分布本身有很大一部分重叠在一起了,例如,对于数据点 2.5 来说,它由两个分布产生的概率都是相等的,你所做的只能是一个猜测;稍微好一点的情况是 2 ,通常我们会将它归类为左边的那个分布,因为概率大一些,然而此时它由右边的分布生成的概率仍然是比较大的,我们仍然有不小的几率会猜错。而整个阴影部分是我们所能达到的最小的猜错的概率,这来自于问题本身的不可分性,无法避免。因此,我们将 k-means 所依赖的这个假设看作是合理的。
基于这样一个假设,我们再来导出 k-means 所要优化的目标函数:设我们一共有 N 个数据点需要分为 K 个 cluster ,k-means 要做的就是最小化
这个函数,其中 在数据点 n 被归类到 cluster k 的时候为 1 ,否则为 0 。直接寻找
和
来最小化
并不容易,不过我们可以采取迭代的办法:先固定
,选择最优的
,很容易看出,只要将数据点归类到离他最近的那个中心就能保证
最小。下一步则固定
,再求最优的
。将
对
求导并令导数等于零,很容易得到
最小的时候
应该满足:
亦即 的值应当是所有 cluster k 中的数据点的平均值。由于每一次迭代都是取到
的最小值,因此
只会不断地减小(或者不变),而不会增加,这保证了 k-means 最终会到达一个极小值。虽然 k-means 并不能保证总是能得到全局最优解,但是对于这样的问题,像 k-means 这种复杂度的算法,这样的结果已经是很不错的了。
下面我们来总结一下 k-means 算法的具体步骤:
- 选定 K 个中心
的初值。这个过程通常是针对具体的问题有一些启发式的选取方法,或者大多数情况下采用随机选取的办法。因为前面说过 k-means 并不能保证全局最优,而是否能收敛到全局最优解其实和初值的选取有很大的关系,所以有时候我们会多次选取初值跑 k-means ,并取其中最好的一次结果。
- 将每个数据点归类到离它最近的那个中心点所代表的 cluster 中。
- 用公式
计算出每个 cluster 的新的中心点。
- 重复第二步,一直到迭代了最大的步数或者前后的
的值相差小于一个阈值为止。
按照这个步骤写一个 k-means 实现其实相当容易了,在 SciPy 或者 Matlab 中都已经包含了内置的 k-means 实现,不过为了看看 k-means 每次迭代的具体效果,我们不妨自己来实现一下,代码如下(需要安装 SciPy 和 matplotlib) :
1 |
#!/usr/bin/python |
代码有些长,不过因为用 Python 来做这个事情确实不如 Matlab 方便,实际的 k-means 的代码只是 41 到 47 行。首先 3 个中心点被随机初始化,所有的数据点都还没有进行聚类,默认全部都标记为红色,如下图所示:
然后进入第一次迭代:按照初始的中心点位置为每个数据点着上颜色,这是代码中第 41 到 43 行所做的工作,然后 45 到 47 行重新计算 3 个中心点,结果如下图所示:
可以看到,由于初始的中心点是随机选的,这样得出来的结果并不是很好,接下来是下一次迭代的结果:
可以看到大致形状已经出来了。再经过两次迭代之后,基本上就收敛了,最终结果如下:
不过正如前面所说的那样 k-means 也并不是万能的,虽然许多时候都能收敛到一个比较好的结果,但是也有运气不好的时候会收敛到一个让人不满意的局部最优解,例如选用下面这几个初始中心点:
最终会收敛到这样的结果:
不得不承认这并不是很好的结果。不过其实大多数情况下 k-means 给出的结果都还是很令人满意的,算是一种简单高效应用广泛的 clustering 方法。
Update 2010.04.25: 很多人都问我要 cluster.pkl ,我干脆把它上传上来吧,其实是很容易自己生成的,点击这里下载。
漫谈 Clustering (1): k-means的更多相关文章
- 漫谈 Clustering (4): Spectral Clustering
转:http://blog.pluskid.org/?p=287 如果说 K-means 和 GMM 这些聚类的方法是古代流行的算法的话,那么这次要讲的 Spectral Clustering 就可以 ...
- 漫谈 Clustering (番外篇): Dimensionality Reduction
由于总是有各种各样的杂事,这个系列的文章竟然一下子拖了好几个月,(实际上其他的日志我也写得比较少),现在决定还是先把这篇降维的日志写完.我甚至都以及忘记了在这个系列中之前有没有讲过“特征”(featu ...
- 漫谈 Clustering (2): k-medoids
上一次我们了解了一个最基本的 clustering 办法 k-means ,这次要说的 k-medoids 算法,其实从名字上就可以看出来,和 k-means 肯定是非常相似的.事实也确实如此,k-m ...
- 漫谈 Clustering (3): Gaussian Mixture Model
上一次我们谈到了用 k-means 进行聚类的方法,这次我们来说一下另一个很流行的算法:Gaussian Mixture Model (GMM).事实上,GMM 和 k-means 很像,不过 GMM ...
- 漫谈 Clustering (4): Spectral Clustering<转载>
转自http://blog.pluskid.org/?p=287 如果说 K-means 和 GMM 这些聚类的方法是古代流行的算法的话,那么这次要讲的 Spectral Clustering 就可以 ...
- KNN 与 K - Means 算法比较
KNN K-Means 1.分类算法 聚类算法 2.监督学习 非监督学习 3.数据类型:喂给它的数据集是带label的数据,已经是完全正确的数据 喂给它的数据集是无label的数据,是杂乱无章的,经过 ...
- 漫谈 Clustering (番外篇): Expectation Maximization
Expectation Maximization (EM) 是一种以迭代的方式来解决一类特殊最大似然 (Maximum Likelihood) 问题的方法,这类问题通常是无法直接求得最优解,但是如果引 ...
- 漫谈 Clustering (番外篇): Vector Quantization
在接下去说其他的聚类算法之前,让我们先插进来说一说一个有点跑题的东西:Vector Quantization.这项技术广泛地用在信号处理以及数据压缩等领域.事实上,在 JPEG 和 MPEG-4 等多 ...
- 漫谈 Clustering (5): Hierarchical Clustering
系列不小心又拖了好久,其实正儿八经的 blog 也好久没有写了,因为比较忙嘛,不过觉得 Hierarchical Clustering 这个话题我能说的东西应该不多,所以还是先写了吧(我准备这次一个公 ...
随机推荐
- MCP|MZL|Accurate Estimation of Context- Dependent False Discovery Rates in Top- Down Proteomics 在自顶向下蛋白组学中精确设定评估条件估计假阳性
一. 概述: 自顶向下的蛋白质组学技术近年来也发展成为高通量蛋白定性定量手段.该技术可以在一次的实验中定性上千种蛋白,然而缺乏一个可靠的假阳性控制方法阻碍了该技术的发展.在大规模流程化的假阳性控制手段 ...
- php模拟post提交数据
$data = '{ "id": "17999030", "method": "sayHello", "jso ...
- JMeter - 如何创建可重用和模块化测试脚本
概述: 我的应用程序几乎没有业务关键流程,我们可以从中提出不同的业务工作流程.当我试图在JMeter中提出性能测试脚本时,我需要找到一些方法来创建可重用/模块化的测试脚本.这样我就可以创建不同的工作流 ...
- BeanFilterUtil
package com.yundaex.utility.bean.filter; import java.util.ArrayList; import java.util.List; import o ...
- 【手撸一个ORM】第七步、SqlDataReader转实体
说明 使用Expression(表达式目录树)转Entity的文章在园子里有很多,思路也大致也一样,我在前面有篇文章对解决思路有些说明,有兴趣的小伙伴可以看下 (传送门),刚接触表达式目录树时写的,不 ...
- HDU - 4366 Successor DFS序 + 分块暴力 or 线段树维护
给定一颗树,每个节点都有忠诚和能力两个参数,随意指定一个节点,要求在它的子树中找一个节点代替它,这个节点要满足能力值大于它,而且是忠诚度最高的那个. 首先,dfs一下,处理出L[i], R[i]表示d ...
- Storm概念学习系列之Worker、Task、Executor三者之间的关系
不多说,直接上干货! Worker.Task.Executor三者之间的关系 Storm集群中的一个物理节点启动一个或者多个Worker进程,集群的Topology都是通过这些Worker进程运行的. ...
- js事件循环(event loop)
我们都知道,js是单线程的,虽然现在有 worker 的存在,但是也只是可以进行运算,并不能操作 dom: js最一开始执行的线程,是主线程,然后主线程执行完毕后,是微队列 microtask 的循环 ...
- spring mvc 注解扫描问题 ,扫描不到controller, use-default-filters="false"
今天搭了个spring mvc项目,怎么也扫描不到controller,最后发现问题在use-default-filters="false"上面,乱copy出的问题 (默认值是tr ...
- css3的transform变换scale和translate等影响jQuery的position().top和offset().top
css3的transform变换scale和translate等影响jQuery的position().top和offset().top