KMeans算法介绍,python实现

K-means算法是一种常用的聚类算法,用于将数据集划分为K个不同的类别。每个类别由其质心(centroid)表示,该质心是类别内所有数据点的平均值。K-means算法的目标是最小化数据点与其所属类别质心之间的平方距离。

 K-means算法在各个领域广泛应用,包括数据分析、图像处理、模式识别等。它是一种简单而高效的聚类算法,但在处理非凸形状的数据集或存在噪声的情况下可能表现不佳。有一些改进的K-means算法,如K-means++和Mini-Batch K-means,可以用来改善初始质心选择和处理大规模数据集的效率。

以下是K-means算法的基本步骤:

  1. 初始化:选择要划分的类别数K,并随机选择K个数据点作为初始质心。

  2. 分配:对于每个数据点,计算其与所有质心之间的距离,并将数据点分配给最近的质心所代表的类别。

  3. 更新:对于每个类别,计算其所有数据点的平均值,以得到新的质心位置。

  4. 重复:重复步骤2和步骤3,直到质心不再变化或达到预定的迭代次数。

  5. 输出:得到最终的类别划分结果和质心位置。

伪代码如下 

 

此出有个可视化网站可以帮助我们更好理解:https://www.naftaliharris.com/blog/visualizing-k-means-clustering/

下面是用python实现: 

import numpy as np
import matplotlib.pyplot as plt

# 随机初始中心点
def randCent(data, k):
    N, D = data.shape
    centroids = np.zeros((k,D))         # 创建k个中心点
    for i in range(k):
        index = np.random.randint(0, N)
        # 随机一个数,将该数作为data的索引,赋给中心点
        centroids[i, :] = data[index, :]
    return centroids

# 距离计算
def distance(x, y):
    return np.linalg.norm(x - y)    # return np.sqrt((x - y)**2)

def KMeans(data, k ,max_iter=200 ,show=False):
    """
    :param data: 需要训练的数据
    :param k: 需要分为几类
    :param max_iter: 最大迭代次数,默认为200
    :param show: 展示算法过程
    :return: 返回聚类结果,仅返回分类结果

    """
    N, D = data.shape           # shape函数查看数组维度
    centroids = randCent(data, k)
    labels = np.zeros(N, dtype=int)
    for pic in range(max_iter):   # 迭代次数
        for i in range(N):      # 更新簇的分类
            min_dis = 100000    # min_dis作为中间值,用于比较
            # min_dis = distance(data[i, :], centroids[0, :])这样写更严谨,但更复杂
            for j in range(k):
                d = distance(data[i, :], centroids[j, :])
                if d < min_dis:
                    min_dis = d
                    index = j
            labels[i] = index
        for i in range(k):      # 更新各簇的中心点
            labels_data = data[labels == i]     # 索引出同一簇的数据
            # 对其求均值,注意axis,默认为None,即对所有求均值,0对列求均值,1对行求
            centroids[i, :] = np.mean(labels_data, axis=0)
        if show:
        # 该过程是展示聚类过程,每迭代50次,画一张图展示所有点的分类情况已经中心点的位置
            if pic % 50 == 0:
                plt.scatter(data[:, 0], data[:, 1], c=labels)
                plt.scatter(centroids[:, 0], centroids[:, 1], marker='x', s=200,
                            linewidths=3, color='b')
                plt.show()
    return labels

导入数据:

data = np.loadtxt(r"data/aggregation.txt")
data = data[:, :-1]
k = 5
labels = KMeans(data, k, show=True, max_iter=200)
plt.show()

过程如下:

标迭代第50次的结果
标题迭代第100次的结果 

 

标迭代第150次的结果
迭代第200次的结果

 

 我们可以观察得到:其实迭代到后面基本就不变了,我们可以设计一下,当中心点不发生变化时就停止迭代

K值对聚类结果的影响:

 这个很容易理解,不同的k表示分成多少类,即导致聚类结果不一样

随机中心点的局限

我们可以看到多次进行kmeans聚类,聚类结果也是不同的

这是因为我们每次初始化的中心点是随机的,这就会导致我们的结果也会不同

 

 不同数据在KMeans算法下的聚类效果

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值