K-means算法(学习笔记)

聚类

无监督学习
训练样本的标记信息是未知的,目标是通过对无标记训练样本的学习来揭示数据的内在性质及规律,为进一步的数据分析提供基础

聚类分析
是在数据中发现数据对象之间的关系,将数据进行分组,组内的相似性越大,组间的差别越大,则聚类效果越好。聚类旨在发现有用的对象簇(cluster)
K-means应用的则为基于原型的簇

在这里插入图片描述
基于原型的
簇是对象的集合,其中每个对象到定义该簇的原型的距离比其他簇的原型距离更近,如(b)所示的原型即为中心点,在一个簇中的数据到其中心点比到另一个簇的中心点更近。这是一种常见的基于中心的簇,最常用的K-Means就是这样的一种簇类型。这样的簇趋向于球形。
在这里插入图片描述

K-means算法原理

kmeans算法又名k均值算法。其算法思想大致为:
先从样本集中随机选取 k 个样本作为簇中心,并计算所有样本与这 k 个“簇中心”的距离,对于每一个样本,将其划分到与其距离最近的“簇中心”所在的簇中,对于新的簇计算各个簇的新的“簇中心”
  根据以上描述,我们大致可以猜测到实现kmeans算法的主要三点:
  (1)簇个数 k 的选择
  (2)各个样本点到“簇中心”的距离
  (3)根据新划分的簇,更新“簇中心”

选择K个点作为初始质心 repeat
将每个点指派到最近的质心,形成K个簇
重新计算每个簇的质心 until 簇不发生变化或达到最大迭代次数

算法要点

  1. k 值的选择
    k 的选择一般是按照实际需求进行决定,或在实现算法时直接给定 k 值。

  2. 距离的度量

    (1)有序属性距离度量(离散属性 {1,2,3} 或连续属性):
    在这里插入图片描述
    (2)无序属性距离度量(比如{飞机,火车,轮船}):
       VDM(Value Difference Metric):
       在这里插入图片描述
     (3)混合属性距离度量,即为有序与无序的结合:
    在这里插入图片描述
     数据集为连续属性,因此代码中主要以欧式距离进行距离的度量计算。

  3. 更新“簇中心”
    对于划分好的各个簇,计算各个簇中的样本点均值,将其均值作为新的簇中心。
    在这里插入图片描述

算法实现(python)

伪代码

输入:训练数据集 D=x(1),x(2),…,x(m) ,聚类簇数 k ;
  过程:函数 kMeans(D,k,maxIter) .
  1:从 D 中随机选择 k 个样本作为初始“簇中心”向量: μ(1),μ(2),…,μ(k) :
  2:repeat
  3:  令 Ci=∅(1≤i≤k)
  4:  for j=1,2,…,m do
  5:    计算样本 x(j) 与各“簇中心”向量 μ(i)(1≤i≤k) 的欧式距离
  6:    根据距离最近的“簇中心”向量确定 x(j) 的簇标记: λj=argmini∈{1,2,…,k}dji
  7:    将样本 x(j) 划入相应的簇: Cλj=Cλj⋃{x(j)} ;
  8:  end for
  9:  for i=1,2,…,k do
  10:    计算新“簇中心”向量: (μ(i))′=1|Ci|∑x∈Cix ;
  11:    if (μ(i))′=μ(i) then
  12:      将当前“簇中心”向量 μ(i) 更新为 (μ(i))′
  13:    else
  14:      保持当前均值向量不变
  15:    end if
  16:  end for
  17:  else
  18:until 当前“簇中心”向量均未更新
  输出:簇划分 C=C1,C2,…,CK

(借鉴)

import numpy as np
import matplotlib.pyplot as plt

# 两点距离
def distance(e1, e2):
    return np.sqrt((e1[0]-e2[0])**2+(e1[1]-e2[1])**2)

# 集合中心
def means(arr):
    return np.array([np.mean([e[0] for e in arr]), np.mean([e[1] for e in arr])])

# arr中距离a最远的元素,用于初始化聚类中心
def farthest(k_arr, arr):
    f = [0, 0]
    max_d = 0
    for e in arr:
        d = 0
        for i in range(k_arr.__len__()):
            d = d + np.sqrt(distance(k_arr[i], e))
        if d > max_d:
            max_d = d
            f = e
    return f

# arr中距离a最近的元素,用于聚类
def closest(a, arr):
    c = arr[1]
    min_d = distance(a, arr[1])
    arr = arr[1:]
    for e in arr:
        d = distance(a, e)
        if d < min_d:
            min_d = d
            c = e
    return c


if __name__=="__main__":
    ## 生成二维随机坐标(如果有数据集就更好)
    arr = np.random.randint(100, size=(100, 1, 2))[:, 0, :]

    ## 初始化聚类中心和聚类容器
    m = 5
    r = np.random.randint(arr.__len__() - 1)
    k_arr = np.array([arr[r]])
    cla_arr = [[]]
    for i in range(m-1):
        k = farthest(k_arr, arr)
        k_arr = np.concatenate([k_arr, np.array([k])])
        cla_arr.append([])

    ## 迭代聚类
    n = 20
    cla_temp = cla_arr
    for i in range(n):    # 迭代n次
        for e in arr:    # 把集合里每一个元素聚到最近的类
            ki = 0        # 假定距离第一个中心最近
            min_d = distance(e, k_arr[ki])
            for j in range(1, k_arr.__len__()):
                if distance(e, k_arr[j]) < min_d:    # 找到更近的聚类中心
                    min_d = distance(e, k_arr[j])
                    ki = j
            cla_temp[ki].append(e)
        # 迭代更新聚类中心
        for k in range(k_arr.__len__()):
            if n - 1 == i:
                break
            k_arr[k] = means(cla_temp[k])
            cla_temp[k] = []

    ## 可视化展示
    col = ['HotPink', 'Aqua', 'Chartreuse', 'yellow', 'LightSalmon']
    for i in range(m):
        plt.scatter(k_arr[i][0], k_arr[i][1], linewidth=10, color=col[i])
        plt.scatter([e[0] for e in cla_temp[i]], [e[1] for e in cla_temp[i]], color=col[i])
    plt.show()

结果:
在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值