Kmeans是一种基于欧式距离的聚类算法,判断两个样本点的距离,距离越近,相似度越高。
步骤为:
1.在一个n簇样本点下,随机选取n个质心点。
2.每个样本点计算它到质心点的距离,并将其分到距离最小的质心点所对应的类中
3.保持类别不变,计算类别的中心点,得到新的n个质心点
4.重复以上步骤,迭代多次(SSE最小时终止)
生成数据集
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
from sklearn.datasets import make_blobs
X,y = make_blobs(n_samples=300,
cluster_std=[0.3,0.3,0.3],
centers=[[-1,1],[0,0],[1,1]],
random_state=100)
绘制散点图
plt.style.use("seaborn")
plt.rc("font",family = "YouYuan")
plt.rcParams["axes.unicode_minus"] = False
plt.scatter(data.x1,data.x2)
随机初始化N个质心点
def initial_centers(datasets,N):
#提取数据集中所有特征的最小值和最大值
info_range = datasets.describe().loc[["min","max"],:]
#遍历数据集中所有的特征,从info_range中随机生成N个
N_randoms = [np.random.uniform(info_range.loc["min",i],info_range.loc["max",i],N) for i in data.columns]
#将列表转为Dataframe 并进行转置
centers = pd.DataFrame(N_randoms,index = datasets.columns).T
return centers
计算数据集中所有点到质心点的距离(这里是距离平方)
#计算数据集中所有的点到质心点距离的平方
def cal_distance(datasets,centers):
#存放n个质心点到样本点的距离平方
d_list = []
for i in centers.index:
d_list.append(np.power(datasets-centers.loc[i,:],2).sum(axis = 1))
#将列表转换为Dataframe,columns为质心点的类别
data_dis = pd.concat(d_list,axis = 1)
return data_dis
单次迭代
def iterate(datasets,centers):
#保持质心点不变,更新y值
data_dis = cal_distance(datasets,centers)
y_temp = data_dis.idxmin(axis = 1)
#计算当前y值下的SSE
SSE = data_dis.min(axis = 1).sum()
#得到新的y值之和,保持y不变,更新质心点
centers = datasets.groupby(y_temp).mean()
return y_temp ,SSE,centers
运行多次,可以观测到SSE在减小。
迭代多次
#创建一个SSE_list,存放每次迭代的SSE
SSE_list = [0]
#初始化质心点
centers = initial_centers(data,3)
#开始迭代
while True:
y_temp ,SSE,centers = iterate(data,centers)
#判断当前SSE值是否与最后一个SSE值同
if SSE ==SSE_list[-1]:
break;
SSE_list.append(SSE)
SSE_list
最终得到的SSE_list 为:
[0,
533.248514452687,
173.4974240812278,
136.09880601267884,
91.02446700337498,
58.622219118691156,
57.73097424985825,
57.71670209312117]
最小的SSE约为57.71,总共迭代了7次。
以上仅是我个人的对于Kmeans算法步骤的一个简单学习,还有很多缺点和不足,日后我会对其进行进一步的学习和改进。
AI 编写的K-means迭代 :
# Number of clusters (K)
K = 3
# Maximum number of iterations
max_iterations = 100
# Initialize cluster centers
cluster_centers = np.array([[point_1_x1, point_1_x2],
[point_2_x1, point_2_x2],
[point_3_x1, point_3_x2]])
for iteration in range(max_iterations):
# Assignment step
#np.linalg.norm 直接计算了L2范数,np.argmin 展平取得最小下标值
distances = np.array([np.linalg.norm(data_set.values - center, axis=1) for center in cluster_centers])
cluster_assignments = np.argmin(distances, axis=0)
# Update step
new_centers = [data_set[cluster_assignments == i].mean(axis=0) for i in range(K)]
new_cluster_centers = np.vstack(new_centers)
# Check for convergence
if np.all(cluster_centers == new_cluster_centers):
break
cluster_centers = new_cluster_centers