K-Means聚类算法
1.算法简介
作为无监督聚类算法中的代表——K均值聚类(Kmeans)算法,该算法的主要作用是将相似的样本自动归到一个类别中。所谓的监督算法,就是输入样本没有对应的输出或标签。聚类(clustering)试图将数据集中的样本划分为若干个通常是不相交的子集,每个子集称为一个“簇(cluster)”,聚类既能作为一个单独过程,用于找寻数据内在的分布结构,也可作为分类等其他学习任务的前去过程。——《Machine Learning》
K均值是聚类算法中最为简单、高效的。其核心思想是:由用户指定K个初始质心,以作为聚类的类别(cluster),重复迭代直至算法收敛。下图可以形象的描述K-Means聚类过程,

2.基本算法流程:
1.选取K个初始质心(作为初始cluster)
K的选取:先验知识、SSE(组内差)、轮廓系数
质心的选取:随机选择、层次聚类、Kmeans++、基于最近邻密度
2.迭代: (距离计算方式是 欧式距离)
对每个样本点,计算得到距其最近的质心,将其类别标为该质心所对应的cluster;
重新计算K个cluser对应的质心
3.直到到达迭代上限或质心不再变化
3.代码实现:
import numpy as np import matplotlib.pyplot as plt # 从sklearn中直接生成聚类数据 from sklearn.datasets import make_blobs #数据加载 x, y = make_blobs( n_samples=100, centers=6, random_state=1234, cluster_std=0.6 ) #可视化显示数据 plt.figure(figsize=(6,6)) plt.scatter(x[:,0], x[:,1], c=y) plt.show() # 引入scipy中的距离函数,默认欧式距离 from scipy.spatial.distance import cdist class K_Means(object): # 初始化,参数 n_clusters(K)、迭代次数max_iter、初始质心 centroids def __init__(self, n_clusters=6, max_iter=300, centroids=[]): self.n_clusters = n_clusters self.max_iter = max_iter self.centroids = np.array( centroids, dtype=np.float ) # 训练模型方法,k-means聚类过程,传入原始数据 def fit(self, data): # 假如没有指定初始质心,就随机选取data中的点作为初始质心 if( self.centroids.shape == (0,) ): # 从data中随机生成0到data行数的6个整数,作为索引值 self.centroids = data[ np.random.randint( 0, data.shape[0], self.n_clusters ) ,: ] # 开始迭代 for i in range(self.max_iter): # 1. 计算距离矩阵,得到的是一个100*6的矩阵 distances = cdist(data, self.centroids) # 2. 对距离按有近到远排序,选取最近的质心点的类别,作为当前点的分类 c_ind = np.argmin( distances, axis=1 ) # 3. 对每一类数据进行均值计算,更新质心点坐标 for i in range(self.n_clusters): # 排除掉没有出现在c_ind里的类别 if i in c_ind: # 选出所有类别是i的点,取data里面坐标的均值,更新第i个质心 self.centroids[i] = np.mean( data[c_ind==i], axis=0 ) # 实现预测方法 def predict(self, samples): # 跟上面一样,先计算距离矩阵,然后选取距离最近的那个质心的类别 distances = cdist(samples, self.centroids) c_ind = np.argmin( distances, axis=1 ) return c_ind #测试 def plotKMeans(x, y, centroids, subplot): plt.subplot(subplot) plt.scatter(x[:,0], x[:,1],c=y) plt.scatter(centroids[:,0],centroids[:,1],s=100,c='r') kmeans = K_Means(n_clusters=5, max_iter=300) plt.figure(figsize=(16,6)) plotKMeans(x, y, kmeans.centroids, 121) # 开始聚类 kmeans.fit(x) print(kmeans.centroids) plotKMeans(x, y, kmeans.centroids, 122) # 做出预测 x_new = np.array([[10,7],[0,0]]) y_pred = kmeans.predict(x_new) print(y_pred) plt.scatter(x_new[:,0],x_new[:,1],s=100,c="black")
4.kMeans的局限性
1、聚类中心的个数K 需要事先给定,但在实际中这个 K 值的选定是非常难以估计的,很多时候,事先并不知道给定的数据集应该分成多少个类别才最合适;
2、Kmeans需要人为地确定初始聚类中心,不同的初始聚类中心可能导致完全不同的聚类结果。(可以使用K-means++算法来解决);
3、结果不一定是全局最优,只能保证局部最优;
4、对噪声和离群点敏感;
5、该方法不适于发现非凸面形状的簇或大小差别很大的簇;
6、需样本存在均值(限定数据种类)。
Kmeans++算法
k-means++算法选择初始seeds的基本思想就是:初始的聚类中心之间的相互距离要尽可能的远。wiki上对该算法的描述是如下:
- 从输入的数据点集合中随机选择一个点作为第一个聚类中心;
- 对于数据集中的每一个点x,计算它与最近聚类中心(指已选择的聚类中心)的距离D(x);
- 选择一个新的数据点作为新的聚类中心,选择的原则是:D(x)较大的点,被选取作为聚类中心的概率较大;
- 重复2和3直到k个聚类中心被选出来;
- 利用这k个初始的聚类中心来运行标准的k-means算法。
5.sklearn中实现的K-means算法:
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是“K”的值,表示了要生成簇的个数默认为8个。Init参数表示了选择的初始化方法,可选的参数有‘k-means++’和‘random’(k-means++可解决K-means算法中对异常值和初值敏感的问题)。n_init表示k-means算法使用不同的质心种子运行的次数其默认值为10。Max_iter表示最大的迭代次数,其默认值为300. tol表示收敛的范围其默认值为0.0001。
参考链接:K-Means(K均值聚类算法) - 知乎 (zhihu.com)
https://www.jianshu.com/p/4f8c097e26a8
https://www.cnblogs.com/pinard/p/6164214.html

浙公网安备 33010602011771号