天天看点

kmeans原理

一、kmeans概述

K-means聚类算法也称k均值聚类算法,属于无监督学习的一种,k-means聚类无需给定Y变量,只有特征X。

K-means聚类算法是一种迭代求解的聚类分析算法,其步骤是随机选取K个对象作为初始的聚类中心,然后计算每个对象与各个种子聚类中心之间的距离,把每个对象分配给距离它最近的聚类中心。聚类中心以及分配给它们的对象就代表一个聚类。每分配一个样本,聚类的聚类中心会根据聚类中现有的对象被重新计算。这个过程将不断重复直到满足某个终止条件。终止条件可以是没有(或最小数目)对象被重新分配给不同的聚类,没有(或最小数目)聚类中心再发生变化,误差平方和局部最小

在聚类问题中,给我们的训练样本是

kmeans原理

,每个

kmeans原理

,没有了y

具体算法描述如下:

1、 随机选取k个聚类质心点(cluster centroids)为

kmeans原理

2、 重复下面过程直到收敛 {

               对于每一个样例i,计算其应该属于的类

kmeans原理

               对于每一个类j,重新计算该类的质心

kmeans原理

}

K是我们事先给定的聚类数,

kmeans原理

代表样例i与k个类中距离最近的那个类,

kmeans原理

的值是1到k中的一个。质心

kmeans原理

代表我们对属于同一个类的样本中心点的猜测,拿星团模型来解释就是要将所有的星星聚成k个星团,首先随机选取k个宇宙中的点(或者k个星星)作为k个星团的质心,然后第一步对于每一个星星计算其到k个质心中每一个的距离,然后选取距离最近的那个星团作为

kmeans原理

,这样经过第一步每一个星星都有了所属的星团;第二步对于每一个星团,重新计算它的质心

kmeans原理

(对里面所有的星星坐标求平均)。重复迭代第一步和第二步直到质心不变或者变化很小。

K-means面对的第一个问题是如何保证收敛,前面的算法中强调结束条件就是收敛,可以证明的是K-means完全可以保证收敛性。下面我们定性的描述一下收敛性,我们定义畸变函数(distortion function)如下:

kmeans原理

     J函数表示每个样本点到其质心的距离平方和。K-means是要将J调整到最小。假设当前J没有达到最小值,那么首先可以固定每个类的质心

kmeans原理

,调整每个样例的所属的类别

kmeans原理

来让J函数减少,同样,固定

kmeans原理

,调整每个类的质心

kmeans原理

也可以使J减小。这两个过程就是内循环中使J单调递减的过程。当J递减到最小时,

kmeans原理

和c也同时收敛。(在理论上,可以有多组不同的

kmeans原理

和c值能够使得J取得最小值,但这种现象实际上很少见)。

     由于畸变函数J是非凸函数,意味着我们不能保证取得的最小值是全局最小值,也就是说k-means对质心初始位置的选取比较感冒,但一般情况下k-means达到的局部最优已经满足需求。但如果你怕陷入局部最优,那么可以选取不同的初始值跑多遍k-means,然后取其中最小的J对应的

kmeans原理

和c输出

二、kmeans的损失函数

和其他机器学习算法一样,K-Means 也要评估并且最小化聚类代价,在引入 K-Means 的代价函数之前,先引入如下定义:

kmeans原理

 引入代价函数:

kmeans原理

 三、kmeans的优缺点

优点:

1)原理比较简单,实现也是很容易,收敛速度快。

2)聚类效果较优。

3)算法的可解释度比较强。

4)主要需要调参的参数仅仅是簇数k。

缺点:

1)K值的选取不好把握

2)对于不是凸的数据集比较难收敛

3)如果各隐含类别的数据不平衡,比如各隐含类别的数据量严重失衡,或者各隐含类别的方差不同,则聚类效果不佳。

4) 采用迭代方法,得到的结果只是局部最优。

四、kmeans参数

sklearn.cluster.KMeans

class sklearn.cluster.KMeans(n_clusters=8, *, init=\'k-means++\', n_init=10, max_iter=300, tol=0.0001, 
precompute_distances=\'deprecated\', verbose=0, random_state=None, copy_x=True, n_jobs=\'deprecated\', algorithm=\'auto\')      
  • n_clusters:int, default=8,簇的个数,即你想聚成几类
  • init:{\'k-means++\', \'random\', ndarray, callable}, default=’k-means++’,初始簇中心的获取方法,\'k-means ++\':以一种聪明的方式为k-mean聚类选择初始聚类中心,以加快收敛速度​​。有关更多详细信息,请参见k_init中的注释部分。\'random\':n_clusters从初始质心的数据中随机选择观察(行)。如果传递了ndarray,则其形状应为(n_clusters,n_features),并给出初始中心。如果传递了callable,则应使用参数X,n_clusters和随机状态并返回初始化
  • n_init:int, default=10,获取初始簇中心的更迭次数,k均值算法将在不同质心种子下运行的次数
  • max_iter:int, default=300,最大迭代次数(因为kmeans算法的实现需要迭代),单次运行的k均值算法的最大迭代次数
  • tol:float, default=1e-4,容忍度,即kmeans运行准则收敛的条件,关于Frobenius范数的相对容差,该范数表示两个连续迭代的聚类中心的差异,以声明收敛
  • precompute_distances:{\'auto\', True, False}, default=\'auto\',是否需要提前计算距离,这个参数会在空间和时间之间做权衡,如果是True 会把整个距离矩阵都放到内存中,auto 会默认在数据样本大于featurs*samples 的数量大于12e6 的时候False,False 时核心实现的方法是利用Cpython 来实现的
  • verbose:int, default=0,冗长模式(不太懂是啥意思,反正一般不去改默认值)
  • random_state:int, RandomState instance, default=None,确定质心初始化的随机数生成。使用整数使随机性具有确定性
  • copy_x:bool, default=True, 对是否修改数据的一个标记,如果True,即复制了就不会修改数据。bool 在scikit-learn 很多接口中都会有这个参数的,就是是否对输入数据继续copy 操作,以便不修改用户的输入数据。这个要理解Python 的内存机制才会比较清楚
  • n_job:sint, default=None,并行设置
  • algorithm:{\'auto\', \'full\', \'elkan\'}, default=\'auto\',kmeans的实现算法,经典的EM风格算法是\'full\'的。通过使用三角形不等式,\'elkan\'变异对于定义良好的聚类的数据更有效。但是,由于分配了额外的形状数组(n_samples,n_clusters),因此需要更多的内存。目前,\'auto\'(保持向后兼容性)选择\'elkan\',但为了更好的启发式,将来可能会更改

属性

  • cluster_centers_:ndarray(n_clusters, n_features),集群中心的坐标
  • labels_:ndarray(n_samples,),每个点的标签
  • inertia_:float,样本到其最近的聚类中心的平方距离的总和
  • n_iter_:int,运行的迭代次数

方法

  • fit(X[, y, sample_weight]):拟合,计算k均值聚类
  • fit_predict(X[, y, sample_weight]):计算聚类中心并预测每个样本的聚类索引
  • fit_transform(X[, y, sample_weight]):计算聚类并将X转换为聚类距离空间
  • get_params([deep]):获取此估计量的参数
  • predict(X[, sample_weight]):预测X中每个样本所属的最近簇
  • score(X[, y, sample_weight]):与K均值目标上X的值相反
  • set_params(**params):设置此估算器的参数
  • transform(X):将X转换为群集距离空间

也可以看看

MiniBatchKMeans

替代性在线实施,使用微型批次对中心位置进行增量更新。对于大规模学习(例如n_samples> 10k),MiniBatchKMeans可能比默认的批处理实现要快得多。

sklearn.cluster

.k_means

sklearn.cluster.k_means(X, n_clusters, *, sample_weight=None, init=\'k-means++\', precompute_distances=\'deprecated\', n_init=10,
 max_iter=300, verbose=False, tol=0.0001, random_state=None, copy_x=True, n_jobs=\'deprecated\', algorithm=\'auto\', return_n_iter=False)      
  • X:{array-like, sparse} matrix of shape (n_samples, n_features),数组,矩阵,稀疏矩阵
  • n_clusters:int
  • sample_weight:array-like of shape (n_samples,), default=None,X中每个观测值的权重。如果为None,则为所有观测值分配相等的权重
  • init:{\'k-means++\', \'random\', ndarray, callable}, default=\'k-means++\'
  • precompute_distances:{\'auto\', True, False}
  • n_init:int, default=10
  • max_iter:int, default=300
  • verbose:bool, default=False
  • tol:float, default=1e-4
  • random_state:int, RandomState instance, default=None
  • copy_x:bool, default=True
  • n_jobs:int, default=None
  • algorithm:{\'auto\', \'full\', \'elkan\'}, default=\'auto\'
  • return_n_iter:bool, default=False

属性

  • centroid
  • label
  • inertia
  • best_n_iter

k_means这个是先写的,他们两的参数就相差一个数据集,不过还是建议用KMeans

五、kmeans可视化

使用iris数据做简单的聚类,并且画出聚类后的图片

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.datasets import load_iris
from sklearn.cluster import KMeans

X=load_iris().data
kmeans = KMeans(n_clusters=3,random_state=0)
kmeans.fit(X)

labels = kmeans.labels_
labels = pd.DataFrame(labels,columns=[\'labels\'])
X=pd.DataFrame(X)
X.insert(4,\'labels\',labels)

from sklearn.manifold import TSNE
tsne = TSNE()
a = tsne.fit_transform(X)
liris = pd.DataFrame(a,index=X.index)

d1 = liris[X[\'labels\']==0]
#plt.plot(d1[0],d1[1],\'r.\')
d2 = liris[X[\'labels\']==1]
#plt.plot(d2[0],d2[1],\'go\')
d3 = liris[X[\'labels\']==2]
#plt.plot(d3[0],d3[1],\'b*\')
plt.plot(d1[0],d1[1],\'r.\',d2[0],d2[1],\'go\',d3[0],d3[1],\'b*\')      
kmeans原理

 值得注意的是,上面的可视化是将特征缩成一个值,然后在和label画图

还有其他的可视化方法

# 导入可视化工具包
import matplotlib.pyplot as plt
%matplotlib inline
from sklearn.datasets import load_iris
from sklearn.cluster import KMeans
import numpy as np
import pandas as pd

X=load_iris().data
clf = KMeans(n_clusters=3,random_state=0)
clf.fit(X)
label = clf.predict(X)

# 颜色和标签列表
colors_list = [\'red\', \'blue\', \'green\']
labels_list = [\'1\',\'2\',\'3\']
x=X
for i in range(3):
    plt.scatter(x[label==i,0], x[label== i,1], s=100,c=colors_list[i],label=labels_list[i])
    
# 聚类中心点
plt.scatter(clf.cluster_centers_[:,0],clf.cluster_centers_[:,1], s=300,c=\'black\',label=\'Centroids\')

plt.legend()
plt.xlabel(\'Annual Income (k$)\')
plt.ylabel(\'Spending Score (1-100)\')
plt.show()      
kmeans原理

 六、获取kmeans特征权重,特征贡献度

有时候我们需要看一下,哪个特征对kmeans贡献最大,但是如果是使用pca之后的数据做模型,那么就有点难计算,但是pca也是根据变量方差去选择,也即是说第一主成分的选择是根据最大方差去选择,了解这个或许还可以计算出来,

但是我们主要说非pca之后的:

#验证过,该属性确实可以计算出来
estimator=KMeans()
estimator.fit(X)
res=estimator.__dict__
print res[\'cluster_centers_\']      
kmeans原理