K-均值是通过对数据集进行分类来聚类的,属于无监督学习,为聚类问题提供了一种解决方案。在数据集没有标注的情况下,便于对数据进行分群。而K-Means中的K即指将数据集分成K个子集合。算法把 n 个点(可以是样本的一次观察或一个实例)划分到 k 个集群(cluster),使得每个点都属于离他最近的均值(即聚类中心,centroid)对应的集群。重复上述过程一直持续到重心不改变。
k均值类算法仅在凸形簇(类似于椭圆形)结构上效果较好。在如下图这种情况k均值效果不好:
- 算法过程:输入为样本集D和聚类簇数k,输出为簇划分C={C1,C2,…,Ck};
1.随机选择k个样本作为初始均值向量;
2.考查所有的样本,计算样本与之前选择的初始均值向量的距离,离哪个近就归为哪一类;
3.根据刚分好的k类,计算出新的均值向量;
4.重复过程2和3,直到迭代产生的结果与上一轮迭代相同或达到设定的迭代次数,算法停止,得到最终的簇划分。
算法python实现:
import numpy as np
import matplotlib.pyplot as plt
# 两点欧氏距离
def distance(e1, e2):
return np.sqrt((e1[0]-e2[0])**2+(e1[1]-e2[1])**2)
# 集合中心
def means(arr):
return np.array([np.mean([e[0] for e in arr]), np.mean([e[1] for e in arr])])
# arr中距离a最远的元素,用于初始化聚类中心
def farthest(k_arr, arr):
f = [0, 0]
max_d = 0
for e in arr:
d = 0
for i in range(k_arr.__len__()):
d = d + np.sqrt(distance(k_arr[i], e))
if d > max_d:
max_d = d
f = e
return f
# arr中距离a最近的元素,用于聚类
def closest(a, arr):
c = arr[1]
min_d = distance(a, arr[1])
arr = arr[1:]
for e in arr:
d = distance(a, e)
if d < min_d:
min_d = d
c = e
return c
if __name__=="__main__":
## 生成二维随机坐标(如果有数据集就更好)
arr = np.random.randint(100, size=(100, 1, 2))[:, 0, :]
## 初始化聚类中心和聚类容器
m = 5 #聚类个数
r = np.random.randint(arr.__len__() - 1)
k_arr = np.array([arr[r]])
cla_arr = [[]]
for i in range(m-1):
k = farthest(k_arr, arr)
k_arr = np.concatenate([k_arr, np.array([k])])
cla_arr.append([])
## 迭代聚类
n = 20 #迭代次数
cla_temp = cla_arr
for i in range(n): # 迭代n次
for e in arr: # 把集合里每一个元素聚到最近的类
ki = 0 # 假定距离第一个中心最近
min_d = distance(e, k_arr[ki])
for j in range(1, k_arr.__len__()):
if distance(e, k_arr[j]) < min_d: # 找到更近的聚类中心
min_d = distance(e, k_arr[j])
ki = j
cla_temp[ki].append(e)
# 迭代更新聚类中心
for k in range(k_arr.__len__()):
if n - 1 == i:
break
k_arr[k] = means(cla_temp[k])
cla_temp[k] = []
## 可视化展示
col = ['HotPink', 'Aqua', 'Chartreuse', 'yellow', 'LightSalmon'] #仅提供了5种颜色
for i in range(m):
plt.scatter(k_arr[i][0], k_arr[i][1], linewidth=10, color=col[i])
plt.scatter([e[0] for e in cla_temp[i]], [e[1] for e in cla_temp[i]], color=col[i])
plt.show()
代码中m表示聚类个数,n表示迭代次数,使用的数据是随机生成的二维坐标,算法通过n次迭代,将随机生成的二维点分为m类。当m=3和m=5时,运行结果如下图所示:
这里m不能超过5个,因为提供的颜色只有五个,如果在col上增加颜色的种类,则聚类数m还可以增加。