Python实战:KMeans聚类 + DBSCAN密度聚类完整案例(轮廓系数评估+数据标准化详解)
目录
一、前言
聚类属于无监督学习,无需标签即可自动对数据进行分组,日常数据分析中最常用两种算法:KMeans划分式聚类、DBSCAN密度聚类。
本文基于啤酒数据集,从零实现两大聚类案例,同时讲解:
-
轮廓系数silhouette_score怎么评估聚类效果
-
循环遍历K值,绘制折线图寻找最优聚类数
-
为什么DBSCAN必须做数据标准化StandardScaler
-
新手代码高频报错点逐行解析
二、数据集说明
数据集:data.txt,以空格分隔,包含4个特征:热量(calories)、钠含量(sodium)、酒精浓度(alcohol)、单价(cost),无分类标签,适合无监督聚类练习。
三、案例一:KMeans聚类 + 轮廓系数选最优K值
3.1 完整可运行代码
import pandas as pd
from sklearn.cluster import KMeans
from sklearn import metrics
# 1.读取数据集
beer=pd.read_csv('data.txt',sep=' ',encoding='utf8',engine='python')
print(beer.head())
# 2.提取聚类所需特征列
X=beer[["calories","sodium","alcohol","cost"]]
# 3.创建空列表存储不同K值对应的轮廓系数
scores=[]
# 4.循环遍历K=2~9,计算每一个聚类数的得分
for k in range(2,10):
# 训练KMeans模型,获取每一样本的聚类标签
labels=KMeans(n_clusters=k).fit(X).labels_
# 计算轮廓系数,评估当前聚类效果
score=metrics.silhouette_score(X,labels)
scores.append(score)
# 打印所有K值对应的分数
print(scores)
# 5.绘制折线图,直观查看最优K值
import matplotlib.pyplot as plt
plt.plot(list(range(2,10)),scores)
plt.xlabel("Number of Clusters Initialized")
plt.ylabel('Silhouette Score')
plt.title("不同聚类数下轮廓系数变化曲线")
plt.show()
# 6.根据图像选择最优K=2,正式训练模型
km=KMeans(n_clusters=2).fit(X)
# 将聚类结果存入原数据表
beer['cluster']=km.labels_
# 计算最优K下最终轮廓系数
score=metrics.silhouette_score(X,beer.cluster)
print("KMeans最终轮廓系数:",score)
3.2 代码逐行通俗讲解(新手必看)
1)文件读取参数说明
-
sep=' ':文件以空格作为分隔符
-
encoding='utf8':文件编码为utf-8,避免中文乱码
-
engine='python':切换python解析引擎,适配不规则空格分隔,避免读取报错
2)核心代码解析
-
range(2,10):KMeans聚类数遍历2-9,不建议K=1,单簇无评估意义 -
KMeans(n_clusters=k).fit(X).labels_:链式写法,一步完成模型创建、训练、获取聚类标签;labels_带下划线,是训练后生成的属性,不能加括号 -
metrics.silhouette_score(X,labels):轮廓系数,取值[-1,1],分数越接近1,聚类效果越好 -
画图逻辑:X轴为聚类个数K,Y轴为轮廓系数,折线最高点对应的K就是最优聚类数
3.3 新手高频问题解答
-
为什么每次运行图片和分数都不一样? KMeans初始聚类中心是随机选取的,每次训练结果不同;添加参数
random_state=123即可固定随机种子,结果永久不变。 -
为什么取多列必须双层中括号? 单层括号取单列返回Series,双层中括号取多列返回DataFrame,聚类模型只能接收二维表格数据。
四、案例二:DBSCAN密度聚类 + 数据标准化
4.1 完整可运行代码
import pandas as pd
from sklearn.preprocessing import StandardScaler
from sklearn.cluster import DBSCAN
from sklearn import metrics
# 读取数据集
beer=pd.read_table('data.txt',sep=' ',encoding='utf8',engine='python')
print(beer.head())
# 提取特征
X=beer[["calories","sodium","alcohol","cost"]]
# 1.初始化标准化工具
scaler=StandardScaler()
# 2.拟合并转换数据:均值归一为0,标准差归一为1
X_scaled=scaler.fit_transform(X)
# 训练DBSCAN密度聚类
# eps:邻域半径;min_samples:核心点最小样本数
db=DBSCAN(eps=1.5,min_samples=2).fit(X_scaled)
# 获取聚类标签
labels=db.labels_
# 将聚类结果存入原数据
beer['cluster_db']=labels
# 排序查看聚类结果(-1代表噪声点)
print(beer.sort_values('cluster_db'))
# 计算DBSCAN轮廓系数
score=metrics.silhouette_score(X_scaled,beer.cluster_db)
print("DBSCAN最终轮廓系数:",score)
4.2 关键知识点:为什么DBSCAN一定要标准化?
原始数据四个特征量级差距极大:
-
热量calories:数值100+
-
酒精alcohol:数值0-10
-
单价cost:数值0-5
DBSCAN基于样本距离聚类,量级大的特征会直接主导距离计算,导致聚类完全失效。
StandardScaler标准化作用:将所有特征统一缩放为均值0、方差1,消除量纲影响,保证聚类公平性。
4.3 DBSCAN参数说明
-
eps:邻域半径,搜索周边样本的距离范围
-
min_samples:一个点成为核心点最少需要的样本数量
-
标签-1:代表离群噪声点,是DBSCAN独有优势,可自动识别异常值
五、KMeans vs DBSCAN 两大聚类算法对比
|
对比维度 |
KMeans |
DBSCAN |
|---|---|---|
|
是否需要提前指定聚类数 |
需要,需结合轮廓系数选K |
不需要,自动根据密度分组 |
|
是否识别噪声点 |
不能,强制所有样本分组 |
可以,自动标记离群值(-1) |
|
数据要求 |
适合球形簇,可不用标准化 |
必须标准化,对距离极度敏感 |
|
适用场景 |
数据分布规则、已知大致分类数 |
数据形状不规则、需要剔除异常值 |
六、全文核心知识点总结(背诵即可)
-
轮廓系数silhouette_score:通用聚类评估指标,越大聚类效果越好,所有无监督聚类都可以用它打分
-
sklearn模型属性:训练后生成的结果都带下划线,如labels_,不能写labels/labels()
-
标准化流程:scaler=StandardScaler() → X_scaled = scaler.fit_transform(X),距离类聚类算法必加
-
代码区别:KMeans需要手动找最优K;DBSCAN依靠密度自动聚类,自带异常检测
七、补充优化代码(固定随机种子,结果永久不变)
给KMeans添加random_state,解决每次运行结果不一致问题:
labels=KMeans(n_clusters=k,random_state=123).fit(X).labels_
km=KMeans(n_clusters=2,random_state=123).fit(X)
八、结语
本文完整复现了课堂/作业常用的两大聚类代码,覆盖数据读取、特征筛选、模型训练、效果评估、可视化全流程,适合Python机器学习新手入门,后续可以结合手肘法同时评估KMeans,进一步提升聚类准确性。
欢迎点赞收藏,有聚类相关报错可以评论区交流~
更多推荐

所有评论(0)