洛阳市网站建设_网站建设公司_交互流畅度_seo优化
2026/1/19 6:19:01 网站建设 项目流程

Day 86:【99天精通Python】机器学习进阶 - K-Means 聚类 - 让数据自动"站队"

前言

欢迎来到第86天!

在之前的机器学习课程中,我们处理的都是有监督学习 (Supervised Learning)
这意味着我们的数据都带有标签 (Label),比如:这张图片是"猫",这个房价是"300万"。

但现实中,大量的数据是没有标签的。比如,你有一堆用户的消费记录,但你不知道他们属于哪个消费群体。
无监督学习 (Unsupervised Learning)就是要让机器在没有标签的数据中,自动发现隐藏的结构。聚类 (Clustering)是其中最常用的一种。

K-Means是最经典的聚类算法,它的目标是把数据分成 K 个簇,让同一个簇内的数据尽可能相似,不同簇之间的数据尽可能不同。

本节内容:

  • K-Means 算法原理
  • Sklearn 中的KMeans
  • 评估指标:轮廓系数 (Silhouette Score)
  • 手肘法 (Elbow Method) 确定 K 值
  • 实战练习:客户分群

一、K-Means 原理:“物以类聚,人以群分”

算法流程很简单:

  1. 初始化:随机选择 K 个点作为初始的"质心" (Centroids)。
  2. 分配 (Assignment):计算每个数据点到各个质心的距离,把它分到最近的那个簇。
  3. 更新 (Update):重新计算每个簇的平均值,将质心移动到这个平均值的位置。
  4. 重复2-3 步,直到质心不再移动。

[外链图片转存中…(img-346iHRze-1768773799828)]


二、Sklearn 实现

我们用make_blobs生成一些用于聚类的数据。

fromsklearn.datasetsimportmake_blobsfromsklearn.clusterimportKMeansimportmatplotlib.pyplotasplt# 1. 生成数据# n_samples: 样本数, centers: 簇中心数, cluster_std: 簇内标准差X,y=make_blobs(n_samples=300,centers=4,cluster_std=0.8,random_state=42)# 可视化原始数据plt.scatter(X[:,0],X[:,1],s=50)# plt.show()# 2. 创建并训练模型# n_clusters=4: 我们想分成 4 个簇kmeans=KMeans(n_clusters=4,random_state=42,n_init='auto')kmeans.fit(X)# 3. 获取结果labels=kmeans.labels_# 每个点的标签 (0, 1, 2, 3)centers=kmeans.cluster_centers_# 4 个质心的坐标# 4. 可视化结果plt.scatter(X[:,0],X[:,1],c=labels,s=50,cmap='viridis')plt.scatter(centers[:,0],centers[:,1],c='red',s=200,alpha=0.75,marker='X')plt.title("K-Means Clustering Result")# plt.show()

三、如何确定 K 值?

在实际问题中,我们事先并不知道数据应该分成几类。K-Means 的一个缺点就是需要手动指定 K 值
我们有两种常用的方法来辅助判断。

3.1 手肘法 (Elbow Method)

计算不同 K 值下的簇内平方和 (Inertia)。Inertia 越小,说明簇内越紧凑。
随着 K 增大,Inertia 肯定会减小。我们寻找那个"拐点"(手肘),即 K 再增大,Inertia 下降得不那么明显的地方。

inertia_list=[]forkinrange(1,11):kmeans=KMeans(n_clusters=k,random_state=42,n_init='auto')kmeans.fit(X)inertia_list.append(kmeans.inertia_)plt.plot(range(1,11),inertia_list,marker='o')plt.xlabel("Number of clusters (K)")plt.ylabel("Inertia")plt.title("Elbow Method For Optimal K")# plt.show()# 在图中,K=4 处是一个明显的拐点

3.2 轮廓系数 (Silhouette Score)

轮廓系数同时考虑了簇内紧凑度簇间分离度

  • 分数范围 [-1, 1]。
  • 越接近 1,聚类效果越好。
fromsklearn.metricsimportsilhouette_score score=silhouette_score(X,labels)print(f"轮廓系数:{score:.2f}")# e.g. 0.82

四、实战练习:客户分群

假设我们有一份商场客户数据,包含"年收入"和"消费分数 (1-100)"。

importpandasaspd# 1. 准备数据data={'Annual Income (k$)':[15,15,16,16,17,18],'Spending Score (1-100)':[39,81,6,77,40,6]}# (为了演示,这里只用少量数据,实际中应该是上千条)df=pd.DataFrame(data)# 2. 标准化 (距离敏感,必须标准化)fromsklearn.preprocessingimportStandardScaler scaler=StandardScaler()X_scaled=scaler.fit_transform(df)# 3. 用手肘法找 K# ... (略)# 4. 训练 (假设我们决定 K=3)kmeans=KMeans(n_clusters=3,random_state=42,n_init='auto')df['Cluster']=kmeans.fit_predict(X_scaled)# 5. 可视化plt.figure(figsize=(8,6))sns.scatterplot(data=df,x='Annual Income (k$)',y='Spending Score (1-100)',hue='Cluster',palette='viridis')plt.title("Customer Segments")# plt.show()# 6. 分析结果print(df)# 簇 0: 低收入高消费 (冲动型)# 簇 1: 低收入低消费 (保守型)# 簇 2: ...

五、常见问题

Q1:K-Means 对初始点敏感吗?

非常敏感。不同的初始质心可能导致完全不同的聚类结果。
Sklearn 的KMeans默认会跑 10 次(n_init=10),每次用不同的初始点,然后返回最好的那次结果。

Q2:数据不是圆形怎么办?

K-Means 假设簇是凸形的(类似圆形),对于不规则形状(如月牙形)效果很差。
这时候需要用其他聚类算法,如DBSCAN谱聚类 (Spectral Clustering)

Q3:如何处理分类特征?

K-Means 是基于欧式距离的,不能直接处理字符串。
需要先将分类特征进行独热编码 (One-Hot)


六、小结

无监督学习

聚类 Clustering

K-Means

1. 随机定 K 个中心
2. 分配点到最近中心
3. 更新中心到平均值

重复 2-3

如何选 K?

手肘法 (Inertia)

轮廓系数 (Silhouette)

关键要点

  1. K-Means是最简单、最常用的聚类算法。
  2. 它需要手动指定 K 值,并对数据尺度敏感(记得标准化)。
  3. 手肘法轮廓系数是确定 K 值的两大辅助工具。

七、课后作业

  1. 图片颜色聚类:读取一张彩色图片,将其像素点的 RGB 值作为特征,用 K-Means (K=8) 进行聚类。然后用每个簇的质心颜色替换该簇所有像素点,看看图片变成了什么样(主题色提取)。
  2. DBSCAN:查阅 sklearn 文档,使用DBSCAN算法处理make_moons(月牙形)数据集,并与 K-Means 的效果进行对比。
  3. 文本聚类:将一堆新闻标题进行 TF-IDF 向量化,然后用 K-Means 进行聚类,看看能否自动把"体育"、"财经"等主题分开。

下节预告

Day 87:机器学习进阶 - PCA 降维- 特征太多了怎么办?1000 个维度的特征可能只有 10 个是真正有用的。明天我们学习如何给数据"瘦身",提取核心特征。


系列导航

  • 上一篇:Day 85 - 支持向量机SVM
  • 下一篇:Day 87 - PCA降维(待更新)

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询