七月算法4月机器学习算法班课程笔记——No.10
前言
与回归与分类不同,聚类是无监督学习算法,无监督指的是只需要数据,不需要标记结果,试图探索和发现一些模式。比如对用户购买模式的分析、图像颜色分割等。聚类算法的提出比较早,是数据挖掘的一个重要模块,可以对大量数据分类并概括出每一类的特点。目前也有很多种聚类算法,包括划分法、层次法、基于密度的方法、基于网格的方法等。实际生产中,很少有只用聚类算法的系统,因为聚类效果的好坏不容易衡量,有时候会用做监督学习中稀疏特征的预处理。
接下来会重点介绍K-means聚类、层次聚类和混合高斯模型。
1. 聚类算法思想
聚类算法的思想:给定N个训练样本(未标记的)x1,x2,...,xN,目标是把比较“接近” 的样本放到一个cluster里, 总共得到K个cluster。没有给定标记,聚类唯一会使用到的信息是样本与样本之间的相似度,聚类就是根据样本相互之间的相似度“抱团” 的。那么怎么评定聚类的好坏呢?——也是用相似度评定,会尽量希望“ 高类内相似度, 低类间相似度”。
评定内容的选择:相似度评定对于聚类至关重要,选用的评定内容决定了相似度的偏向。看下面的两张图:
如果以轮廓和色调作为评定标准,那么这两张图很容易被分为一类,如果以眼睛鼻子来评定,就能区分开。所以在不同的场景下,应该选用不同的评定内容。例如:
- 图片检索: 图片内容相似度
- 图片分割: 图片像素(颜色)相似度
- 网页聚类: 文本内容相似度
- 社交网络聚类: (被)关注人群, 喜好, 喜好内容
- 电商用户聚类: 点击/加车/购买商品, 行为序列。比如按时间聚类,夜晚12点以后还在购物的多是学生党。
计算相似度距离:不管用什么样的评定内容,最终都会把样本表示成向量,那么向量的距离怎么表示呢?常用的距离计算公式有:
- 欧式距离
d(x,z)=∥x?z∥=∑d=1D(xd?zd)2????????????
- 曼哈顿距离
d(x,z)=∑d=1D|xd?zd|
- 余弦距离:保证不了迭代的收敛,中心距离不像欧式距离简单直观。
- 核函数映射后距离
d(x,z)=∥?(x)??(z)∥
接下来细讲的三个算法中,K-means, 高斯混合模型是一个独立于另外一个的,需要输入聚类个数;层次聚类可以看做树状层叠,无需初始输入聚类个数。
2. K-means聚类
2.1 K-means聚类算法
K-means是提出非常早, 使用非常频繁的聚类算法。之前面试的时候我以为面试官会问比较难的聚类算法,但是发现多是问k-means,不过不仅仅是描述算法,要知道k-means的优缺点、适用场合,会问一些细致的问题。现在理解为什么了,因为公司大多也不会用太复杂的算法,K-means算是聚类中用的最多的了。
输入:N个样本、拟定的聚类个数K
初始化:随机初始化K个D维的向量 或 选取K个不同的样本点作为初始聚类中心
迭代直至收敛:
1. 对于每个样本xn都指定其为离其最近的聚类中心的cluster
2. 重新计算聚类中心
迭代收敛怎么定义呢? 一是聚类中心不再有变化,二是每个样本到对应聚类中心的距离之和不再有很大变化。
下面演示聚类的过程。
初始化:比如以下样本点要聚成2类,先随机初始化两个中心点。
计算距离,分类:对原始数据中的每个样本点,分别计算到两个中心点的距离,样本点离哪个中心的距离近,就分到相应的类别中。如下图,得到两个类别的分隔线,其实这条线也可以是两个点的垂直平分线,因为垂直平分线的性质可知,垂直平分线上的点,到两个中心点的距离相同。
重新计算中心点:把蓝色点的位置的平均值作为蓝色的中心点,同理红色。
迭代:重新计算距离分类,重新计算中心点,知道达到了收敛条件。
2.2 初始化中心的选择
K-means算法确实是对初始化聚类中心敏感的,比较好的初始中心不仅可以降低迭代次数,也会引导更好的聚类结果。上面提到,初始化中心是随机产生的,那么怎么优化初始化中心呢?
1. 初始第一个聚类中心为某个样本点, 初始第二个聚类中心为离它最远的点, 第三个为离它俩最远的。
2. 多初始化几遍, 选所有这些聚类中损失函数(到聚类中心和)最小的。其中损失函数的定义如下。假定μ1,...,μk为k个聚类中心,用rnk∈0,1表示xn是否属于聚类k,则损失函数的散度(混乱度)为:
J(μ,r)=∑n=1N∑k=1Krnk∥xn?μk∥2
3. 使用优化的初始化聚类方法。例如Arthur 和 Vassilvitskii 提出的Kmeans++,会找最远的一些点初始化。
2.3 K值的选择
k-means的输入需要知道聚类个数,对于大量的数据,我们如何知道应该分为几类合理呢?而且k值选的不好确实会出现下面的状况,例如数据实际上划分为2类比较合理,如果硬性的划分为1类,或者3类,就没有很好的效果。
选择方法:“肘点” 法。选取不同的K值,画出损失函数曲线。
这里分析之后可以取k=2,因为2之后的损失函数变化不大。肘点法是教科书上经常介绍的方法,但是实际工作中,肘点法却不见得好用。
【实际案例】:有80w个商品的图片,希望实现聚类,每100个数据为一类。
直观思路:80w/100,约为8000个类,然后设置k=8000,把像素值展开跑实验,没有优化默认跑十遍,
实验数据要跑两三天。
优化思路:把商家的文本描述,比如颜色,长短等,先按文本聚200个类,然后并行的对这200各类按
照上述方式实验,三个小时可以完成。
聚类个数k怎么定呢?肘点法太耗时了。建议先定估计一个值,聚类后观察每个簇的元素个数,若有一些
簇元素很少,考虑降低k,如果比较平均,在考虑增加k。若某个簇元素个数很多,可以考虑单
独对这个簇再聚类。
嗯,这也是海量数据数理的常用方法——分治法。
下图表示了不同的K取值对图像分割的影响(聚类很多时候也是业务相关的)。
2.4 K-means局限性
1. 属于“硬聚类” , 每个样本只能有一个类别。 其他的一些聚类方法(GMM或者模糊K-means允许“软聚类”)。
2. K-means对异常点的“免疫力” 很差, 我们可以通过一些调整,比如中心不直接取均值, 而是找均值最近的样本点代替——k-medoids算法。
3. 对于团状的数据点集区分度好, 对于带状(环绕)等“非凸”形状不太好。 (用谱聚类或者做特征映射)
3. 层次聚类
K-means里面的K太难确定了,有的同学会有疑惑“无监督的聚类还需要指定k呀?有没有不需要指定k的聚类呢?“,下面来看看层次聚类。层次聚类是教科书上必讲的内容,比较容易理解,层次聚类就是通过对数据集按照某种方法进行层次分解,直到满足某种条件为止。按照分类原理的不同,可以分为凝聚和分裂两种方法。
凝聚型:比如有五个样本,先把每一个样本看做一簇,然后选择最近的两个样本归为一簇,得到4个簇,然后4个簇中选两个最近的簇作为一簇,直到所有的样本聚在一起就停止。可以想象整个过程会很慢。
算法中比较重要的是计算cluster R和cluster S之间的距离,介绍三种方法:
1. 最小连接距离法
d(R,S)=minxR∈R,xS∈Sd(xR,xS)
2. 最大连接距离法
d(R,S)=maxxR∈R,xS∈Sd(xR,xS)
3. 平均连接距离法
d(R,S)=1|R∥S|∑xR∈R,xS∈Sd(xR,xS)
虽然慢,但是还是有好处的,比如生物上基因工程应用广泛,因为可以得到每个粒度的情况。
K-means VS 层次聚类?
1. K-means这种扁平聚类产出一个聚类结果(都是独立的)
2. 层次聚类能够根据你的聚类程度不同,有不同的结果
3. K-means需要指定聚类个数K,层次聚类不用
4. K-means比层次聚类要快一些(通常说来)
5. K-means用的多
4. 混合高斯模型(GMM)
高斯模型,给定均值和方差,将一个事物分解为基于高斯概率密度函数(正态分布曲线)形成的模型。
P(x)=φ(x;μ,σ)=1σ2π??√exp(?(x?μ)22σ2)
但是有时候不是只有一个密集区域,而是多个密集区域,需要多个高斯模型线性加权而成。高斯混合模型就是用高斯概率密度函数(正态分布曲线)精确地量化事物,它是一个将事物分解为若干的基于高斯概率密度函数形成的模型。
P(C=i)=ωi,P(x|C=i)=φ(x;μi,σi)P(x)=∑i=1KP(x,C=i)=∑i=1KP(C=i)P(x|C=i)=ωiφ(x;μi,σi)
根据上面的式子,如果我们要从 GMM 的分布中随机地取一个点的话,实际上可以分为两步:首先随机地在这 K 个 Component 之中选一个,每个 Component 被选中的概率实际上就是它的系数 ωi ,选中了 Component 之后,再单独地考虑从这个 Component 的分布中选取一个点就可以了──这里已经回到了普通的 Gaussian 分布,转化为了已知的问题。
那么如何用 GMM 来做 clustering 呢?其实很简单,现在我们有了数据,假定它们是由 GMM 生成出来的,那么我们只要根据数据推出 GMM 的概率分布来就可以了,然后 GMM 的 K 个 Component 实际上就对应了 K 个 cluster 了。根据数据来推算概率密度通常被称作 density estimation,特别地,当我们在已知(或假定)了概率密度函数的形式,而要估计其中的参数的过程被称作“参数估计”。
GMM的优势:
1. 可理解性好,可看做多个分布的组合
2. 速度快,因为EM这种高效的算法在, 时间复杂度O(tkn)
3. 学术上比较直观,最大数据似然概率
4. 其实可以拓展到多个其他分布的混合,多个多项式分布做类别判定
GMM的劣势:
1. 初始化要慎重, 不然可能掉到局部最优里去
2. 需要手工指定K(高斯分布)的个数
3. 对于我们提到的“非凸” 分布数据集, 也无能为力
一句话总结GMM:根据当前的参数指定概率分布,根据概率分布重新估计参数。
5. 聚类示例
演示了python做文本聚类的例子,主要包括以下内容:
1. 句子的分词和stemming
2. 得到的次做tf-idf编码到向量空间
3. 用余弦举例或欧式距离计算两个文本之间的举例
4. k-means聚类
5. 用multidimensional scaling对结果数据降维(数据可视化)
6. 画出聚类的结果
7. 做层次聚类
8. 画出层次聚类的结果
用到的类库包括:np、pd、BeautifulSoup、feature_extraction等。
NLTK可以做自然语言处理的工作,去掉英语中”a”,”the”等停用词。
stemming:把意义相同的词关联到一起,比如”study”,”studying”等。
……
下面是k-means聚类和层次聚类得到的结果:
完整的代码和数据集在QQ群共享。