• K-Means算法的Python实现


    算法简介

    K-Means是一种常用的聚类算法。聚类在机器学习分类中属于无监督学习,在数据集没有标注的情况下,便于对数据进行分群。而K-Means中的K即指将数据集分成K个子集合。

    K-Means演示

    从以下的动画、视频和计算过程可以较为直观了解算法的计算过程。

    动画展示

    wikipedia kmeans animation

    视频展示

    https://youtu.be/BVFG7fd1H30

    在线展示

    kmeans测试页面

    使用场景

    由于简单和低维度下高效的特性,K-Means算法被应用在人群分类,图像分段,文本分类以及数据挖掘前数据预处理场景中。

    算法理解

    计算流程

    一下使用$$分隔的内容为LaTeX编码的数学表达式,请自行解析。
    假设有n个点$$x_{1}$$, $$x_{2}$$, $$x_{3}$$, ..., $$x_{n}$$ 以及子集数量K。

    • 步骤1 取出K个随机向量作为中心点用于初始化

    [C = c_{1},c_{2},...,c_{k} ]

    • 步骤2 计算每个点$$x_{n}$$与K个中心点的距离,然后将每个点聚集到与之最近的中心点

    [min_{c_{i} in C} dist(c_{i},x) ]

    dist函数用于实现欧式距离计算。

    • 步骤3 新的聚集出来之后,计算每个聚集的新中心点

    [c_{i} = avg(sum_{x_{i} in S_{i}} x_{i})​ ]

    Si表示归属于第i个中心点的数据。

    • 步骤4 迭代步骤2和步骤3,直至满足退出条件(中心点不再变化)

    Python代码实现

    本代码参考了https://mubaris.com/posts/kmeans-clustering/这篇博客, 用于聚类的数据集可从GitHub上下载到,下载的地址https://github.com/mubaris/friendly-fortnight/blob/master/xclara.csv

    Python代码如下:

    导包,初始化图形参数,导入样例数据集

    %matplotlib inline
    from copy import deepcopy
    import numpy as np
    import pandas as pd
    from matplotlib import pyplot as plt
    plt.rcParams['figure.figsize'] = (16, 9)
    plt.style.use('ggplot')
    
    
    # 导入数据集
    data = pd.read_csv('xclara.csv')
    # print(data.shape)
    # data.head()
    

    将数据集转换为二维数组,并绘制二维坐标图

    # 将csv文件中的数据转换为二维数组
    f1 = data['V1'].values
    f2 = data['V2'].values
    
    X = np.array(list(zip(f1, f2)))
    plt.scatter(f1, f2, c='black', s=6)
    

    样例点

    定义距离计算函数

    # 按行的方式计算两个坐标点之间的距离
    def dist(a, b, ax=1):
        return np.linalg.norm(a - b, axis=ax)
    

    初始化分区数,随机获得初始中心点

    # 设定分区数
    k = 3
    # 随机获得中心点的X轴坐标
    C_x = np.random.randint(0, np.max(X)-20, size=k)
    # 随机获得中心点的Y轴坐标
    C_y = np.random.randint(0, np.max(X)-20, size=k)
    C = np.array(list(zip(C_x, C_y)), dtype=np.float32)
    

    将初始化中心点和样例数据画到同一个坐标系上

    # 将初始化中心点画到输入的样例数据上
    plt.scatter(f1, f2, c='black', s=7)
    plt.scatter(C_x, C_y, marker='*', s=200, c='red')
    

    初始节点和样例数据节点

    实现K-Means中的核心迭代

    # 用于保存中心点更新前的坐标
    C_old = np.zeros(C.shape)
    print(C)
    # 用于保存数据所属中心点
    clusters = np.zeros(len(X))
    # 迭代标识位,通过计算新旧中心点的距离
    iteration_flag = dist(C, C_old, 1)
    
    tmp = 1
    # 若中心点不再变化或循环次数不超过20次(此限制可取消),则退出循环
    while iteration_flag.any() != 0 and tmp < 20:
        # 循环计算出每个点对应的最近中心点
        for i in range(len(X)):
            # 计算出每个点与中心点的距离
            distances = dist(X[i], C, 1)
            # print(distances)
            # 记录0 - k-1个点中距离近的点
            cluster = np.argmin(distances) 
            # 记录每个样例点与哪个中心点距离最近
            clusters[i] = cluster
            
        # 采用深拷贝将当前的中心点保存下来
        # print("the distinct of clusters: ", set(clusters))
        C_old = deepcopy(C)
        # 从属于中心点放到一个数组中,然后按照列的方向取平均值
        for i in range(k):
            points = [X[j] for j in range(len(X)) if clusters[j] == i]
            # print(points)
            # print(np.mean(points, axis=0))
            C[i] = np.mean(points, axis=0)
            # print(C[i])
        # print(C)
        
        # 计算新旧节点的距离
        print ('循环第%d次' % tmp)
        tmp = tmp + 1
        iteration_flag = dist(C, C_old, 1)
        print("新中心点与旧点的距离:", iteration_flag)
    

    将最终结果和样例点画到同一个坐标系上

    # 最终结果图示
    colors = ['r', 'g', 'b', 'y', 'c', 'm']
    fig, ax = plt.subplots()
    # 不同的子集使用不同的颜色
    for i in range(k):
            points = np.array([X[j] for j in range(len(X)) if clusters[j] == i])
            ax.scatter(points[:, 0], points[:, 1], s=7, c=colors[i])
    ax.scatter(C[:, 0], C[:, 1], marker='*', s=200, c='black')
    

    最终计算结果图示

  • 相关阅读:
    规约先行-(六)并发处理
    MySQL选择合适的方式存储时间
    规约先行-(五)集合处理
    规约先行-(四)OOP 规约
    12.20-LaTex git workflow
    6.25-ROS 软件度量
    6.19-rosdoc_lite and 文档构建工具
    12.27-ros-decision making
    12.3-分级并发有限状态机-SMACH
    12.07-rostest学习
  • 原文地址:https://www.cnblogs.com/shenfeng/p/kmeans_demo.html
Copyright © 2020-2023  润新知