K-Means简单理解之《老王开超市》以及‘肘部法则’

本文讲解Kmeans的简单理解和小应用《老王开超市》以及肘部法则

有很多聚类方法,我们这里是最基本的Kmeans聚类

  1. 什么是Kmeans聚类,俗话讲‘物以类聚,人以群分’。数据也是如此

    与分类不同的是:聚类是无监督算法,而分类是有监督算法是带标签的。
    聚类可以简单的理解为根据数据的各个特征把一堆数据聚集为多个群体。然后针对不同群体的数据进行不同的操作。

例如
老王想要在村子里开几个个超市,那么开超市的可不单单是随便挑选位置的;
他应该考虑到每家每户到超市的距离都尽可能的小,保证村民和自己的利益最大化。

假设这个村子一个有20个房屋,他们在平面上的坐标为
[2, 5], [4, 6], [3, 1], [6, 4], [7, 2], [8, 4], [2, 3], [3, 1], [5, 7], [6, 9], [12, 16], [10, 11], [15, 19],[16, 12], [11, 15], [10, 14], [19, 11], [17, 14], [16, 11], [13, 19]
数据分布为:
村民分布

在Kmeans的思想中,需要首先给他K个聚类中心,这个是随机的。
老王由于资金短缺,所以预计只开两个超市,K就是2
然后聚类中心也就是超市的位置,就应该计算每户到超市的距离
然后将村民聚成两类
每一个村民到超市的距离就有了。我们要的就是通过反复的计算距离(我们一般用欧几里得来计算距离)
欧几里得公式
最终将村民到超市的距离计算出来,第二次循环,再次计算村民到到超市的距离,再次将村民聚为两类,通过反复循环来调优,直到聚类中心不再变换。
结果图为:
超市位置

那么我们该如何确定最优的聚类中心个数呢:
在这里讲解一下肘部法则:
为什么叫它肘部法则呢,因为它是根据聚类中心个数距离平方和所画出来的图。针对每一个聚类中心都有所对应的距离平方和,(这里的距离平方和可以理解为损失)
如图:
肘部法则图
在不同问题中考虑因素不同,在老王开超市这个问题中,我们可以看到在聚类中心越多,损失越少。在聚类中心个数为5-20个的时候,它的损失下降的很少。所以我们可以根据肘部法则来确定最优的聚类中心个数。

代码

from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
import numpy as np

from pylab import *

mpl.rcParams['font.sans-serif'] = ['SimHei']  # 画图是争取显示中文

# 20个数据
data = np.array(
    [[2, 5], [4, 6], [3, 1], [6, 4], [7, 2], [8, 4], [2, 3], [3, 1], [5, 7], [6, 9], [12, 16], [10, 11], [15, 19],
     [16, 12], [11, 15], [10, 14], [19, 11], [17, 14], [16, 11], [13, 19]])

est = KMeans(n_clusters=2)  # 创建一个kmean对象
est.fit(data)  # 训练模型

# plt.figure()
# plt.scatter(data[:, 0], data[:, 1])
# plt.show()

print('聚类中心的位置: \n', est.cluster_centers_)
print('聚类中心所属聚类中心的索引: ', est.labels_)
print('代价', est.inertia_)   # 依据距离来计算的
print(data)
# 画样本数据
plt.figure('K-mean算法', figsize=(10, 6))
plt.scatter(data[est.labels_ == 0, 0], data[est.labels_ == 0, 1])
plt.scatter(data[est.labels_ == 1, 0], data[est.labels_ == 1, 1])
# plt.plot(est.inertia_)
# plt.scatter(data[:, 0], data[:, 1])

for i in range(2):
    plt.scatter(est.cluster_centers_[i, 0], est.cluster_centers_[i, 1], marker='x')

for i in range(2):
    plt.annotate('超市'+str(i+1), xy=(est.cluster_centers_[i, 0], est.cluster_centers_[i, 1]), xytext=(4, 4), textcoords='offset points', fontsize=10)

plt.show()

m = 20
k = []  # K是聚类中心个数
inertia = []  # 用来存储聚类中心个数所对应的代价
for i in range(m):
    est = KMeans(n_clusters=i+1)
    est.fit(data)
    k.append(i+1)
    inertia.append(est.inertia_)


plt.figure('肘部法则图', figsize=(10, 6))
plt.title('代价函数图')
plt.xlabel('k值')
plt.ylabel('代价')
plt.plot(k, inertia)
plt.show()

如果有些地方写错的话,欢迎指出。谢谢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值