机器学习----K-均值(K-means)算法原理及python实现

K-均值是通过对数据集进行分类来聚类的,属于无监督学习,为聚类问题提供了一种解决方案。在数据集没有标注的情况下,便于对数据进行分群。而K-Means中的K即指将数据集分成K个子集合。算法把 n 个点(可以是样本的一次观察或一个实例)划分到 k 个集群(cluster),使得每个点都属于离他最近的均值(即聚类中心,centroid)对应的集群。重复上述过程一直持续到重心不改变。

k均值类算法仅在凸形簇(类似于椭圆形)结构上效果较好。在如下图这种情况k均值效果不好:
在这里插入图片描述

  • 算法过程:输入为样本集D和聚类簇数k,输出为簇划分C={C1,C2,…,Ck};
    1.随机选择k个样本作为初始均值向量;
    2.考查所有的样本,计算样本与之前选择的初始均值向量的距离,离哪个近就归为哪一类;
    3.根据刚分好的k类,计算出新的均值向量;
    4.重复过程2和3,直到迭代产生的结果与上一轮迭代相同或达到设定的迭代次数,算法停止,得到最终的簇划分。

算法python实现:

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']    #仅提供了5种颜色
    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()

代码中m表示聚类个数,n表示迭代次数,使用的数据是随机生成的二维坐标,算法通过n次迭代,将随机生成的二维点分为m类。当m=3和m=5时,运行结果如下图所示:
在这里插入图片描述

在这里插入图片描述

这里m不能超过5个,因为提供的颜色只有五个,如果在col上增加颜色的种类,则聚类数m还可以增加。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值