K-means算法(Lloyod,1982)是简单而又有效的统计聚类算法,使机器能够将具有 相同属性
的样本归置到一块儿。与分类不同,对于一个分类器,通常需要告诉它 “这个样本被分成哪些类”这样一些标签,在
最理想情况下,一个分类器会从所 得到的训练集中进行“学习”,我们将这种提供训练的过程称为“监督学习”。但是
在聚类下,我们并不关心某一类是什么,我们的目的是想将相似的样本归置在 一起,这样,一个聚类算法通常只要知
道该如何计算样本间的相似度并将相似样 本归并到一起就可以操作了,因此聚类通常并不需要使用训练数据进行学
习,这 在机器学习中被称作“无监督学习”。K-means算法就是这种用于统计的无监督 聚类技术。
K-Means算法思想:对给定的样本集,事先确定聚类簇数K,让簇内的样本尽可 能紧密分布在一起,使簇间的距离
尽可能大。该算法试图使集群数据分为n组独 立数据样本,使n组集群间的方差相等,数学描述为最小化惯性或集群
内的平方 和。K-Means作为无监督的聚类算法,实现较简单,聚类效果好,因此被广泛使用。
K-means聚类算法简介
1.首先获得一个数据样品集
2.按照平均的方法找到k个初始聚类中心
3.将数据中的每个点 与已有的k个聚类中心计算得到欧氏距离
得到离该点最近的聚类中心 把数据集分成一个个的簇( cluster )
4.为了更加精确 要采取迭代的方法 将以经分好的簇 经过加权平均得到新的聚类中心 重新进行分类计算 —>3 直到new中心和last中心乎一样 既每个数据点的所属聚类中心不再发生变化 迭代结束
举例
初始数据坐标
每个数据点距离聚类中心的欧氏距离
按照距离找到所属的聚类中心
0代表第一个中心 1带代表第二个
因为这里选取的k为2
这个结果存到last容器里面 然后得到新的new数据后比较
import numpy as np
import matplotlib.pyplot as plt
# 构造聚类中心
# dataset [N,D]
# K 聚类中心的数目 [K,D]
def creat_centers(dataset, K):
val_max = np.max(dataset, axis=0)
val_min = np.min(dataset, axis=0)
centers = np.linspace(val_min, val_max, num=K + 2)
return centers[1:-1, :]
#draw_kmeans 画图
def draw_kmeans(dataset, lab, centers, dic_colors=None, name="0.jpg"):
plt.cla()
vals_lab = set(lab.tolist())
for i, val in enumerate(vals_lab):
index = np.where(lab == val)[0]
sub_dataset = dataset[index, :]
plt.scatter(sub_dataset[:, 0], sub_dataset[:, 1], s=16., color=dic_colors[i])
for i in range(np.shape(centers)[0]):
plt.scatter(centers[i, 0], centers[i, 1], color="k", marker="+", s=200.)
plt.savefig(name)
#进行kmeans的计算
#dataset数据样品集
#k个聚类中心
#最多m次迭代
#颜色和是否画图
def run_kmeans(dataset, K, m, dic_colors, b_draw):
N, D = np.shape(dataset)
# print(N,D)
# 确定初始化聚类中心
centers = creat_centers(dataset, K)
lab = np.zeros(N)
if b_draw:
draw_kmeans(dataset, lab, centers, dic_colors, name="int.jpg")
# 进行m轮迭代
labs = np.zeros(N) # 初始聚类结果
for it in range(m):
# 计算每个点距离中心的距离
distance = np.zeros([N, K])
for k in range(K):
center = centers[k, :]
# 计算欧式距离
diff = np.tile(center, (N, 1)) - dataset
sqrDiff = diff ** 2
sqrDiffSum = sqrDiff.sum(axis=1)
distance[:, k] = sqrDiffSum
# 距离排序,进行聚类
labs_new = np.argmin(distance, axis=1)
error = np.sum(np.min(distance, axis=1)) / N
print(np.sum(np.min(distance,axis=1)))
print("第 %d 次聚类 距离误差 %.2f" % (it, error))
# 绘图
if b_draw:
draw_kmeans(dataset, labs_new, centers,
dic_colors, name=str(it) + "_oldcenter.jpg")
# 计算新的聚类中心
for k in range(K):
index = np.where(labs_new == k)[0]
centers[k, :] = np.mean(dataset[index, :], axis=0)
# 绘图
if b_draw:
draw_kmeans(dataset, labs_new, centers,
dic_colors, name=str(it) + "_newcenter.jpg")
# 如果聚类结果和上次相同,退出
if np.sum(labs_new - labs) == 0:
return labs_new
else:
labs = labs_new
return labs
if __name__ == "__main__":
a = np.random.multivariate_normal([2, 2], [[.5, 0], [0, .5]], 100)
b = np.random.multivariate_normal([0, 0], [[0.5, 0], [0, 0.5]], 100)
dataset = np.r_[a, b]
lab_ture = np.r_[np.zeros(100), np.ones(100)].astype(int)
dic_colors = {0: (0., 0.5, 0.), 1: (0.8, 0, 0)}
labs = run_kmeans(dataset, 2, 20, dic_colors,True)
初始数据
分类后数据