K-means clustering k均值聚类算法(k-means clustering algorithm)是一种迭代求解的聚类分析算法,在这一章里,你将使用有效的数据集对k-means聚类算法进行分析,并了解到数据挖掘中的若干重要概念。
背景介绍 k均值算法群集中的每个点都应靠近该群集的中心。要想实现kmeans算法, 首先我们选择k,即我们想要在数据中找到的簇数。然后,以某种方式初始化这k个簇的中心,称为质心。 然后,我们将数据中的每个点分配给质心最接近的点,然后将每个质心的位置重新计算为分配给其质心的所有点的均值。 下面介绍一个网站
这个网站能把kmeans算法的聚类过程动态图画出来,如图我们点击Add Centroid,添加了四个中心点
然后点击GO,就能看到kmeans算法聚类的动画过程
算法步骤
首先输入k的值,即我们希望将数据集经过聚类得到k个分组;
从数据集中随机选择k个数据点作为初始聚类中心,对任意一个样本点,求其到K个聚类中心的距离,将样本点归类到距离最小的中心的聚类,如此迭代n次;
每次迭代过程中,利用均值等方法更新各个聚类的中心点;
对K个聚类中心,利用2,3步迭代更新后,如果位置点变化很小,则认为达到稳定状态,对不同的聚类块和聚类中心可选择不同的颜色标注。
算法优缺点 优点 1.kmeans算法原理比较简单,实现起来也很容易,收敛速度较快。
2.聚类效果相对于其他聚类算法来说较好,算法的可解释度比较强。
3.参数较少,主要需要调参的参数仅仅是簇数k。
缺点 1.字符串等非数值型数据不适用,kmeans算法基于均值计算,首先要求簇的平均值可以被定义和使用。
2.K-Means的第一步是确定k(要生成的簇的数目),对于不同的初始值K,可能会导致不同结果。
3.应用数据集存在局限性,适用于球状或集中分布数据,不适用于特殊情况数据。
算法定义 k均值聚类是最著名的划分聚类算法,给定一个数据点集合和需要的聚类数目k,k由用户指定,其主要目的是将n个样本点划分为k个簇,使得相似的样本尽量被分到同一个聚簇。
K值的选取 在实际应用中,由于Kmeans一般作为数据预处理,或者用于辅助分类贴标签。所以k一般不会设置很大。对于k值的选取,一般采用以下几种方法。
手肘法
手肘法的核心指标是SSE(sum of the squared errors误差平方和)
聚类数k增大,数据划分就会更精细,每个簇的聚合程度也会提高,从而误差平方和SSE会逐渐变小。当k小于真实聚类数时,k的增大会增加每个簇的聚合程度, 故SSE的下降幅度会很大。当k到达真实聚类数时,再增加k所得到的聚合程度会迅速变小,所以SSE的下降幅度会骤减, 然后随着k值的继续增大而趋于平缓,由此可见SSE和k的关系图是 一个手肘的形状,而这个肘部对应的k值就是数据的真实聚类数。
具体做法是让k从1开始取值直到取到你认为合适的上限,对每一个k值进行聚类并且记下对于的SSE,然后画出k和SSE的关系图, 最后选取肘部对应的k作为我们的最佳聚类数。 下图利用了UCI上葡萄酒的数据集wine.data ,然后用sklearn库中自带的k-means算法对K值的选取进行了可视化操作。
轮廓系数法 轮廓系数(silhouette coefficient)是簇的密集与分散程度的评价指标
计算样本i到同一类中其他样本的平均距离ai。如果ai越小,说明样本i与同类中其他样本的距离越近,即越相似。我们将ai称为样本i的类别内不相似度。
计算样本i到其他类别的所有样本的平均距离bi,称为样本i与其他类之间的不相似度。如果bi越大,说明样本i与其他类之间距离越远,即越不相似。
轮廓系数的值在-1和1之间,该值越接近于1,簇越紧凑,聚类越好。当轮廓系数接近1时,簇内紧凑,并远离其他簇。其中,轮廓系数的计算如下所示:
案例实现(python) 数据集 数据集介绍 本章的数据样本来源于UCI 上的小麦种子数据集。部分数据集如下图所示:
其中,数据集包含210个样本。每个样品具有7个属性:面积A,周长P,紧密度C = 4piA / P ^ 2,籽粒长度,籽粒宽度,不对称系数和籽粒凹槽长度。 所有这些参数都是实值连续的。数据集包含属于三种不同小麦品种的籽粒:卡玛,罗莎和加拿大。
数据集特点:
多元
实例数量:
210
领域:
生活类
属性特征:
真实
属性数量:
7
上传日期:
2012.9.29
相关人物:
分类/聚类
缺值:
N/A
浏览次数:
326689
代码实现 1、导入我们需要的库
1 2 3 import matplotlib.pyplot as pltfrom numpy import *import numpy as np
2、计算欧氏距离
1 2 3 4 def get_distance (p1, p2 ): diff = (sum (power(p1 - p2, 2 ))) return diff
3、导入数据
1 2 3 4 5 6 7 8 9 10 11 12 13 def load_data (file_path ): f = open (file_path) data = [] for line in f.readlines(): row = [] lines = line.strip().split() for x in lines: row.append(float (x)) data.append(row) f.close() return np.mat(data)
4、初始化聚类中心
1 2 3 4 5 6 7 8 9 10 11 12 13 14 def random_data (my_data, k ): sum = np.shape(my_data)[1 ] print (sum ) my_cluster_center = np.mat(np.zeros((k, sum ))) for j in range (sum ): Xmin = np.min (my_data[:, j]) Xrange = np.max (my_data[:, j]) - Xmin my_cluster_center[:, j] = Xmin * np.mat(np.ones((k, 1 ))) + np.random.rand(k, 1 ) * Xrange print ('初始化的聚类中心如下:' ) print (my_cluster_center) return my_cluster_center
5、k_means算法聚类分析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 def k_means (data, k, cluster_center ): m, n = np.shape(data) sub_center = np.mat(np.zeros((m, 2 ))) change = 1 while change == 1 : change = 0 for i in range (m): min_distance = np.inf Index = 0 for j in range (k): diff = get_distance(data[i,], cluster_center[j,]) if diff < min_distance: min_distance = diff Index = j if sub_center[i, 0 ] != Index: change = 1 sub_center[i,] = np.mat([Index, min_distance]) for j in range (k): all = np.mat(np.zeros((1 , n))) r = 0 for i in range (m): if sub_center[i, 0 ] == j: all = all + data[i,] r = r + 1 for a in range (n): try : cluster_center[j, a] = all [0 , a] / r except : print ("没有样本属于这个聚类中心!" ) print ("聚类中心发生变化如下:" ) print (cluster_center) return cluster_center, sub_center
6、保存数据
1 2 3 4 5 6 7 8 9 10 def save_result (Myfile_name, data ): m, n = np.shape(data) f = open (Myfile_name, "w" ) for i in range (m): X = [] for j in range (n): X.append(str (data[i, j])) f.write("\t" .join(X) + "\n" ) f.close()
7、画图
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 def draw (point_data, center, sub_center ): Myfig = plt.figure() axes = Myfig.add_subplot(111 ) length = len (point_data) print (length) for a in range (length): if sub_center[a, 0 ] == 0 : axes.scatter(point_data[a, 2 ], point_data[a, 3 ], color='m' , alpha=0.4 ) if sub_center[a, 0 ] == 1 : axes.scatter(point_data[a, 2 ], point_data[a, 3 ], color='b' , alpha=0.4 ) if sub_center[a, 0 ] == 2 : axes.scatter(point_data[a, 2 ], point_data[a, 3 ], color='g' , alpha=0.4 ) for i in range (len (center)): axes.scatter(center[i, 2 ], center[i, 3 ], color='red' , marker='p' ) plt.xlabel('X' ) plt.ylabel('Y' ) plt.title('kmeans-JYZ' ) plt.show()
8、主函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 if __name__ == "__main__" : K = 3 print ("第一步:导入样本数据" ) sample_data = load_data("seeds.data" ) print ("第二步:初始化k个聚类中心" ) cluster_center = random_data(sample_data, K) print ("第三步:K_Means算法" ) cluster_center, sub_center = k_means(sample_data, K, cluster_center) print ("第四步:保存最终的聚类中心" ) save_result("cluster_center.txt" , cluster_center) print ("第五步:保存每个样本所属类别" ) save_result("sub_center.txt" , sub_center) draw(sample_data, cluster_center, sub_center)
运行结果 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 第一步:导入样本数据 第二步:初始化k个聚类中心 8 初始化的聚类中心如下: [[17.51686311 16.40829437 0.91619839 6.60986498 3.15821884 5.49005513 4.80842984 1.67208591 ] [19.37741169 16.76073519 0.91290766 6.40031021 3.85596015 2.23395909 5.15480027 2.34787189 ] [14.9196659 13.09405509 0.82642333 5.51808314 3.06647918 3.5302489 4.7662341 2.10372636 ]] 第三步:K_Means算法 聚类中心发生变化如下: [[17.81384615 15.93923077 0.87981154 6.0735 3.61865385 4.72330769 5.90411538 1.92307692 ] [19.0005 16.40125 0.8873 6.24715 3.7551 2.935375 6.11635 1.975 ] [13.15833333 13.79847222 0.86487917 5.37635417 3.05568056 3.727925 5.12176389 2.02083333 ]] 聚类中心发生变化如下: [[17.23121212 15.66787879 0.88107879 5.97942424 3.56660606 4.40127273 5.81918182 1.84848485 ] [18.9372093 16.36790698 0.88761628 6.23623256 3.74776744 2.91974419 6.07788372 1.90697674 ] [12.94813433 13.70589552 0.86318358 5.34711194 3.02578358 3.77799403 5.09188806 2.06716418 ]] 聚类中心发生变化如下: [[16.62634146 15.39829268 0.88052439 5.89009756 3.49668293 3.75556341 5.67960976 1.65853659 ] [19.19767442 16.48046512 0.8879907 6.26725581 3.77960465 3.21153488 6.12765116 2. ] [12.78412698 13.63063492 0.8621 5.32544444 3.00333333 3.84895317 5.07414286 2.11111111 ]] 聚类中心发生变化如下: [[15.944 15.0836 0.880146 5.78036 3.42138 3.133462 5.50546 1.44 ] [19.15104167 16.46916667 0.88708958 6.26885417 3.7729375 3.46041667 6.12725 2. ] [12.51366071 13.50669643 0.86001875 5.28633036 2.96550893 4.05597411 5.056375 2.25 ]] 聚类中心发生变化如下: [[15.38075758 14.81636364 0.8797803 5.68925758 3.35859091 2.94465303 5.36257576 1.28787879 ] [19.06 16.43176471 0.88679804 6.25333333 3.76323529 3.51547059 6.11290196 2. ] [12.15903226 13.35 0.85610215 5.24280645 2.91091398 4.3377 5.05383871 2.50537634 ]] 聚类中心发生变化如下: [[15.06763889 14.66194444 0.87993194 5.63831944 3.32394444 2.84957222 5.28854167 1.22222222 ] [18.96296296 16.39666667 0.88595185 6.24272222 3.74992593 3.54033333 6.10077778 2. ] [12.01321429 13.29011905 0.85372857 5.22530952 2.88675 4.53208333 5.06521429 2.66666667 ]] 聚类中心发生变化如下: [[14.84614286 14.54828571 0.88059429 5.59571429 3.30232857 2.74761714 5.22582857 1.15714286 ] [18.78677966 16.32915254 0.88474746 6.22098305 3.72767797 3.58188136 6.07911864 2. ] [11.97938272 13.27962963 0.85269136 5.22535802 2.87914815 4.60960494 5.07677778 2.72839506 ]] 聚类中心发生变化如下: [[14.67805556 14.47152778 0.87971389 5.56618056 3.28319444 2.71346111 5.18791667 1.13888889 ] [18.72180328 16.29737705 0.88508689 6.20893443 3.72267213 3.60359016 6.06609836 1.98360656 ] [11.93675325 13.26441558 0.85168831 5.22703896 2.86797403 4.6994026 5.09263636 2.81818182 ]] 聚类中心发生变化如下: [[14.63202703 14.45324324 0.8790973 5.56178378 3.27489189 2.74404324 5.18493243 1.13513514 ] [18.72180328 16.29737705 0.88508689 6.20893443 3.72267213 3.60359016 6.06609836 1.98360656 ] [11.90906667 13.25026667 0.85154933 5.22233333 2.86509333 4.72218667 5.09304 2.86666667 ]] 聚类中心发生变化如下: [[14.63202703 14.45324324 0.8790973 5.56178378 3.27489189 2.74404324 5.18493243 1.13513514 ] [18.72180328 16.29737705 0.88508689 6.20893443 3.72267213 3.60359016 6.06609836 1.98360656 ] [11.90906667 13.25026667 0.85154933 5.22233333 2.86509333 4.72218667 5.09304 2.86666667 ]] 第四步:保存最终的聚类中心 第五步:保存每个样本所属类别 210
总结 在这里,我们借助小麦种子seeds.data的数据集,介绍了K均值聚类算法的概念,以及利用python实现算法聚类分析以及可视化的过程, 并分析了kmeans算法的优缺点。主要思想就是把相似对象归为同一簇,把不相似对象归到不同簇。簇内的对象越相似,聚类的效果越好。
参考文献 1.https://blog.csdn.net/weixin_42029738/article/details/81978038
2.https://blog.csdn.net/sinat_36710456/article/details/88019323
3.Ahmad EL ALLAOUI. Clustering Kmeans with Evolutionary Strategies[J]. International Journal of Imaging and Robotics™,2017,17(3).
4.刘子熠,张喆,高天,武强. Analysis of Pump Data Based on Association and Kmeans Algorithm[J]. 数据挖掘,2020,10(02).
5.Yi Yi Aung,Myat Myat Min. An Analysis of Kmeans Algorithm Based Network Intrusion Detection System[J]. Advances in Science, Technology and Engineering Systems,2018,3(1).