kmeans聚类算法_聚类算法之Kmeans

本篇大纲:

1、背景知识:一些常见的距离度量/相似度计算方式

2、聚类算法之Kmeans

3、kmeans优缺点及其改进

4、kmeans的简单代码实现


上上期回顾

1、我们先做了基本铺垫,对于最值求解问题进行三种类别划分,包括无约束问题,等式约束问题和不等式约束问题,并简单阐述对应的求解方式。

2、我们从感知器出发,简单阐述其二分类原理,从而明白SVM是从何算法改进而来。

3、我们从svm的两个核心目标出发,推出其目标函数和约束条件,根据函数距离和几何距离相等的约束来简化计算过程,从而得到精简版的目标函数和约束条件。通过对约束条件的变形,我们基本转成不等式约束的基本形式,从而进行KKT条件的转换,通过导数求解,我们解出w的值以及另一个等式约束条件,进一步的,我们通过smo求解方式对函数进行进一步求解,得到最终的w和b的值,也就获得了函数超平面的方程。通过对函数超平面方程进行符号化的封装,从而达到通过给定空间样本坐标,得到目标分类结果的效果。

4、我们浅尝辄止地谈了一下解决低维空间数据映射到高维空间高计算量问题的核函数,以及用于增强超平面泛化能力的软间隔,并简单分析了一下松弛因子和惩罚系数的关系。

5、我们言简意赅地提了一下SVM的特点及其应用场景,并给出了svm在sklearn中相关的算法及参数的说明。


没事唠两句

在传统机器学习领域里,主要涉及的任务有回归、分类、聚类、推荐等。

回归由于其精确度问题,并没有被广泛大量地商业化应用,多是用于一些分析工作,或是作为一个简单的参考数据以及辅助数据而存在。

分类是一大主流方向,也是商业化覆盖最大的一个方向,包括后面深度学习领域的一些主攻方向,个人理解也是在分类基础上做了进一步其它工作。

聚类多用于前期数据分析的辅助,零散错乱的数据,无论是对于标注还是对于分析,相比整齐规划的数据而言,其时间开销和精度提升的代价多是会相对大一些,而整齐有致的数据,则多会让工作变得更加条理高效一些。

推荐算法领域颇广,常见的如电商平台的物品推荐,音乐视频的兴趣推荐,阅读平台的兴趣文章推荐等等,是另一个商业化覆盖较大的方向领域。但是就目前市场来看,推荐算法的整体效果还未完全成熟,虽百家齐放,但效果上仍参差不齐。


背景知识

啥是聚类:

简单来说,就是物以类聚,人以群分。

换一句话说,就是将相似的归为一类,不相似的则不为一类。

那么问题就来了,什么才是相似,相似的度量方式是什么?

难道标签一致还不能作为相似的标准吗?还需要其他的方式来进一步度量是否相似吗?

首先,标签是结果,是参考答案。所以自然可以理解为标签一致的即属于相似的一类,标签不一致的则不属于相似的一类。

但是并不是所有数据上来就有答案的,或者并不是所有数据都是带标签的。

那么聚类问题实际上就是属于无监督(无标签)学习,自然需要其它的方式来进行判断是否相似。

一般来说,我们会以距离或者相似度来作为相似的度量方式。

常见的距离度量方式

先给出米可夫斯基距离

23b23590619b7c512488730c74c57d0c.png

那么,当p等于1时,也就是曼哈顿距离

991e80130b95feab5c870c7d6d5f4bee.png

当p等于2时,则是欧几里得距离,也就是欧氏距离

366b726a3e603775d4d3059461809cf3.png

当p等于无穷时,则是切比雪夫距离

fa545ae46585873abc1575128c21fac8.png

在这里,我们最常见的是曼哈顿距离和欧式距离。

曼哈顿距离最初是源于曼哈顿城市的出租车距离计算,对于我们来说,这个背景可有可无,就不展开讲了。或许,我们更应该关心的是,什么时候用曼哈顿距离,什么时候用欧式距离,以及使用两者对应的优缺点是什么?

对于这个问题,实际上,我们可以参考L1正则和L2正则的优缺点,因为L1正则实际上就是使用的曼哈顿距离公式,而L2正则实际上就是使用的欧式距离公式,具体优缺点,我们可以回顾这里:回归算法之线性回归(二)

常见的相似度计算方式

杰卡德系数

45a46fe6e1d35509bced887bcdcc2cdb.png

杰卡德系数多用于文本相似的计算,比如A文本共100个词,B文本也是100个词,两个文本交集为50个词,两个文本并集为150个词,那么两者对应的杰卡德系数即可三分之一,两者的距离则为三分之二,距离越大,自然也就越不相似。但从其计算方式上我们可以大概知道,杰卡德系数用于文本分类,其粒度较粗,更多是从词的组成上来判断是否相似的,而不会去考虑语义。

余弦相似度

8a334ca605fc9e4fb917da512bbae778.png

从数学的角度来讲,向量是空间中带有方向的线段,而余弦的求解过程也可以理解为一个向量在另一个向量方向上的投影,故而当两个向量的方向一致时,其余弦值则会为1。如果运用到文本相似度计算上,比如我们使用文章各词语的词频所构成的向量,作为该文章的向量化表示,那么计算两个向量的余弦值,就可以作为两文章的相似程度判断,这里我们使用余弦相似度来作为相似度判断标准,更多的,是考虑文章的描述方向,对于其文章的长度,我们考虑则会相对少一些。

实际应用中,对于数据而言,如果会有一些预处理操作,那么就会使得后面更加高效快捷。对于求余弦相似度而言,我们可能会先对数据进行归一化操作,所谓归一化,也就是让向量的模长变为1,因为是同时对所有数据进行相同操作,故而对于结果而言,该变化不会产生多少影响,另外,归一化操作同标准化、区间放缩法一样,都具备去量纲的效果,故而多数情况下,我们在求余弦相似度之前,会加上一步归一化操作,从而简化余弦相似度的计算。

皮尔逊系数

700f9b6a395dc0bae614ae0204dd9a2b.png

相关系数的取值是从-1到1,当相关系数的值小于0时,则代表X和Y之间负相关,当相关系数的值大于0时,则代表X和Y之间正相关,一般而言,当相关系数的绝对值大于0.8时,我们认为是极相关,当然,也可以个人要求更严格一些,比如认为大于0.85我们才去认为极相关,也是无可厚非的。特殊的,通过公式我们可以看出,当X=Y时,分子等于分母(因为DX=E(X^2)-(EX)^2),此时相关系数为1,也就是两者完全相同,也就是完全可以被彼此代替。

那么皮尔逊系数和余弦相似度两者之间又有什么联系呢?有什么讲究什么时候选择哪种方式呢?

先看看余弦相似度和皮尔逊系数的另一种表达方式:

8c0190d2cd2353b5691b58353074c489.png

所以,实际上,皮尔逊系数是去中心化的余弦相似度。

那什么场景下会更适合皮尔逊系数呢,举个例子,比如说有用户甲,对电影A、电影B、电影C都有一个自己的打分,用户乙,同样对电影A、电影B、电影C有一个自己的打分,现在要看用户对各个电影的评价是否是相似的,直白的,我们可以通过对分数的对比来获得结果,但是因为不同用户都有自己的评价标准,A用户比较严格,认为是好的,也就给打7分,而B用户则比较感性化,认为是好的,则打9分。故而这里我们需要做一个去用户标准化操作,故而选择使用皮尔逊相关系数会比较合适。

再举个例子,比如我们有若干特征变量,我们想要判断一下不同特征变量之间是否具有相关性较强的特征变量,这个时候,因为不同的特征变量都有自己的一个隐藏标准,在各自的标准下,其数值自然也就不同,故而此时,我们要想判断变量之间是否相关,则需要做一个变量的去中心化操作,从而消去特征变量自身的隐藏标准,也就更加准确。

互信息:

b97f2ac49a6fb24ccf37aedbc171acdd.png

互信息的相关介绍以及其对应的应用场景,有兴趣的可以再去看看决策树这篇内容,这里就不再赘述。

那么到这里,我们对于一些基本的相似读计算方式也就算有个大概的了解了。


聚类算法之Kmeans

聚类算法其实有很多,包括层次聚类,密度聚类,谱聚类等等。

但是为何这篇只提Kmeans,是因为Kmeans是算法理解简单,而又使用最多,并且从原理上来说,其它的聚类算法只是其算法或求解思路有些差别,但是其核心思路还是一致,具体做的事也是有着同一个目标,故而这篇我们重点详细单独阐述Kmeans算法。对于其它聚类算法,如果必要,我们在下一篇再进行展开。

基本上来说,聚类算法的核心都是先获得簇心,然后根据簇心划分簇,再按照一定的标准或方法更新簇心,根据更新后的簇心重新划分簇,不断迭代至满足一定条件。当然,这只是大部分情况下,也并不是绝对的,比如密度聚类,则并不是按上述流程走的,这个我们后面再叙。

所以,大部分情况下,不同的聚类算法,其主要的差别有这么几点:第一,其簇心选择方式可能不同。第二,根据簇心划分簇的方式可能不一样。第三,其更新簇心的方式可能不同。

Kmeans算法,也叫k均值算法,顾名思义,其核心思想也就是根据均值来更新簇心。

其具体算法流程如下:

1、随机初始化k个簇心

2、对于每个样本,根据其到各簇心的距离(这里用欧式距离),将其标注为距离最近的簇心类别。

3、更新每个簇的簇心,计算方式即求均值

4、重复上述2、3两个步骤,直到能达到某个终止条件。

一般终止条件有:

1、迭代次数:即自己设定一定的迭代次数。

2、最小平方误差MSE:即上轮簇心和当前计算均值所得结果的mse

3、簇中心的变化率:即更新一轮,簇心发生变化的总比例值。

或许有人会问,是否可以对这个算法进行改进,比如单纯地换一种距离度量方式,如使用曼哈顿距离,或者单纯地换一种簇心计算方法,如使用中位数等。

然而,这里欧氏距离计算方式和求均值更新簇心实际上是绑定的,严格来说,正是由于欧氏距离求解方式的确定,进而导致了更新簇心时是求均值的方式。

可以这么理解

假定我们记k个簇心分别为a1,a2,。。。ak,每个簇的样本数量为N1,N2,。。。Nk。

我们使用平方误差(欧氏距离)作为目标函数,即

5021cb0a30214b2f5779a8388d3a463b.png

那么要想获得最优解,,也就是目标函数要尽可能小,也就是,求偏导,让其等0。这里的求偏导是对第j个簇心aj求的偏导。故而:

495e19d68b335cfda5cd3ca1e3c4c95e.png

故而我们也就明白了,这里的簇心更新的方式,实际上是由距离度量方式所决定的。


kmeans优缺点及其改进

整体上看,Kmeans算法原理简单,操作可行性高。

但不可避免的,kmeans算法有以下一些缺点:

1、簇心初值敏感,不同的初值其划分的结果可能不一样

举例来说:假定我们的数据是人为的创造上下左右四个圆,然后分别在四个圆里随意画上若干个点。那么理论上我们知道,我们期望是能分出上下左右四个簇。

实际上,如果我们初始化四个簇心,而这四个簇心恰好分别处于四个圆里,那么根据kmeans的处理流程,我们大概率能够获得我们期望的四个簇,即分别属于上下左右四个圆里(这里的圆只是我们自己的辅助说法,并非在数据中真实存在,数据均为空间中点的坐标)。

如果我们初始化的四个簇心,有两个或两个以上簇心,是在同一个圆里,那么,根据kmeans的流程,最后的结果,很可能是和我们的预期完全不一致。也就是我们说的初值敏感。

2、异常点存在会导致偏差严重

举例来说:为简化运算,我们以一维数据为例,假定我们某个簇共有五个点,这五个点对应的值分别为2,4,6,8,100。不论该簇的初始簇心是几,这轮更新簇心时,根据kmeans算法,我们求平均,则是120/5=24。看起来这个数似乎并不合理,有点员工和老板的平均薪资来计算整体平均收入的代入感。。。这也就是我们说的异常点的存在,会导致偏差叫严重。

3、更新簇心求均值,迭代效率慢

回到kmeans算法流程上,我们每次更新簇心,是计算本簇中所有样本点的均值来作为新的簇心,这也就意味着,对于本簇中的所有非簇心样本,簇心都要与其进行一次距离计算,这还只是一轮,要知道,我们的数据量往往并不是几十几百或者几千。。。这个计算代价,就显得非常庞大了。

相应的,对于这些缺点,也就有了相应的改进措施

一、对于簇心初值敏感问题

1、二分kmeans算法:其核心在于二分法。

具体流程:先以所有样本为一个簇,然后进行kmeans划分,将一个簇一分为二划分为两个簇。然后,再选择一个簇进行kmeans算法划分,再次将该簇一分为二,划分为两个簇。循环以上操作,直至达到终止条件(这里终止条件可以是簇的数量或者是迭代次数)。

而这里最重要的选簇依据一般有两种:一种是簇中样本数最多的。另一种即对所有簇进行SSE(即簇中所有非簇心点到簇心点的距离平方和相加所得)计算,选择SSE最大的簇进行划分。

2、k-means++算法:其核心也是簇心数目从小到大不断累加上去。

具体流程:先从所有数据集中随机选取一个节点作为第一个簇心,然后计算其他所有点到该簇心的距离(当有多个簇心时,则为计算所有点到所有簇心的距离和),根据距离,按照概率选出下一个簇心,这里的概率和距离成正比,即距离越大,概率越大。比如a、b、c三点距离簇心距离和分别为3、2、1,则选择a点的概率为3/(3+2+1)=1/2。重复迭代至找到k个簇心。多补充一句,sklearn中kmeans的簇心初始化方法,一般也默认选择k-means++。当然,这个是可选可配的。

由于k-means++计算的是所有的样本点到簇心的距离和,其计算量庞大,故而又有了kmeansII算法

其具体流程为:先从所有数据集中任选一个节点作为第一个簇心,然后重复logn次,每次随机选择k个样本点,计算k个节点到它的距离(当有多个簇心时,则为计算所有点到所有簇心的距离和),根据距离按概率选出下一个簇心,依然是距离越大,概率越大。重复迭代至找到k个簇心。

那么以上三种算法都是对于kmeans算法初值敏感问题的改进,进一步说,主要解决的是kmeans初始化k个簇心的问题。而对于kmeans其它的步骤,并不会产生影响,依然还是按原有流程继续往下走。

二、对于异常点导致偏差大的问题

这里主要是使用的k中值法来解决,也就是说,不再使用均值法来更新簇心,而均值法是由欧式距离最小化得来的。故而k中值法即并非用欧氏距离来度量样本之间的距离,k中值用的是曼哈顿距离,相应的,其簇心更新为中位数更新,也就是选取所有样本的中位数点对应的样本作为新一轮的簇心。这里的推导和欧氏距离推均值一个思路,有兴趣的可以自己推一推。

三、对于更新簇心求均值,计算慢的问题

这里则主要使用miniBatch Kmeans算法来解决,其具体思路为:将所有数据集看成一个篮子,先从篮子里抽取部分数据集,然后根据kmeans算法构建出k个簇心的模型,然后再从篮子中继续抽取部分数据,继续添加到现有模型中,分配给距离最近的簇心点,再更新簇心,然后继续从篮子中取数据,添加至模型,迭代至簇心稳定或达到一定迭代次数。

整体而言,miniBatch kmeans是kmeans的一种简易版本,计算量少,迭代快,效果上也只是略差于kmeans。但其整体速度相比而言,是毋庸置疑的,当然,这里的前提是数据量比较大的情况下。

那么到这里,kmeans算法的缺点以及其相应的改进算法也就基本明确了。



场景分析

首先,开头我们便提到,kmeans算法由于其原理简单,应用广泛,故而先提。实际上,它确实是属于用得相对最多的一个。

虽然对于不同的数据类型而言,不同的聚类算法其聚类效果不一样,比如环形,月牙形等,kmeans的效果并不是很理想,但是现实业务中,大多数情况下,我们要进行聚类的数据多属于服从高斯分布的数据,而对于这类分布的数据而言,使用kmeans算法还是使用其他的聚类算法,如谱聚类,层次聚类等等,效果上并没有太大差别,加上kmeans在聚类算法中往往先入为主,也只是辅助作用,效果也不差,故而一般情况下而言,还是会优先考虑选择使用kmeans算法。

当然,特殊场景,还是需要特殊考虑,尤其是在需要严格要求精度的情况下。


kmeans算法的代码实现

以下是个人实现的kmeans代码,可简单参考一下。

d41d6a39e4d92808a86452fdd6930c25.png

54e66a68573fa75032c98c85eb539c92.png

d90a150708a37f661188398881c5300b.png

57bce0eb9a52731449ed30968ba92550.png

1d999a69b7af738568fec109eb6a58e7.png

b310d0ff81c92cbb421883d89893c7ba.png

从两图中可以看出,左边是原始给定数据样本点,右边是聚好类别后的四个簇,整体上看,效果还可以。


排版不佳,还请见谅。

快乐需要传递,知识需要分享。

如果感觉还不错,请帮忙分享推广。


更多文章请关注

81d072fa9c4adbed3cca6fa3fd274605.png

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值