列表

详情


2. 知道kmeans吧?说下迭代过程,簇心随机不好,怎么才能更稳定?

回答思路

k-means算法,也被称为k-均值算法,是最基本也是应用最广泛的聚类算法。该算法的核心思想是将各个聚类子集内的所有数据样本的均值作为该聚类的代表点。

即在迭代过程中把数据集划分为不同的类别,使得评价聚类性能的距离函数达到最优,从而使生成的每个聚类内紧凑,类间远离。

迭代过程

输入:簇的数目k和包含n个对象的数据库。

输出:k个簇,使平方误差准则最小。

算法步骤:

为每个聚类确定一个初始聚类中心,这样就有K个初始聚类中心。

将样本集中的样本按照最小距离原则分配到最邻近聚类

使用每个聚类中的样本均值作为新的聚类中心。

重复步骤2.3直到聚类中心不再变化。

结束,得到K个聚类

伪代码

input:获取数据n个m维的数据input:随机生成K个m维的点while(t) // t表示设置的终止条件,比如迭代次数   for(int i=0;i < n;i++) //遍历每个元素     for(int j=0;j < k;j++) //为每个元素计算其到K个聚类中心的距离       计算点i到类j的距离   for(int i=0;i < k;i++) //更新聚类中心点     1.找出所有属于自己这一类的所有数据点//通过选定的距离度量函数确定     2.把自己的坐标修改为这些数据点的中心点坐标end output: K个m维的点(聚成了K类)

复杂度分析

1、时间复杂度

O(tnkm),其中,t为迭代次数,k为簇的数目,n为样本点数,m为样本点维度。

2、空间复杂度

O(m(n+k)),其中,k为簇的数目,m为样本点维度,n为样本点数。

k-means迭代过程可视化

https://hckr.pl/k-means-visualization/

对kmeans算法不熟悉的同学可以从该网站里面,直观地了解kmeans迭代的每个过程

 

簇心随机不好,怎么才能更稳定

K-Means算法试图找到使平方误差准则函数最小的簇,当潜在的簇形状是凸面的,簇与簇之间区别较明显,且簇大小相近时,其聚类结果较理想,但对于其他场景效果则不一定很好。

而且该算法除了要事先确定簇数K和对初始聚类中心敏感外,经常以局部最优结束,同时对“噪声”和孤立点敏感,并且该方法不适于发现非凸面形状的簇或大小差别很大的簇。

举个例子,典型的月牙形数据

from sklearn.datasets import make_moons X, y = make_moons(200, noise=.05, random_state=0) labels = KMeans(2, random_state=0).fit_predict(X) plt.scatter(X[:, 0], X[:, 1], c=labels, s=50, cmap='viridis')

解决这种场景的思路可以借鉴支持向量机的核函数(使用核函数转换来将数据投影成到更高维度),在聚类中,可以考虑谱聚类,即Spectral clustering。

from sklearn.cluster import SpectralClustering model = SpectralClustering(n_clusters=2, affinity='nearest_neighbors', assign_labels='kmeans') labels = model.fit_predict(X) plt.scatter(X[:, 0], X[:, 1], c=labels, s=50, cmap='viridis')

 

总结来说,主要有三种方法,解决簇心随机不好的问题,使聚类更稳定

 

多次运行,每次使用一组不同的随机初始质心,然后选取具有最小SSE(误差的平方和)的簇集。这种策略简单,但是效果可能不好(本质还是随机选取)。

取一个样本,并使用谱聚类或者层次聚类技术对它聚类。比如从层次聚类中提取K个簇,并用这些簇的质心作为初始质心。

取所有点的质心作为第一个点,然后,对于每个后继初始质心,选择离已经选取过的初始质心最远的点。使用这种方法,确保了选择的初始质心不仅是随机的,而且是散开的。但是,这种方法可能选中离群点。(典型的改进是kmeans++)


上一题