欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

kmeans聚类算法

程序员文章站 2022-03-10 10:35:43
...

前言

kmeans是一种聚类算法

其简单,易用

在机器学习,数据挖掘领域常常应用

原理

众所周知聚类就是要对一堆杂乱无章的数据进行分类合并

假设我们有数据集dataset,并且将其聚类为k个簇
kmeans聚类算法的思想有如下几步

第一步

首先在数据集随机挑选k个点,分别作为这k个簇的质心

第二步

其余的点根据欧式距离公式,找到离其自身最近的质心
并合并为一类

第三步

现在我们已经初步的到聚类过的样本集合

然后我们取每个样本集合的均值点作为新的质心
重新进行聚类

第四步

各样本点根据新的质心再进行回归

直到样本点分类不再发生改变

算法实现

网上也有很多算法实现
这里我找到一篇比较有效率的代码
下面是该博客地址
https://blog.csdn.net/xufive/article/details/101448969
我在其源代码上增加了一些注释
话不多说直接上代码

import numpy as np
import time
import matplotlib.pyplot as plt


def kmeans(ds, k):
    """
    kmeans聚类算法
    :param ds: 数据集,形式为ndarray(m, n) 即m个样本,每个样本有 n 个属性值
    :param k: 指定分簇数量
    :return:
    """
    m, n = ds.shape
    result = np.empty(m, dtype=np.int) # 产生一个有随机元素的指定大小的矩阵
    cores = ds[np.random.choice(np.arange(m), k ,replace=False)] # 从m个样本随机挑选k个作为core

    while True:
        d = np.square(np.repeat(ds, k, axis=0).reshape(m, k, n) - cores)
        """
        np.repeat是将一个矩阵展开成行向量
        第二个参数指定要复制多少
        这里就是展开数据集
        因为有k个质心
        然后分别计算对应的距离差值
        """
        distance = np.sqrt(np.sum(d, axis=2)) # 在第二维度累加,即形状由(m, k, n)变为(m, k)
        index_min = np.argmin(distance, axis=1) # 找距离最小值

        if (index_min == result).all():
            # 这个条件就是样本聚类没有发生改变
            return result, cores # 返回聚类结果,以及质心

        result[:] = index_min

        for i in range(k):
            # 取质心集合的平均值做为新的质心
            items = ds[result==i] # 找出当前质心对应的数据集
            cores[i] = np.mean(items, axis=0) # 取质心平均值作为新的质心进行迭代


def create_data_set(*cores):
    """生成k-means聚类测试用数据集"""

    ds = list()
    for x0, y0, z0 in cores:
        x = np.random.normal(x0, 0.1 + np.random.random() / 3, z0)
        y = np.random.normal(y0, 0.1 + np.random.random() / 3, z0)
        ds.append(np.stack((x, y), axis=1))

    return np.vstack(ds)


k = 4
ds = create_data_set((0,0,2500), (0,2,2500), (2,0,2500), (2,2,2500))

t0 = time.time()
result, cores = kmeans(ds, k)
t = time.time() - t0

plt.scatter(ds[:,0], ds[:,1], s=1, c=result.astype(np.int))
plt.scatter(cores[:,0], cores[:,1], marker='x', c=np.arange(k))
plt.show()

print(u'使用kmeans算法,1万个样本点,耗时%f0.3秒'%t)


kmeans聚类算法