一、K-means算法简介
K-means算法是
一种典型的无监督学习算法,主要用于将相似的样本自动归到一个类别中,发现k个不同的簇,并且每个簇的中心用簇中所含值的均值计算而成。对于不同相似度计算方法,有不同聚类结果,常用的相似度计算方法有欧式距离法。组内差别越小,组间差别越大,聚类越好。
二、算法原理
随机给定K个簇中心,循环进行以下两步,将数据点归类到离他最近的簇上,然后计算每一个簇的重心。
三、K-means算法核心伪代码:
创建K个点作为初始质心(随机选择) 当任意一个点的簇分配结果发生改变时:
对数据中的每个点和质心计算质心与数据点之间的距离
将数据点分配到距其最近的簇
对每个簇,计算簇中所有点的均值并且将均值作为新的质心
不断迭代
直到簇不再发生变化或者达到最大迭代次数
四、代码实现
测试数据集:
kmeans_data.txt
1.658985 4.285136
-3.453687 3.424321
4.838138 -1.151539
-5.379713 -3.362104
0.972564 2.924086
-3.567919 1.531611
0.450614 -3.302219
-3.487105 -1.724432
2.668759 1.594842
-3.156485 3.191137
3.165506 -3.999838
-2.786837 -3.099354
4.208187 2.984927
-2.123337 2.943366
0.704199 -0.479481
-0.392370 -3.963704
2.831667 1.574018
-0.790153 3.343144
2.943496 -3.357075
-3.195883 -2.283926
2.336445 2.875106
-1.786345 2.554248
2.190101 -1.906020
-3.403367 -2.778288
1.778124 3.880832
-1.688346 2.230267
2.592976 -2.054368
-4.007257 -3.207066
2.257734 3.387564
-2.679011 0.785119
0.939512 -4.023563
-3.674424 -2.261084
2.046259 2.735279
-3.189470 1.780269
4.372646 -0.822248
-2.579316 -3.497576
1.889034 5.190400
-0.798747 2.185588
2.836520 -2.658556
-3.837877 -3.253815
2.096701 3.886007
-2.709034 2.923887
3.367037 -3.184789
-2.121479 -4.232586
2.329546 3.179764
-3.284816 3.273099
3.091414 -3.815232
-3.762093 -2.432191
3.542056 2.778832
-1.736822 4.241041
2.127073 -2.983680
-4.323818 -3.938116
3.792121 5.135768
-4.786473 3.358547
2.624081 -3.260715
-4.009299 -2.978115
2.493525 1.963710
-2.513661 2.642162
1.864375 -3.176309
-3.171184 -3.572452
2.894220 2.489128
-2.562539 2.884438
3.491078 -3.947487
-2.565729 -2.012114
3.332948 3.983102
-1.616805 3.573188
2.280615 -2.559444
-2.651229 -3.103198
2.321395 3.154987
-1.685703 2.939697
3.031012 -3.620252
-4.599622 -2.185829
4.196223 1.126677
-2.133863 3.093686
4.668892 -2.562705
-2.793241 -2.149706
2.884105 3.043438
-2.967647 2.848696
4.479332 -1.764772
-4.905566 -2.911070
python实现:
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
读取数据集数据,并绘出数据集散点图
data = pd.read_table('kmeans_data.txt',header=None,names=['x','y'])
x = data['x']
y = data['y']
plt.scatter(x,y)
原始数据集图
通过计算各点与质心距离(欧式距离),得到与当前点距离最近的质心
def distance(data,centers):
# data: 80x2, centers: 4x2
dist = np.zeros((data.shape[0],centers.shape[0]))
for i in range(len(data)):
for j in range(len(centers)):
dist[i,j] = np.sqrt(np.sum((data.iloc[i,:]-centers[j])**2))
return dist
def near_center(data,centers):
dist = distance(data,centers)
near_cen = np.argmin(dist,1)
return near_cen
在范围内随机确定质心,迭代(假定10次)调用计算点与质心距离方法,调用更新质心方法,并绘出聚类结果图
def kmeans(data,k):
centers = np.random.choice(np.arange(-5,5,0.1),(k,2))
print(centers)
for _ in range(10):
near_cen = near_center(data,centers)
for ci in range(k):
centers[ci] = data[near_cen==ci].mean()
return centers,near_cen
centers,near_cen = kmeans(data,4)
plt.scatter(x,y,c=near_cen)
plt.scatter(centers[:,0],centers[:,1],marker='*',s=500,c='r')
初始化质心位置坐标与运行一次后质心位置坐标对比图
- 迭代1次聚类结果图
- 迭代2次聚类结果图
- 迭代3次聚类结果图
- 迭代10次聚类结果图
以上为质心为4个聚类结果
可改变质心数,展示不同聚类结果
-
当质心为3时聚类结果图
-
当质心为2时聚类结果图
五、算法优缺点
优点:
- 简单、快速、适合常规工具集
缺点:
- K值难确定,事先不知道数据集聚成几个簇才合适;
- 需要选多点研究 ,复杂度与样本呈线性关系,样本越多,复杂度越大
- 初始聚类中心为随机的,一旦选择不合理,无法得到有效的聚类结果
- 很难发现任意形状的簇
六、k-means算法改进
查阅书籍及资料得到k值未知时合理划分的k-means改进方法:
取k值的上限作为k值的初始值,运行k-means算法得到初始聚类,再通过判断边界距离确定小的聚类是否应是同一聚类,若是同一聚类,则合并这些聚类,从而不断缩小聚类数k的值,最终得到合理划分。