通过这篇文章,我们需要知道什么是聚类,了解聚类算法的应用场景,知道聚类算法的分类,了解Kmeans算法的API,动手实践Kmeans算法,能掌握K-means聚类的实现步骤,了解 SSE 聚类评估指标,了解 SC 聚类评估指标,了解 CH 聚类评估指标,了解肘方法的作用;能使用聚类算法完成客户案例分析,知道怎么求最佳K值。
一、聚类算法-概念
1.什么是聚类算法?
•根据样本之间的相似性,将样本划分到不同的类别中;不同的相似度计算方法,会得到不同的聚类结果,常用的相似度计算方法有欧式距离法。
•聚类算法的目的是在没有先验知识的情况下,自动发现数据集中的内在结构和模式。
•无监督学习算法
2.使用不同的聚类准则,产生的聚类结果不同

3.聚类算法在现实生活中的应用

二、聚类算法分类
1.根据聚类颗粒度分类

2.根据实现方法分类
•K-means:按照质心分类,主要介绍K-means,通用、普遍
•层次聚类:对数据进行逐层划分,直到达到聚类的类别个数
•DBSCAN聚类是一种基于密度的聚类算法
•谱聚类是一种基于图论的聚类算法
三、聚类算法API
sklearn.cluster.KMeans(n_clusters=8)
•参数: n_clusters:开始的聚类中心数量
整型,缺省值=8,生成的聚类数,即产生的质心(centroids)数。
•方法
estimator.fit(x)
estimator.predict(x)
estimator.fit_predict(x)
计算聚类中心并预测每个样本属于哪个类别,相当于先调用fit(x),然后再调用predict(x)
四、案例-使用KMeans模型数据探索聚类
随机创建不同二维数据集作为训练集,并结合k-means算法将其聚类,尝试分别聚类不同数量的簇,并观察聚类效果:

1.聚类步骤

"""
案例:
演示 KMeans 聚类算法 入门案例。
Kmeans简介:
它属于 无监督学习,即:有特征,无标签,根据样本间的相似性进行划分。
所谓的相似性 可以理解为 就是 距离,例如:欧式距离,曼哈顿(城市街区)距离,切比雪夫距离,闵式距离……
一般大厂,项目初期在没有 先备知识(标签)的情况下可能会用。
"""
# 导包
from sklearn.cluster import KMeans # 聚类的API,采用指定 质心 来分簇
import matplotlib.pyplot as plt # 绘图的
from sklearn.datasets import make_blobs # 默认会按照高斯分布(正态分布)生成数据集,只需要指定均值,标准差
from sklearn.metrics import calinski_harabasz_score # 评价指标,值越大,聚类效果越好。
# 1.准备数据集
x, y = make_blobs(
n_samples=1000, # 参1:样本数量
n_features=2, # 参2:样本特征数量(2列)
centers=[[-1,-1], [0,0], [1,1], [2,2]], # 参3:样本标签数量
cluster_std=[0.4,0.2,0.3,0.4], # 参4:标准差
random_state=23 # 参5:随机种子
)
# print(x)
# print(y)
# 2.绘制上述的图形
# 参1:横坐标,参2:纵坐标,参3:颜色
plt.scatter(x[:,0],x[:,1])
plt.show()
# 3.创建KMeans对象
# 参1:聚类的数量,参2:随机种子
estimator = KMeans(n_clusters=4, random_state=23)
# 4.模型训练 和 预测
y_pred = estimator.fit_predict(x) # 预测值
# 5.绘制预测结果
plt.scatter(x[:,0],x[:,1],c=y_pred)
plt.show()
# 6.评价指标
print(f'评价指标(评分):{calinski_harabasz_score(x,y_pred)}') # 越大越好
五、聚类算法****API

六、KMeans算法实现流程
1 、事先确定常数K ,常数K意味着最终的聚类类别数
2、随机选择 K 个样本点作为初始聚类中心
3、计算每个样本到 K 个中心的距离,选择最近的聚类中心点作为标记类别
4、根据每个类别中的样本点,重新计算出新的聚类中心点(平均值),如果计算得出的新中心点与原中心点一样则停止聚类,否则重新进行第 3 步过程,直到聚类中心不再变化
七、KMeans算法实现流程 -- 举例
已知数据如下表所示,按照KMeans算法实现流程进行聚类:

随机设置K个特征空间内的点作为初始的聚类中心(本案例中设置p1和p2)

2、对于其他每个点计算到K个中心的距离,选择最近的一个聚类中心点作为标记类别

3、接着对标记的聚类中心,重新计算每个聚类的新中心点(平均值)

4、如果计算得出的新中心点与原中心点一样(质心不再移动),那么结束,否则重新进行第二步过程【经过判断,需要重复上述步骤,开始新一轮迭代】

5、当每次迭代结果不变时,认为算法收敛,聚类完成

KMeans****算法实现流程-总结
1 、事先确定常数K ,常数K意味着最终的聚类类别数
2、随机选择 K 个样本点作为初始聚类中心
3、计算每个样本到 K 个中心的距离,选择最近的聚类中心点作为标记类别
4、根据每个类别中的样本点,重新计算出新的聚类中心点(平均值),如果计算得出的新中心点与原中心点一样则停止聚类,否则重新进行第 3步过程,直到聚类中心不再变化
七、误差平方和SSE (The sum of squares due to error)

SSE 越小,表示数据点越接近它们的中心,聚类效果越好
八、"肘"方法 (Elbow method) - K值确定
•"肘" 方法通过 SSE 确定 n_clusters 的值
•对于n个点的数据集,迭代计算 k from 1 to n,每次聚类完成后计算 SSE
•SSE 是会逐渐变小的,因为每个点都是它所在的簇中心本身。
•SSE 变化过程中会出现一个拐点,下降率突然变缓时即认为是最佳 n_clusters 值。
•在决定什么时候停止训练时,肘形判据同样有效,数据通常有更多的噪音,在增加分类无法带来更多回报时,我们停止增加类别。

from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
from sklearn.metrics import calinski_harabasz_score
def dm01_SSE误差平方和求模型参数():
sse_list = \[\]
#产生数据random_state*=22**固定好*x, y = make_blobs(n_samples=1000, n_features=2, centers=\[-1, -1, 0, 0, 1, 1, 2, 2],
cluster_std=0.4, 0.2, 0.2, 0.2, random_state=22)
for clu_num in range(1, 100):
my_kmeans = KMeans(n_clusters=clu_num, max_iter=100, random_state=0)
my_kmeans.fit(x)
sse_list.append(my_kmeans.inertia_ ) #获取sse**的值plt.figure(figsize=(18, 8), dpi=100)
plt.xticks(range(0, 100, 3), labels=range(0, 100, 3))
plt.grid()
plt.title('sse')
plt.plot(range(1, 100), sse_list, 'or-')
plt.show()
#通过图像可观察到n_clusters*=4sse开始下降趋缓**,最佳值4*

八、SC轮廓系数法(Silhouette Coefficient)
轮廓系数法考虑簇内的内聚程度(Cohesion),簇外的分离程度(Separation)。其计算过程如下


"""
案例:
演示聚类算法的评估指标,即:SSE + 肘部法, SC轮廓系数法, CH轮廓系数法
聚类算法的评估指标:
思路1:SSE + 肘部法
SSE:
所有簇的 所有样本到该簇的质心的 误差平方和。
特点:
随着K值的增加,SSE值会逐渐减少
目标:
SSE值越小,代表簇内样本越聚集,内聚程度越高。
肘部法:
K值增大,SSE值会随之减小,下降梯度陡然变缓的时候,那个K值,就是我们要的最佳值。
思路2:SC轮廓系数
考虑簇内 -> 聚集程度,越小越好
考虑簇外 -> 分离程度,越大越好
思路3:CH轮廓系数
考虑簇内 -> 聚集程度,越小越好
考虑簇外 -> 分离程度,越大越好
考虑k值 -> k值越小,代表簇内样本越聚集,内聚程度越高
"""
# 导包
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
from sklearn.metrics import calinski_harabasz_score, silhouette_score
# 1. 定义函数,演示:SSE + 肘部法
def dm01_sse():
# 1.定义SSE列表,记录:每个K值的 SSE值
sse_list = []
# 2.生成数据集。
x, y = make_blobs(
n_samples=1000,
n_features=2,
centers=[[-1, -1], [0, 0], [1, 1],[2,2]],
cluster_std=[0.4, 0.2, 0.2, 0.2],
random_state=23
)
# 3.for训练遍历,获取到每个K值,计算其对应的 sse值,并添加到sse_list列表中
for k in range(1,100):
# 3.1 创建KMeans对象,参1:簇的数量,参2:最大迭代数,参3:固定随机种子。
estimator = KMeans(n_clusters=k, max_iter=100, random_state=23)
# 3.2 训练模型
estimator.fit(x)
# 3.3 模型预测
# 3.4 获取到每个簇的SSE值
sse_value = estimator.inertia_
# 3.5 将每个K值对应的sse值,添加到sse_list列表中
sse_list.append(sse_value)
# 4.绘制SSE曲线 -> 数据的可视化。
# print(sse_list)
# 4.1 创建画布,指定:画布的尺寸
plt.figure(figsize=(20,10))
# 4.2 设置标题。
plt.title('SSE value')
# 4.3 设置x轴的刻度
plt.xticks(range(0, 100, 3))
# 4.4 添加x轴,y轴的标签
plt.xlabel('K')
plt.ylabel('SSE')
# 4.5 绘制网格
plt.grid(True)
# 4.6 绘制折线图。
plt.plot(range(1,100),sse_list)
plt.show()

九、聚类效果评估 -- CH轮廓系数法(Calinski-Harabasz Index)

通过图像可观察到 n_clusters=4 取到最大值; 最佳值4
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
from sklearn.metrics import calinski_harabasz_score
def dm03_ch系数():
tmp_list = \[\]
#产生数据random_state*=22**固定好*x, y = make_blobs(n_samples=1000, n_features=2, centers=\[-1, -1, 0, 0, 1, 1, 2, 2],
cluster_std=0.4, 0.2, 0.2, 0.2, random_state=22)
for clu_num in range(2, 100):
my_kmeans = KMeans(n_clusters=clu_num, max_iter=100, random_state=0)
my_kmeans.fit(x)
ret = my_kmeans.predict(x)
tmp_list.append(calinski_harabasz_score(x, ret)) *#*sc
plt.figure(figsize=(18, 8), dpi=100)
plt.xticks(range(0, 100, 3), labels=range(0, 100, 3))
plt.grid()
plt.title('ch')
plt.plot(range(2, 100), tmp_list, 'og-')
plt.show()

通过图像可观察到 n_clusters=4 取到最大值; 最佳值4
十、总结

十一、案例:顾客数据聚类分析
•已知:客户性别、年龄、年收入、消费指数
•需求:对客户进行分析,找到业务突破口,寻找黄金客户

•客户分群效果展示:

1.首先寻找"K"值
"""
案例:
基于用户的 年收入 和消费指数,根据用户的 相似性 进行 聚类
"""
import os
# 解决Windows KMeans MKL警告
os.environ["OMP_NUM_THREADS"] = "1"
# 导包
import pandas as pd
import numpy as np
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
from sklearn.metrics import calinski_harabasz_score, silhouette_score
# 1.定义函数,找 聚类的 质心数(k值)
def dm01_find_k():
# 1.加载数据集
df = pd.read_csv('./data/customers.csv')
# df.info()
# 2.定义 sse_list, sc_list, 记录:不同k值的 评估效果
sse_list = [] # sse: 只考虑簇内,越小越好
sc_list = [] # sc: 考虑 簇内和簇间,越大越好
# 抽取特征
x = df.iloc[:, 3:5]
print(x)
# y = df.iloc[:, -1]
# 3.定义for训练,测试不同k值的 评估效果
for k in range(2,20):
# 4.创建(KMeans 模型)对象。
estimator = KMeans(n_clusters=k, max_iter=100, random_state=10)
# 5.模型训练
estimator.fit(x)
# 6.模型预测
y_pred = estimator.predict(x)
# 7.分别把评分添加到对应的列表中。
sse_list.append(estimator.inertia_)
sc_list.append(silhouette_score(x,y_pred))
# 4. 绘制折线图,看看k值 哪个最好
plt.figure(figsize=(10,8))
plt.plot(range(2,20),sse_list,label='SSE')
plt.show()
plt.figure(figsize=(10, 8))
plt.plot(range(2,20),sc_list,label='Silhouette')
plt.show()
# 结论:k=5的时候,效果最好

2.模型聚类
# 2.定义函数,实现:模型训练,模型预测,模型评估
def dm02_train_predict_evaluate():
# 1.加载数据集
df = pd.read_csv('./data/customers.csv')
# 2.提取特征
x = df.iloc[:, 3:5]
# 3.创建模型
my_model = KMeans(n_clusters=5,max_iter= 100,random_state=23)
# 4.训练模型
my_model.fit(x)
# 5.模型预测
y_pred = my_model.predict(x)
# 6.绘制5个簇的 样本 -> 散点图
plt.figure(figsize=(10,8))
plt.scatter(x.values[y_pred == 0, 0], x.values[y_pred == 0, 1], label='HG') # 0号簇
plt.scatter(x.values[y_pred == 1, 0], x.values[y_pred == 1, 1]) # 1号簇
plt.scatter(x.values[y_pred == 2, 0], x.values[y_pred == 2, 1]) # 2号簇
plt.scatter(x.values[y_pred == 3, 0], x.values[y_pred == 3, 1]) # 3号簇
plt.scatter(x.values[y_pred == 4, 0], x.values[y_pred == 4, 1]) # 4号簇
# 7.绘制5个簇的 质心 -> 散点图
# print(my_model.cluster_centers_) # 5个质心的坐标
plt.scatter(my_model.cluster_centers_[:, 0], my_model.cluster_centers_[:, 1], c='black')
plt.title('Cluster of Clusters')
plt.xlabel('Annual Income (k$)')
plt.ylabel('Estimated Income (1-100)')
plt.legend()
plt.show()
# 3.测试
if __name__ == '__main__':
# dm01_find_k()
dm02_train_predict_evaluate()