K-means算法(基于numpy)
K-means算法是输入K个聚类个数,以及包含 M个数据对象的数据库(本篇采用的是sklearn.datasets中的make_blobs方法生成高斯(正态)分布的10000个点以及5个随机点作为中心点的样本数据,以便用于聚类),输出满足方差最小的标准k个聚类的一种算法。
同一聚类中的对象相似度较高;而不同聚类中的对象相似度较小的特点。
聚类相似度是利用各聚类中对象的均值所获得一个“中心对象”来进行计算的。
具体实现代码以及详解如下:
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs #make_blobs的主要作用是处理数据,生成高斯(正态)分布的数据,以便用于聚类
import time
# 计算两点之间距离
def distance(point1, point2):
return np.sum((point1 - point2) ** 2)
# 计算当前各个中心点中离给定点pt最近的一个
def classify(pt, centers):
temp = [distance(pt, centers[i]) for i in range(len(centers))]
index = np.argmin(temp) #argmin是指使得函数f(x)取得其最小值时,自变量x的值
dist = temp[index] #获得最小的距离
return (index, dist)
# 将每个点归入到离它最近的中心点类别下
def re_category():
for category in results: #category:类别
category.clear() #清空存放各分类结果的列表
newcost = 0.0
for pt in X:
index, dist = classify(pt, centers) #dist:距离
results[index].append(pt) # 将pt纳入离它最近的中心点类别下
newcost += dist #计算各个点离其归属中心点的最小距离之和
return newcost / M #返回其平均值
# 根据当前的类别划分,重新计算每个类别下新的中心点
def calc_centers():
for i in range(len(results)):
centers[i] = np.mean(results[i], 0) #results类别,分类
M = 10000 #数据点个数
K = 5 #类别数
# 围绕K个中心点,生成M个随机二维数据点 # cluster_std:每个类别的方差; random_state:随机种子,使随机状可重
X, Y = make_blobs(n_samples=M, centers=K, cluster_std=2.0, random_state=20)
cost = 1e10 # 初始误差可以是一个很大的数
epsilon = 1e-8 #结束时的误差一定尽可能的小
max_iter = 100 #最大循环次数
results = [[] for i in range(K)] #存放分类结果
# 随机选择K个中心点作为初始点
init_indecies = np.random.randint(0, M, K) #随机索引
centers = X[init_indecies] #根据随机出来的索引取对应的点坐标作为中心点
start = time.time() #开始时间
# 计算分类
newcost = re_category()
iter = 0
while iter < max_iter:
iter += 1
if np.abs(newcost - cost) > epsilon :
cost = newcost
# 重新计算各类中心点
calc_centers()
# 再次计算
newcost = re_category()
else: #只有当上次各个点离其归属中心点的最小距离之和的平均值与本次相差极小时,认为分类完成。
stop = time.time()
print("最终耗时为", stop - start)
print("经过",iter,"次循环,分类完成...")
break
#将各个点按照不同分类赋予不同颜色
yPredicts = np.zeros(M) #全零的一维数组,存放不同分类的颜色值
for i in np.arange(M):
category, _ = classify(X[i], centers)
yPredicts[i] = category
#两行代码支持中文
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
#创建子图显示
fig = plt.figure()
subplot1 = fig.add_subplot(1,2,1)
subplot1.set_xlabel("查看原始分类情况")
subplot1.scatter(X[:, 0], X[:, 1], c=Y, s=30, cmap=plt.cm.Paired) #Paired成对
subplot2 = fig.add_subplot(1,2,2)
subplot2.set_xlabel("查看K-Means分类结果")
subplot2.scatter(X[:, 0], X[:, 1], c=yPredicts, s=30, cmap=plt.cm.Paired)
plt.show()
运行及显示结果如下: