手写KMeans聚类,纯python实现(使用了numpy 库),具体见代码,注释都在代码中。
# -*- coding: utf-8 -*-
"""
Created on Sun Jun 21 16:46:52 2020
@author: Lenovo
"""
import numpy as np
#计算距离函数
def euclidean_distance(x1,x2):
distance=0
for i in range(len(x1)):
distance+=pow((x1[i]-x2[i]),2)
return np.sqrt(distance)
#定义初始化函数
def centroids_init(k,X):
n_samples,n_features=X.shape
centroids=np.zeros((k,n_features))
#centroids用于储存每个聚类中心
for i in range(k):
#每一次循环随机选择一个类别中心
centroid=X[np.random.choice(range(n_samples))] # 从 n_samples里面随机选一个作为聚类中心
centroids[i]=centroid
return centroids
#定义样本的最近质心点所属的类别索引
def closest_centroid(sample,centroids):
closest_i=0
#先把距离设为无穷大
closest_dist=float('inf')
for i,centroid in enumerate(centroids):
distance=euclidean_distance(sample,centroid)
if distance < closest_dist:
closest_i=i
closest_dist=distance
return closest_i
#定义构建类别过程
def create_clusters(centroids,k,X):
clusters=[[] for i in range(k)]
#假如 K 为3,那么上面语句执行后,clusters为 [[],[],[]]
for sample_i , sample in enumerate(X):
#得到sample所属的聚类中心的标签
centroid_i=closest_centroid(sample,centroids)
clusters[centroid_i].append(sample_i)
return clusters
#根据上一步的计算结果计算新的中心点
def calculate_centroids(clusters,k,X):
n_features=np.shape(X)[1]
centroids=np.zeros((k,n_features))
for i,cluster in enumerate(clusters):
#求平均值,这就是KMeans更新聚类中心的方法
centroid=np.mean(X[cluster],axis=0)
#更新聚类中心
centroids[i]=centroid
return centroids
#获取每个样本所属的聚类类别
def get_cluster_labels(clusters,X):
y_pred=np.zeros(np.shape(X)[0])
for cluster_i,cluster in enumerate(clusters):
for sample_i in cluster:
y_pred[sample_i]=cluster_i
return y_pred
#封装整合
def kmeans(X,k,max_iter):
centroids=centroids_init(k,X)
for i in range(max_iter):
clusters=create_clusters(centroids,k,X)
prev_centroids=centroids
centroids=calculate_centroids(clusters,k,X)
diff=centroids-prev_centroids
#当聚类中心不再变化时,停止迭代
if not diff.any():
break
return get_cluster_labels(clusters,X),centroids
X=np.array([[0,2],[0,0],[5,0],[4,5],[1,1]])
labels,centers=kmeans(X,2,10)
print(labels)
print(centers)
输出为:
[1. 1. 0. 0. 1.]
[[4.5 2.5 ]
[0.33333333 1. ]]
参考文献:
公众号“机器学习实验室”的原创文章“数学推导+纯Python实现机器学习算法25:kmeans聚类”