聚类算法
聚类算法简介
概述:根据样本之间的相似性,将样本划分到不同的类别中,不同的相似度计算方法,会得到不同的聚类结果
常用相似度计算方法有:欧式距离法,曼哈顿街区距离,皮尔逊相关系数 ,余弦相似度
聚类算法属于无监督学习(有特征无标签)
生活中的应用场景:
用户画像,广告推荐,搜索殷引擎的流量推荐,恶意流量识别
聚类算法分类
一.根据聚类颗粒度分类
二.根据实现方法分类:
1.K-means,按照质心分类,主要介绍K-means,通用,普遍
2.层次聚类:对数据进行逐层划分,直到达到聚类的类别个数
3.DBSCAN聚类是一种基于密度的聚类算法
4.谱聚类是一种基于图论的聚类算法
聚类算法API的使用
导包:sklearn.clustrer.KMeans sklearn.datasets.make_blobs
sklearn.cluster.KMeans(n_clusters=8) : 例如:es = KMeans(n_clusters=4,random_state=23) es.fit_predict(x)
eg:
import os
os.environ['OMP_NUM_THREADS']='4'# 必须放在第一个位置上
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs # 默认按照高斯分布(正态分布)生成数据集,只需要指定均值,标准差
from sklearn.cluster import KMeans
from sklearn.metrics import calinski_harabasz_score
# 创建数据集
# X为样本特征,Y为样本簇类别, 共1000个样本,每个样本2个特征,共4个簇,
# 簇中心在[-1,-1], [0,0],[1,1], [2,2], 簇方差分别为[0.4, 0.2, 0.2, 0.2]
# 参1 样本数量 参2 样本特征数量 参3:初始化质心
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)
# 创建1000个样本点,每个样本有2个特征
# 设置4个聚类中心:[-1,-1]、[0,0]、[1,1]、[2,2]
# 各聚类的标准差分别为0.4、0.2、0.2、0.2
# 使用随机种子9确保结果可重现
# 返回特征矩阵X和标签向量y
# 数据集可视化
# 参1 横坐标,参2 纵坐标
plt.scatter(X[:, 0], X[:, 1], marker='o')
#plt.scatter() - 绘制散点图函数
# X[:, 0] - 取数据矩阵X的第一列作为x轴坐标
# X[:, 1] - 取数据矩阵X的第二列作为y轴坐标
# marker='o' - 设置散点标记为圆形
# 用于可视化二维数据点的分布情况。
plt.show()
# 3.创建KMeans对象
# 参1 聚类数量,参2 随机种子
es = KMeans(n_clusters=4,random_state=23)
# 4预测
y_predict=es.fit_predict(X)
# 5 绘制预测结果
plt.scatter(X[:,0],X[:,1],c=y_predict)
plt.show()
# 6评估指标
print(f"评估指标:{calinski_harabasz_score(x,y_predict)}")
Kmeans实现流程(算法原理)
1.事先确定常数K,常数K意味着最终的聚类类别数
2.随机选择K个样本点作为初始聚类中心
3.计算每个样本到K个中心的距离,选择最近的聚类中心作为标记类别
4.根据每个类别中的样本点,重新计算出新的聚类中心点(平均值),如果计算出新中心点与原中心点一样则停止聚类,否则重新进行第三步过程,直到聚类中心不再变化
模型评估方法
1.SSE评估指标:(The sum of squares due to error)
误差平方和SSE
考虑簇内的内聚程度
SSE公式:
Ci表示簇,K表示聚类中心个数,p表示某个簇内的样本 m表示质心点
SSE越小越好,表示数据点越接近他们的中心,聚类效果越好
2.SC轮廓系数(Silhouette Coefficient)(最常用)
考虑簇内的内聚程度和簇外的分离程度
对计算每一个样本 i 到同簇内其他样本的平均距离 ai,该值越小,说明簇内的相似程度越大 计算每一个样本 i 到最近簇 j 内的所有样本的平均距离 bij,该值越大,说明该样本越不属于其他簇 j 根据下面公式计算该样本的轮廓系数:S = b −a/max(a, b) 计算所有样本的平均轮廓系数 轮廓系数的范围为:[-1, 1],SC值越大聚类效果越好
3.CH轮廓系数法(Calinski-Harabasz Index)
CH系数考虑簇内的内聚程度,簇外的离散程度,质心的个数
类别内部数据的距离平方和越小越好,类别之间的距离平方和越大越好。聚类的种类数越少越好
m表示样本数量,k表示质心个数
```python
def dm02_sc轮廓系数法():
# 0定义sc列表,目的每个K值的SSE值
sc_list=[]
# 1获取数据
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值,计算对应SC值,并添加到sc_list列表中
for k in range(2,100): # 考虑簇外,至少2簇
es=KMeans(n_clusters=k,max_iter=100,random_state=23)
es.fit(x)
y_pre=es.predict(x)
sc_value=silhouette_score(x,y_pre)
sc_list.append(sc_value)
# 4绘制SC曲线,--数据可视化
plt.figure(figsize=(20,10))
plt.title('sc_value')
plt.xticks(range(0,100,3))
plt.xlabel('k')
plt.ylabel('sc_value')
plt.grid()
# 注意 sc值从2开始
# 轮廓系数需要至少两个簇才能计算,因为其计算过程涉及比较样本与其所在簇的紧密度和与其他簇的分离度
# 当 n_clusters=1 时,所有样本被分到同一个簇中,无法计算轮廓系数
plt.plot(range(2,100),sc_list)
# 聚类的目的是将数据分成不同的组,只有一个簇的情况下失去了聚类的意义
# 至少需要2个簇才能体现分组的效果和评估指标的有效性
# 因此,从2开始是为了确保轮廓系数计算的可行性和聚类分析的实际意义。
plt.show()
if __name__ == '__main__':
dm02_sc轮廓系数法()
```

由此可知,最佳K=4
KMeans聚类算法注意点
数据集中是否有异常数据
异常值
特征列量纲异常 标准化 minmaxscaler standardscaler
数据集数据量
数据量大, 计算时间长
MinBatchKMeans(n_clusters=, batch_size=)
案例:顾客数据聚类分析法
已知:客户性别、年龄、年收入、消费指数 需求:对客户进行分析,找到业务突破口,寻找黄金客户
流程:先查看数据集有无空值,无,下一步
先通过dm01_find_kl寻找到最佳K值由图可知K=5,而后再用dm02_train_pre()画出聚类图
from sklearn.cluster import KMeans # 聚类KPI 采用指定 质心,分簇
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
from sklearn.metrics import calinski_harabasz_score, silhouette_score
from sklearn.metrics import silhouette_score,calinski_harabasz_score
import pandas as pd
# 1寻找最优k 给你客户数据,需要你进行评估需要分几类
def dm01_find_k():
# 1加载数据集
df=pd.read_csv('../data/customers.csv')
# 2.定义空列表,存储数据 (sse sc ) 用来记录不同K值得评估效果
sse_list=[]
sc_list=[] # 考虑簇内和簇外 越大越好
ch_list=[]
# 3.抽取特征
x=df.iloc[:,3:5]
for k in range(2,20):
es=KMeans(n_clusters=k,max_iter=100,random_state=23)
es.fit(x)
y_pre=es.predict(x)
sse_list.append(es.inertia_)
sc_list.append(silhouette_score(x,y_pre))
# ch_list.append(calinski_harabasz_score(x,y_pre))
# 4绘制折线图 sse sc,绘制两个
plt.figure(figsize=(20,10))
plt.plot(range(2,20),sse_list,'or-',label='SSE')
plt.show()
plt.figure(figsize=(20,10))
plt.plot(range(2,20),sc_list,'or-',label='SC')
plt.show()
# plt.figure(figsize=(20,10)) # k太小会看不出来,可以设置200就行
# plt.plot(range(2,20),ch_list,'or-',label="CH")
# plt.show()
def dm02_train_pre():
# 1加载数据
df=pd.read_csv('../data/customers.csv')
# 2特征提取
x=df.iloc[:,3:5]
# print(x.head())
print(x.values)
# 3模型训练
es=KMeans(n_clusters=5,max_iter=100,random_state=23)
# 4模型预测
es.fit(x)
y_pred=es.predict(x)
# 5 绘图 5个簇,样本点---散点图
# print(x.values[y_pred==4])
print('*'*23)
plt.scatter(x.values[y_pred == 0 ,0], x.values[y_pred == 0, 1])
"""
散点图取横纵坐标,横坐标为x.values[y_pred==0,0] 因为有5个簇,0-4分别代表第一个簇到第五个簇,0,0的第一个0意思是找第一个簇,第二个0是指找到第一个簇的第一列当作横坐标,纵坐标是x.values[y_pred == 0, 1] ,0,1的0代表第一个簇,1代表着第一个簇的第二列,取来做纵坐标。因为我们提取特征x的时候,就提取了两列 x=df.iloc[:,3:5],左闭右开,所以取到第三列Annual Income (k$)和第四列Spending Score (1-100)当作特征值,所以在分类后,这两个列就算是簇的第一列和第二列,
"""
plt.scatter(x.values[y_pred == 1, 0], x.values[y_pred == 1, 1])
plt.scatter(x.values[y_pred == 2, 0], x.values[y_pred == 2, 1])
plt.scatter(x.values[y_pred == 3, 0], x.values[y_pred == 3, 1])
plt.scatter(x.values[y_pred == 4, 0], x.values[y_pred == 4, 1])
# 绘制5个簇得质心
plt.scatter(es.cluster_centers_[:,0],es.cluster_centers_[:,1])
# 优化图形
plt.title('Clusters of customers ')
plt.xlabel('Annual Income(k$)')
plt.ylabel('Spending Score(1-100)')
plt.show()
if __name__ == '__main__':
dm01_find_k()
# dm02_train_pre()
由此可知,紫色是高收入高消费人群,红色是低收入高消费人群,蓝色是中收入中消费人群,绿色是低收入低消费人群,橙色是高收入低消费人群 ,红色和紫色这两个用户群体是黄金用户
更新日期:2025年9月8日