一、面试高危问题:如何衡量聚类算法的效果?
聚类模型的结果不是某种标签输出,聚类结果也不确定,表明其优劣是由业务需求或算法需求决定的,没有永远的正确答案。 如何衡量聚类的效果呢?
我记得KMeans的目标是确保“集群内的差异小,集群外的差异大”,可以通过测量集群内的差异来测量集群的效果。 另一方面,Inertia是用距离测量集群内差异的指标,所以可以将Inertia用作集群的测量指标吗? Inertia越小型号越好。 虽然也可以回答,但是集群内误差平方和Inertia这个指标的缺点和局限性太大了。
二、关于簇内误差平方和Inertia的讨论
主要有以下情况。
)1)非有界。 我们只知道Inertia越小越好,0是最好的,但不知道小Inertia是达到了模型的极限,还是会继续提高。
)2)其计算易受特征数的影响,当数据维数较大时,Inertia计算量陷入维数诅咒,计算量爆炸,不适于一次性评估模型。
)3)它受超参数k的影响。 在以往的尝试中,我们发现实际上随着k的增大,Inertia注定会变小,但这并不意味着模型的效果变好了。
(4) Inertia作为评价指标,在某些细长聚类、环状聚类或不规则形状流形的情况下,聚类算法不起作用
聚类是一种无标签、不知道真实答案的预测算法,必须完全依赖于评价聚类内的密集度(聚类内的差异小)和聚类间的离散度(聚类外的差异大)来评价聚类的效果其中轮廓系数是最常用的聚类算法的评价指标。 每个样本都有定义,可以同时测量。
(1)样本与其所在集群中的其他样本之间的相似度等于样本与同一集群中所有其他点之间的平均距离,且此距离被设置为a。
)样本和另一集群中的样本之间的相似度等于样本和下一最近集群中的所有点之间的平均距离,其中b表示该距离。
二.轮廓系数的计算
根据聚类要求,“集群内差异小,集群外差异大”,我们希望b永远大于a,且越大越好。 单个样本的轮廓系数计算如下:
可以按如下方式分析此表达式:
很容易看出轮廓系数范围为(-1,1 ) :
)1)轮廓系数越接近1,此时a越接近0,样本与自己所在集群中的样本非常相似,且与其他集群中的样本不相似。
)2)轮廓系数为0时:在这种情况下,a=b,两个集群中的样本相似度一致,两个集群本来应该是一个集群。
)3)轮廓系数为负时)采样点与聚类外的采样非常相似。
当一个集群中的大多数样本具有相对较高的轮廓系数时,集群的总轮廓系数较高,并且整个数据集合的平均轮廓系数越高,集群就越合适。
如果许多样本点具有低轮廓因子或负值,则聚类不合适,并且聚类的超级参数k可能太大或太小。
一.轮廓系数的代码实现
sklearn使用模块metrics中的silhouette_score类计算轮廓系数。 这返回数据集中所有样本的轮廓系数的平均值。 但是,也有metrics模块中的silhouette_sample。 该参数与轮廓系数匹配,但返回数据集中每个样本的唯一轮廓系数。轮廓系数在我们自建的数据集:
)1)部署所需的模块、库
importnumpyasnpimportpandasaspdimportmatplotlib.pyplotaspltfromsklearn.datasetsimportmake _ blobsfromsklearn.cluster imppltearn corefromsklearn.metricsimportsilhouette _ samples PLT.style.use (gg plot ‘ (2) ) ) ) ) ) ) ) )。
生成500*2的数据集。 每个数据集有四个中心点。 这意味着数据集有四个标签x,y=make_blobs(n_samples=500,n_features=2,centers=4,Random_staabs )
(3)轮廓系数计算
cluster=kmeans(n_clusters=3,random_state=0).fit(x ) silhouette_score(x,cluster_.labels_ ) 计算silhouette_samples(x,cluster.labels_ ) #每个样本的轮廓系数。 输出如下。
0.5150064498560357
Array(0.62982017、0.5034877、0.56148795、0.84881844、0.56034142、0.78740319、0.39254042、0.4424015、0.48582704…])。
)4) k引起的轮廓系数变化图
sco
re=[]for i in range(2,100): cluster= KMeans(n_clusters=i, random_state=0).fit(X) score.append(silhouette_score(X,cluster.labels_)) plt.plot(range(2,100),score)plt.axvline(pd.DataFrame(score).idxmin()[0]+2,ls=’:’) # x轴的取值起点是2,所以id+2
轮廓系数有很多优点:
(1) 它在有限空间中取值,使得我们对模型的聚类效果有一个“参考”。
(2) 它对数据的分布没有假设,因此在很多数据集上都表现良好。但它在每个簇的分割比较清洗时表现最好。
初始质心选择问题
在 K-Means 中有一个重要的环节,就是放置初始质心。如果有足够的时间, Kmeans 一定会收敛,但inertia(簇内误差平方和)可能收敛到局部最小值。是否能够收敛到真正的最小值很大程度上取决于质心的初始化。 init 就是用来帮助我们决定初始化方式的参数。
初始质心放置的位置不同,聚类的结果很可能也会不一样,一个好的质心选择可以让 K-Means 避免更多的计算,让算法收敛稳定且更快。为了优化选择初始质心的方法, 2007年Arthur, David, and Sergei Vassilvitskii三人发表了论文“kmeans++:The advantages of careful seeding”,他们开发了 ”k-means ++“初始化方案,使得初始质心(通常)彼此远离,以此来引导出比随机初始化更可靠的结果。
质心初始化参数init的说明
可输入”k-means++”, “random”或者一个 n 维数组
(1)初始化质心的方法,默认”k-means++”
(2)输入”k-means++”:一种为 K 均值聚类选择初始聚类中心的聪明的办法,以加速收敛。
(3)输入”random” 表示随机从训练数据中选取初始质心。
(4)如果输入了 n 维数组,数组的形状应该是(n_clusters, n_features)并给出初始质心
一分快三技巧8795、0.84881844、0.56034142、0.78740319、0.39254042、0.4424015、0.48582704…])。
)4) k引起的轮廓系数变化图
sco
re=[]for i in range(2,100): cluster= KMeans(n_clusters=i, random_state=0).fit(X) score.append(silhouette_score(X,cluster.labels_)) plt.plot(range(2,100),score)plt.axvline(pd.DataFrame(score).idxmin()[0]+2,ls=’:’) # x轴的取值起点是2,所以id+2
轮廓系数有很多优点:
(1) 它在有限空间中取值,使得我们对模型的聚类效果有一个“参考”。
(2) 它对数据的分布没有假设,因此在很多数据集上都表现良好。但它在每个簇的分割比较清洗时表现最好。
初始质心选择问题
在 K-Means 中有一个重要的环节,就是放置初始质心。如果有足够的时间, Kmeans 一定会收敛,但inertia(簇内误差平方和)可能收敛到局部最小值。是否能够收敛到真正的最小值很大程度上取决于质心的初始化。 init 就是用来帮助我们决定初始化方式的参数。
初始质心放置的位置不同,聚类的结果很可能也会不一样,一个好的质心选择可以让 K-Means 避免更多的计算,让算法收敛稳定且更快。为了优化选择初始质心的方法, 2007年Arthur, David, and Sergei Vassilvitskii三人发表了论文“kmeans++:The advantages of careful seeding”,他们开发了 ”k-means ++“初始化方案,使得初始质心(通常)彼此远离,以此来引导出比随机初始化更可靠的结果。
质心初始化参数init的说明
可输入”k-means++”, “random”或者一个 n 维数组
(1)初始化质心的方法,默认”k-means++”
(2)输入”k-means++”:一种为 K 均值聚类选择初始聚类中心的聪明的办法,以加速收敛。
(3)输入”random” 表示随机从训练数据中选取初始质心。
(4)如果输入了 n 维数组,数组的形状应该是(n_clusters, n_features)并给出初始质心