一、k-means算法介绍
k-means 算法是首先从含有n个数据对象的数据集中随机选择K个数据对象作为初始中心。
然后计算每个数据对象到各中心的距离,根据最近邻原则,所有数据对象将会被划分到离它最近的那个中心所代表的簇中。
接着分别计算新生成的各个簇中数据对象的均值作为各簇新的中心,比较新的中心和上一次得到的中心,如果没有发生变化,则算法收敛,输出结果;
如果新的中心和上一次的中心相比发生变化,则要以新的中心对所有数据对象重新进行划分。直到满足算法的收敛条件为止。
二、缺点和优化方法
K-means聚类算法的三种改进(K-means++,ISODATA,Kernel K-means)介绍与对比
1、针对于k-means 算法第一步分析改进:k-means 算法是首先从含有n个数据对象的数据集中随机选择K个数据对象作为初始中心。
缺点:对初始中心的选取敏感,初始中心随机选取,导致结果波动较大,稳定性较差。
优化:K-means++ (思想:K-means++认为初始聚类中心当然是互相离得越远越好)
注:sklearn.cluster中提供的KMeans类默认使用的就是K-means++算法,如想使用K-means算法可以将init=‘random’
model=KMeans(n_clusters=k,n_jobs=4,max_iter=iter,random_state=1234)
但是本次试验将实现代码另外分两个文件实现出来比较。
三、代码实现
压缩包附Kmeans++.py和Kmeans.py
其中主要是两个寻找中心的代码不一样
Kmeans++:
#选择尽可能相距较远的类中心
def get_centroids(dataset, k):
m, n = np.shape(dataset)
cluster_centers = np.zeros((k, n))
index = np.random.randint(0, m)
cluster_centers[0,] = dataset[index,]
# 2、初始化一个距离的序列
d = [0.0 for _ in range(m)]
for i in range(1, k):
sum_all = 0
for j in range(m):
# 3、对每一个样本找到最近的聚类中心点
d[j] = nearest(dataset[j,], cluster_centers[0:i, ])
# 4、将所有的最短距离相加
sum_all += d[j]
# 5、取得sum_all之间的随机值
sum_all *= random.rand()
# 6、获得距离最远的样本点作为聚类中心点
for j, di in enumerate(d):
sum_all = sum_all - di
if sum_all > 0:
continue
cluster_centers[i,] = dataset[j,]
break
return cluster_centers
Kmeans:
#随机初始化类中心
def randcenter(set,k):
dim=shape(set)[1]
init_cen=zeros((k,dim))
for i in range(dim):
min_i=min(set[:,i])
range_i=float(max(set[:,i]) - min_i)
init_cen[:,i]=min_i + range_i*random.rand(k)
return init_cen
四、结果对比(数据:为上课所用consumption_data.xls 评估方法:轮廓系数)
稳定性:K-means++结果跑出来基本固定、但是K-means不同次跑出来的结果会有所不同
K-means++:(与sklearn.cluster中提供的KMeans类调用所得结果一致)
质心:
类别和类别对应数量和轮廓系数:
K-means–情况一:
质心:
类别和类别对应数量:
轮廓系数:
K-means–情况二: