k_means聚类算法理论+代码实现

总体说明:

这篇文章是想简单的让大家理解一下k_means聚类的本质,和过程实现,方便后面能看懂复杂工程上的应用。要是这篇文章看懂了的话可以看看下面链接的工程应用代码实现。

K-means 聚类算法及其代码实现_Jim_Liu-CSDN博客_k-means代码

KMeans++算法理论和实现_肥宅Sean-CSDN博客

1、定义:

上图的数据可以分成两个分开的点集(称为簇),一个能够找到这些点集的算法,就被称为聚类算法。

原理:设法定出不同类别的核心或初始内核,然后依据样本与核心之间的相似性度量将样本聚集成不同的类别。

2、聚类算法的一般步骤:

S1:先定义总共有多少个类/簇(cluster)

S2:将每个簇心(cluster centers)随机定在一个点上

S3:将每个数据点关联到最近簇中心所属的簇上

S4:对于每一个簇找到其所有关联点的中心点(取每一个点坐标的平均值)

S5:将上述点变为新的簇心

S6:不停重复,直到每个簇所拥有的点不变

3、聚类算法的应用:

 在商务上,聚类能帮助市场分析人员从客户基本库中发现不同的客户群,并且用购买模式来刻画不同的客户群的特征。在生物学上,聚类能用于推导植物和动物的分类,对基因进行分类,获得对种群中固有结构的认识。聚类在地球观测数据库中相似地区的确定,汽车保险单持有者的分组,及根据房子的类型、价值和地理位置对一个城市中房屋的分组上也可以发挥作用。聚类也能用于对Web上的文档进行分类,以发现信息。诸如此类,聚类有着广泛的实际应用。

4、聚类算法的代码实现:

#题目:一共有6个点,坐标如下。将其分为两个簇,起始时,随机选两个点作为两个簇的簇心,问最后簇的所属情况
'''
    A0(1,2)
    A1(1,4)
    A2(3,1)
    A3(3,5)
    A4(5,2)
    A5(5,4)
'''
import random
import numpy as np
import torch

import math

import numpy as np
import matplotlib.pyplot as plt

COOEDINATE = [(1,2),(1,4),(3,1),(3,5),(5,2),(5,4)]

#1、随机选取一个坐标,作为簇心
# 从给定列表中生成了 n 个随机样本。
init_seed = 0
#GPU
#torch.cuda.manual_seed(init_seed)
#torch.cuda.manual_seed_all(init_seed)
torch.manual_seed(init_seed)
random.seed(init_seed)
X1,X2 =random.sample(COOEDINATE,2) 
#print(X1,X2) #(3, 5) (5, 4)

#2、将其余四个点按距离聚类
#3、计算平均值,从新选择簇心
sum0=0
sum1=0
data1 = []
data2 = []
X3 = (0,0)
X4 = (0,0)
k=0
while(1):  #当簇心不再变化时说明聚类完成
    i=0
    class1 = []
    class2 = []
    #计算距离,聚类
    for x in COOEDINATE:
        data1.append(list(x)[0])
        data1.append(list(x)[1])
        data1.append(list(X1)[0])
        data1.append(list(X1)[1])       
        result1 = math.sqrt(
            math.pow(
                data1[0+i] -
                data1[2],
                2) +
            math.pow(
                data1[1+i] -
                data1[3],
                2))

        data2.append(list(x)[0])
        data2.append(list(x)[1])
        data2.append(list(X2)[0])
        data2.append(list(X2)[1])
       
        result2 = math.sqrt(
            math.pow(
                data2[0+i] -
                data2[2],
                2) +
            math.pow(
                data2[1+i] -
                data2[3],
                2))

        #print('result1,result2:',result1,result2)

        if result1<=result2:
            class1.append(x)
        else:
            class2.append(x)
        i+=4
    for j in class1:
            sum0 += j[0]
            sum1 += j[1]
    X3 = (sum0/len(class1),sum1/len(class1))
    print('x1,x',int(list(X1)[0]),int(list(X3)[0]))
    print('y1,y',int(list(X1)[1]),int(list(X3)[1]))
    if X1 != X3:
        X1 = X3
    sum0 = 0
    sum1 = 0
    for j in class2:
            sum0 += j[0]
            sum1 += j[1]
    X4 = (sum0/len(class2),sum1/len(class2))
    print('x2,x',int(list(X2)[0]),int(list(X4)[0]))
    print('y2,y',int(list(X2)[1]),int(list(X4)[1]))
    if X2 != X4:
        X2 = X4
    elif int(list(X1)[0] == list(X3)[0]) & int(list(X1)[1] == list(X3)[1]) & int(list(X2)[0] == list(X4)[0]) & int(list(X2)[1] == list(X4)[1]):
        print("聚类完成,簇心为:",X2)
        break
    
    k+=1
    if k >= 60:
        break

print(class1)
print(class2)

#4、可视化

#!/usr/bin/env python3
from matplotlib import pyplot as plt
from matplotlib.font_manager import FontProperties  #显示中文

x_a = []
y_a = []
for i in class1:
    x_a.append(list(i)[0])
    y_a.append(list(i)[1])
x_b = []
y_b = []
for i in class2:
    x_b.append(list(i)[0])
    y_b.append(list(i)[1])
# _xticks_a=["{}类".format(i) for i in x_a]
# _xticks_b=["{}类".format(i) for i in x_b]
_xticks_a=x_a
_xticks_b=x_b

# 设置图片大小
plt.figure(figsize=(10,8),dpi=80)

# 画散点图
plt.scatter(x_a, y_a)
plt.scatter(x_b, y_b)

# x轴刻度
_xticks = _xticks_a + _xticks_b
_x = list(x_a) + list(x_b)
plt.xticks(_x,_xticks,rotation=0) # rotation:旋转显示x轴文字信息
plt.savefig("kmeans.jpg")
plt.show() #顺序一定不能弄反,不然保存会出问题(空白)

实验结果:

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

西街暖阳

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值