sklearn初探(八):自行实现k-means算法及其可视化
前言
本次任务为自行实现一个k-means聚类算法,并使用t-sne对聚类结果降维,使用matplotlib进行可视化。当然,本次不会调用sklearn包,不过姑且算是一个系列中的。完整源码以及数据集链接在文末给出。
定义距离
既然是聚类算法,那么一定要定义距离。距离的选择有很多种,比如欧氏距离,海明距离,余弦距离等等。由于本次实验数据维度不高,选择最简单的欧氏距离。
def distEclud(vec_a, vec_b):
sum = 0.0
# print(len(vec_a))
vec_a = vec_a.tolist()
vec_b = vec_b.tolist()[0]
# print(vec_a)
# print(vec_b)
for i in range(0, len(vec_a)):
sum += (vec_a[i]-vec_b[i])**2
return np.sqrt(sum)
选择随机初始聚类质心
k-means聚类算法就是每次迭代中,将距离已知质心最近的点归为一类,然后根据每一类的点更新该类的质心。初始的质心一般随机生成,而这种随机性也造成k-means算法不稳定。实际上,sklearn包中的k-means算法在初始质心的选择上做了优化。我们这里就仅实现简单的随机选择。
def randCent(dataset, k):
n = np.shape(dataset)[1]
centroids = np.mat(np.zeros([k, n]))
for i in range(n):
maxi = max(dataset[:, i])
mini = min(dataset[:, i])
centroids[:, i] = mini + (maxi - mini) * np.random.random([k, 1])
return centroids
k-means核心算法
下面就到最激动人心的时刻了。代码中没有注释,不过很容易看懂(前提是你了解k-means算法)。
def my_k_means(data_set, k):
m = np.shape(data_set)[0] # 样本数量
clusterAssment = np.mat(np.zeros((m, 2)))
centroids = randCent(data_set, k)
cluster_changed = True
while cluster_changed:
cluster_changed = False
for i in range(m):
mindist = np.inf
for j in range(k):
distj = distEclud(data_set[i, :], centroids[j, :])
if distj < mindist:
mindist = distj
minj = j
if clusterAssment[i, 0] != minj:
cluster_changed = True
clusterAssment[i, :]