K-means的Python实现

K-means算法


以空间中k个点为中心进行聚类,对最靠近他们的对象归类。通过迭代的方法,逐次更新各聚类中心的值,直至得到最好的聚类结果。


kmeans.py

import random
import pandas as pd
import numpy as np


# 计算欧拉距离
def calcDis(dataSet, centroids, k):
    clalist=[]
    for data in dataSet:
        diff = np.tile(data, (k, 1)) - centroids
        squaredDiff = diff ** 2
        squaredDist = np.sum(squaredDiff, axis=1)
        distance = squaredDist ** 0.5
        clalist.append(distance)
    clalist = np.array(clalist)
    return clalist

# 计算质心
def classify(dataSet, centroids, k):
    # 计算样本到质心的距离
    clalist = calcDis(dataSet, centroids, k)

    # 分组并计算新的质心
    minDistIndices = np.argmin(clalist, axis=1)
    newCentroids = pd.DataFrame(dataSet).groupby(minDistIndices).mean()
    newCentroids = newCentroids.values

    #assert k == len(newCentroids)

    # 计算变化量
    changed = newCentroids - centroids

    return changed, newCentroids

# 使用k-means分类
def kmeans(dataSet, k):
    # 随机取质心
    centroids = random.sample(dataSet, k)

    # 更新质心 直到变化量全为0
    changed, newCentroids = classify(dataSet, centroids, k)
    while np.any(changed != 0):
        changed, newCentroids = classify(dataSet, newCentroids, k)

    centroids = sorted(newCentroids.tolist())

    # 根据质心计算每个集群
    cluster = []
    clalist = calcDis(dataSet, centroids, k)
    minDistIndices = np.argmin(clalist, axis=1)
    for i in range(k):
        cluster.append([])
    for i, j in enumerate(minDistIndices):
        cluster[j].append(dataSet[i])

    return centroids, cluster


def main():
    # 创建数据集
    def createDataSet():
        return [[1, 1], [1, 2], [2, 1], [6, 4], [6, 3], [5, 4]]

    dataset = createDataSet()
    centroids, cluster = kmeans(dataset, 3)
    print('质心为:%s' % centroids)
    print('集群为:%s' % cluster)

if __name__=='__main__':
    exit(main())

输出结果:

质心为:[[1.3333333333333333, 1.3333333333333333], [5.0, 4.0], [6.0, 3.5]]
集群为:[[[1, 1], [1, 2], [2, 1]], [[5, 4]], [[6, 4], [6, 3]]]

PS:


上面代码有个小问题:在迭代更新的过程中如果有的质心没有一个点离它最近,会有问题。
查了很多资料也不知道还怎样处理,看其他实现的代码都没注意这个问题,有知道怎么解决的希望能告诉我。

这里给个这样的例子:

数据集:[[1, 1], [1, 2], [2, 1], [4, 4], [4, 3], [3, 4]]
k = 3 并且正好随机到[1, 1], [1, 2], [2, 1]这三个。

第一次:
[[1, 1]]    [[1, 2], [3, 4], [4, 4]]    [[2, 1], [4, 3]]
质心分别为:
[1, 1]    [2.67, 3.33]    [3, 2]

第二次:
[[1, 1], [1, 2], [2, 1]]    [[3, 4], [4, 3], [4, 4]]    []
质心分别为:
[1.33, 1.33]    [3.67, 3.67]    [???]

这样有一个变成空的了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值