K-means 详细代码(2种方法,对比循环次数及用时)

目录

前言

一、K-means是什么?

二、主要思想

1. 核心思想:

2. 2个for循环:

3.实现流程:

三、代码实现

1.方法一

2.方法二

总结


前言

        通过本文您可以学到K-means的基本思想,以及2种代码实现方法!


一、K-means是什么?

        K-menas是机器学习中的一种无监督的算法,属于聚类的算法。作用是将一堆数据,按照相关的联系分为几个类别。一般用于客户分类等方面。

二、主要思想


1. 核心思想:

        核心思想其实都已经包含与算法的名字内。K是要划分的类别,means是求均值。这个俩个贯穿了整个K-means算法的核心。 

2. 2个for循环:

        整个算法是依靠2个for循环来实现的,第一个for循环的作用是将所有样本进行分类。第二个for循环的作用是聚类中心得移动。

3.实现流程:


        1.我们需要先在样本中随机生成k个聚类中心。

        2.需要考虑一下用什么数据结构来存【样本类别(k个),样本到此类中心的min距离】

        这个非常重要。

        3.开始第一个for循环。计算样本中每个点到k个聚类中心的距离,距离哪个点最小,划分

        为哪一类,并标记好距离是多少。

        4.开始第二个for循环。跟据上述步骤我们已经将所有样本分为k个类别了,现在我们要将

        每一类别的样本数据求均值。此时,我们就得到了k个新的聚类中心点。

        5.判断分类操作什么时候停止。一个是看样本类别是否变更,另一个是聚类中心点是否变更。

        6.我们将3,4,5几个步骤放到一个大的循环里面,让2个for循环一直执行,直到聚类中心停止。




三、代码实现




1.方法一

import numpy as np
import random
import copy
import time
import matplotlib.pyplot as plt

Data = np.random.rand(100,2)
def initCentroidrs(data,k):
    num = len(data)
    random.seed(66)
    index = np.random.choice(num,k,replace=False) # flase不放回抽样
    centroidrs = data[index]
    return centroidrs
c = initCentroidrs(Data,4)
iters = 300
count = 0
a = time.time()
while (iters>0):
    B = []
    iters -=1
    for i in c:
        # dis是一个列表,里面是每一个样本到聚类中心的距离。
        dis = np.sqrt(((Data-i)**2).sum(axis=1))
        # B是外侧列表[]里面放置4个dis内侧列表
        B.append(dis)
    # 矩阵化
    B = np.array(B)
    # 按列求最小值的下标,此下标即为每一个样本所属于的类别
    index = np.argmin(B,axis=0)
    c_ = copy.deepcopy(c)   # 深拷贝,复制中心点数据。
    # 第二个循环求,分好类之后,每一类样本的平均值,即为类的聚类中心点坐标。然后更新聚类中心。
    for i in range(len(c)):
        # [index==i] 返回的是【ture,false,....】长度等于样本个数。
        # 当i=0时,Data只取对应位置为ture的数据,所以Data_i为0类别所有样本的数据。
        Data_i = Data[index == i,:]
        # 对此数据按列求均值即为本类的新的聚类中心点。
        c[i] = np.mean(Data_i,axis=0)
    # 判断新的聚类中心,与上一次的聚类中心是否一致。如果一致,则不需更新聚类中心点。
    count +=1
    if (c_==c).all():
        break
b = time.time()

print('最终聚类中心')
print(c)
print('上一次循环聚类中心')
print(c_)
print('循环次数',count)
print('用时时长',b-a)

plt.scatter(c[:,0],c[:,1])
plt.scatter(Data[:,0],Data[:,1])
plt.show()


结果展示

最终聚类中心
[[0.13850262 0.26604074]
 [0.3046347  0.71009279]
 [0.66872951 0.25949051]
 [0.74085396 0.71999526]]
上一次循环聚类中心
[[0.13850262 0.26604074]
 [0.3046347  0.71009279]
 [0.66872951 0.25949051]
 [0.74085396 0.71999526]]
循环次数 9
用时时长 0.0009975433349609375

Process finished with exit code 0

2.方法二


import numpy as np
import random
import copy
import time
np.set_printoptions(suppress=True)

Data = np.random.rand(100,2)

K = 4
def dist(x1,x2):
    return np.square(sum((x1-x2)**2))
def initCentroidrs(data,k):
    num = len(data)
    random.seed(66)
    index = np.random.choice(num,k,replace=False) # flase不放回抽样
    centroidrs = data[index]
    return centroidrs
a = time.time()
def k_means(data,k):
    m,n = data.shape    # m为样本个数,n为特征个数
    class_dist = np.zeros((m,2))  # 构建一个都是0的(m,2)矩阵,第一列放类别,第二列放最小距离。
    centroidrs = initCentroidrs(data, k)
    change_center = True
    count = 0
    while change_center:
        change_center = False
        for i in range(m):   # 循环所有样本
            # 设置初始的类别,跟距离
            min_dist = np.inf    # 无限大
            class_index = 0
            # 计算第i个点到k个质心的距离,并以最小的距离将其进行归类(0到k-1类)。
            for j in range(k):
                dist_x2c = dist(data[i],centroidrs[j])
                if dist_x2c < min_dist:
                    min_dist = dist_x2c
                    class_index = int(j)
            # 判断初始设的类别与上述的分类是否一致,如果否就变更类别。(初始类别都是0)
            if class_dist[i,0] != class_index:
                class_dist[i,0] = class_index
                class_dist[i, 1] = min_dist
                change_center = True
                count +=1
        c_=copy.deepcopy(centroidrs)
        for j in range(k):
            # class_dist[:,0] == j  是bool类型[ True  True False False False False]
            data_j = data[class_dist[:,0] == j,:]  # 类别是j的所有数据
            centroidrs[j] = np.mean(data_j,axis=0)
    return centroidrs,class_dist,c_,count

# 5. 打印最终的聚类中心和每个样本所属的簇
centroidrs, class_dist,c_,count = k_means(Data,4)
b = time.time()
print('最终聚类中心')
print(centroidrs)
print('上一次循环聚类中心')
print(c_)
print('循环次数',count)
print('用时时长',b-a)

# print(class_dist)

结果展示

最终聚类中心
[[0.38176368 0.33070398]
 [0.17384564 0.69145547]
 [0.62558847 0.79347614]
 [0.79725016 0.29485955]]
上一次循环聚类中心
[[0.38176368 0.33070398]
 [0.17384564 0.69145547]
 [0.62558847 0.79347614]
 [0.79725016 0.29485955]]
循环次数 115
用时时长 0.023465871810913086



总结

        本文介绍了k-means的核心思想,基本实现流程,以及代码实现部分。欢迎大家一起学习交流!


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值