1504综合练习

Part A:给定数据/代码的精讲精练(共 7 题)

练习 1:“k-means 手算迭代 —— 从零开始理解算法”

🎯 目标:通过完整的手算过程,深刻理解 k-means 的每一步迭代逻辑。 📂 数据:一维数据集 {1, 2, 4, 5, 8, 9, 10},K=2,初始质心为 2 和 8。

【详细操作步骤(Step-by-Step)】

第 1 步:第一轮迭代 —— 分配(Assignment)

计算每个点到两个质心的距离(一维中距离 = |x - 质心|),将每个点分配到最近的质心。

数据点 到质心1(2)的距离 到质心2(8)的距离 归属
1 |1-2| = 1 |1-8| = 7 质心1
2 ____ ____ ____
4 ____ ____ ____
5 ____ ____ ____
8 ____ ____ ____
9 ____ ____ ____
10 ____ ____ ____

第 2 步:第一轮迭代 —— 更新(Update)

根据分配结果,重新计算每个簇的质心(取平均值)。

簇1(归属质心1的点):

  • 新质心1 = (____ + ____ + ____ + ____) / 4 = ____

簇2(归属质心2的点):、____

  • 新质心2 = (____ + ____ + ____) / 3 = ____

第 3 步:第二轮迭代 —— 分配

用新质心重新分配所有点。

数据点 到新质心1(___)的距离 到新质心2(___)的距离 归属
1 ____ ____ ____
2 ____ ____ ____
4 ____ ____ ____
5 ____ ____ ____
8 ____ ____ ____
9 ____ ____ ____
10 ____ ____ ____

第 4 步:第二轮迭代 —— 更新

重新计算质心:

  • 新质心1 = (____ + ____ + ____) / 3 = ____
  • 新质心2 = (____ + ____ + ____ + ____) / 4 = ____

第 5 步:判断收敛

比较两轮质心:

  • 质心1:第1轮 ____ → 第2轮 (是否变化?__)
  • 质心2:第1轮 ____ → 第2轮 (是否变化?__)

结论:质心____(继续变化 / 已稳定),算法____(需要继续迭代 / 已收敛)。

第 6 步:最终聚类结果

  • 簇1:{____, ____, ____},质心 = ____
  • 簇2:{____, ____, ____, ____},质心 = ____

练习 2:“二维平面手算 k-means —— 直观理解质心移动”

🎯 目标:在二维平面上手算并可视化 k-means 的迭代过程。 📂 数据:5 个二维点:A(0,0), B(1,2), C(3,1), D(5,4), E(6,3),K=2,初始质心为 A(0,0) 和 D(5,4)。

【详细操作步骤(Step-by-Step)】

第 1 步:在坐标纸上描点

在提供的网格坐标纸上标出 A、B、C、D、E 五个点,用不同颜色标记初始质心 A 和 D(用 ⭐ 标记)。

第 2 步:第一轮迭代 —— 分配

使用欧氏距离公式 d = √[(x₁-x₂)² + (y₁-y₂)²] 完成下表(距离保留两位小数):

样本 到质心1 A(0,0) 的距离 到质心2 D(5,4) 的距离 归属
A(0,0) 0 √[(0-5)²+(0-4)²] = √41 ≈ 6.40 质心1
B(1,2) √[(1-0)²+(2-0)²] = √5 ≈ 2.24 √[(1-5)²+(2-4)²] = √20 ≈ 4.47 ____
C(3,1) ____ ____ ____
D(5,4) ____ 0 质心2
E(6,3) ____ ____ ____

第 3 步:第一轮迭代 —— 更新

簇1(归属质心1的点):、____

  • 新质心1 = ((++)/3, (++)/3) = (____, ____)

簇2(归属质心2的点):

  • 新质心2 = ((+)/2, (+)/2) = (____, ____)

第 4 步:在坐标纸上标出新质心

用 ▲ 标记新质心1 和 新质心2,用箭头标出质心移动的方向。

第 5 步:第二轮迭代 —— 分配

样本 到新质心1 (,) 的距离 到新质心2 (,) 的距离 归属
A(0,0) ____ ____ ____
B(1,2) ____ ____ ____
C(3,1) ____ ____ ____
D(5,4) ____ ____ ____
E(6,3) ____ ____ ____

第 6 步:判断是否收敛

本轮分配结果与上一轮是否相同?______

如果相同,算法收敛。最终聚类为:

  • 簇1:{____, ____, ____}
  • 簇2:{____, ____}

练习 3:“sklearn KMeans —— 第一段完整聚类代码”

🎯 目标:在 Jupyter 中运行第一段完整的 KMeans 聚类代码,熟悉 API 和基本流程。 📂 数据:使用 sklearn.datasets.make_blobs 生成测试数据。

【详细操作步骤(Step-by-Step)】

第 1 步:导入必要的库

1import numpy as np
2import matplotlib.pyplot as plt
3from sklearn.datasets import make_blobs
4from sklearn.cluster import KMeans

第 2 步:生成测试数据

 1# 生成 300 个样本,4 个簇,2 个特征(便于可视化)
 2X, y_true = make_blobs(n_samples=300, centers=4, 
 3                       cluster_std=0.8, random_state=42)
 4print(f"数据形状:{X.shape}")  # 应该输出 (300, 2)
 5
 6# 可视化原始数据(无标签)
 7plt.figure(figsize=(6, 5))
 8plt.scatter(X[:, 0], X[:, 1], s=30, alpha=0.7)
 9plt.title('原始数据(无标签)')
10plt.grid(True)
11plt.show()

第 3 步:创建并训练 KMeans 模型

 1# 创建模型:K=4,固定随机种子保证结果可复现
 2kmeans = KMeans(n_clusters=4, random_state=42)
 3kmeans.fit(X)  # 训练模型
 4
 5# 获取聚类结果
 6labels = kmeans.labels_          # 每个样本的簇标签(0, 1, 2, 3)
 7centroids = kmeans.cluster_centers_  # 质心坐标(4 × 2)
 8inertia = kmeans.inertia_        # WCSS 值
 9
10print(f"簇标签(前10个):{labels[:10]}")
11print(f"质心坐标:\n{centroids}")
12print(f"WCSS (inertia):{inertia:.2f}")

第 4 步:可视化聚类结果

 1plt.figure(figsize=(8, 6))
 2# 用不同颜色显示不同簇
 3plt.scatter(X[:, 0], X[:, 1], c=labels, cmap='viridis', s=30, alpha=0.7)
 4# 用红色 X 标记质心
 5plt.scatter(centroids[:, 0], centroids[:, 1], 
 6            c='red', marker='X', s=200, linewidths=3, 
 7            edgecolors='black', label='质心')
 8plt.title('KMeans 聚类结果 (K=4)')
 9plt.legend()
10plt.grid(True)
11plt.show()

第 5 步:回答以下问题

  1. kmeans.labels_ 中存储的是什么?取值范围是多少?
  2. kmeans.cluster_centers_ 的 shape 是什么?(____, ____)
  3. 如果修改 random_state 的值,聚类结果会变化吗?为什么?
  4. inertia_ 值的含义是______,这个值越小代表______。

练习 4:“手肘法 —— 科学选择 K 值”

🎯 目标:通过绘制手肘图,掌握选择最优 K 值的标准方法。 📂 数据:使用 make_blobs 生成含有真实 4 个簇的数据(centers=4)。

【详细操作步骤(Step-by-Step)】

第 1 步:生成数据

1from sklearn.datasets import make_blobs
2from sklearn.cluster import KMeans
3import matplotlib.pyplot as plt
4
5X, _ = make_blobs(n_samples=400, centers=4, cluster_std=0.6, random_state=42)

第 2 步:对 K=1 到 10 分别训练模型,记录 inertia

1inertia_list = []
2K_range = range(1, 11)
3
4for k in K_range:
5    kmeans = KMeans(n_clusters=k, random_state=42)
6    kmeans.fit(X)
7    inertia_list.append(kmeans.inertia_)
8    print(f"K={k}: inertia={kmeans.inertia_:.2f}")

第 3 步:绘制手肘图

1plt.figure(figsize=(8, 5))
2plt.plot(K_range, inertia_list, 'bo-', linewidth=2, markersize=8)
3plt.xlabel('K 值(聚类个数)', fontsize=12)
4plt.ylabel('WCSS(簇内平方和)', fontsize=12)
5plt.title('手肘法确定最优 K 值', fontsize=14)
6plt.grid(True, alpha=0.3)
7plt.xticks(K_range)
8plt.show()

第 4 步:分析手肘图

将你的观察结果填入下表:

K 值 inertia 下降幅度(相比前一K)
1 ____
2 ____ ____
3 ____ ____
4 ____ ____(肘点)
5 ____ ____
6 ____ ____

第 5 步:回答以下问题

  1. 根据手肘图,你认为最优 K 值是____,因为______。
  2. 这个最优 K 值与数据生成时设置的 centers=4 是否一致?____
  3. 如果 K 继续增加到 10,inertia 是否会继续下降?____ 这种情况下,为什么不能选 K=10?
  4. 手肘法的“主观性”体现在哪里?______

练习 5:【独立实战】“随机初始化对 KMeans 的影响”

🎯 目标:通过实验验证 KMeans 对初始质心的敏感性,理解 n_init 的作用。 📂 数据:使用 make_blobs 生成 3 个簇的数据,但数据分布较复杂(cluster_std=2.0,簇间有重叠)。

任务要求

  1. 生成数据make_blobs(n_samples=300, centers=3, cluster_std=2.0, random_state=42)

  2. 固定 n_init=1,使用 random_state=0, 10, 20, 30, 40, 50 分别训练 6 个模型,记录每个模型的 inertia_ 和聚类结果(labels_)。

  3. 观察差异

    • 6 个模型的 inertia 是否相同?最大值与最小值相差多少?
    • 绘制其中 inertia 最大和最小两个模型的聚类结果对比图(并排),观察差异。
  4. 设置 n_init=50,重复上述实验,观察 inertia 是否趋于稳定。

  5. 提交物

    • 一份表格,包含 6 个 random_state 对应的 inertia 值。
    • 两张并排的聚类结果对比图。
    • 用 50 字以内的文字总结 n_init 参数的作用。

练习 6:【独立实战】“数据标准化对 KMeans 的影响”

🎯 目标:理解特征尺度差异对基于距离的聚类算法的影响。 📂 数据:自行构造包含两个尺度差异较大的特征的数据。

任务要求

  1. 自行构造数据

    1import numpy as np
    2from sklearn.datasets import make_blobs
    3X, _ = make_blobs(n_samples=200, centers=3, random_state=42)
    4# 人为放大第2个特征(放大100倍)
    5X[:, 1] = X[:, 1] * 100
  2. 分别对原始数据和标准化后的数据执行 KMeans 聚类(K=3,固定 random_state):

    1from sklearn.preprocessing import StandardScaler
    2scaler = StandardScaler()
    3X_scaled = scaler.fit_transform(X)
  3. 并排可视化:在同一行展示两个聚类结果(原始数据 vs 标准化数据),观察差异。

  4. 分析

    • 原始数据的聚类结果中,第 2 个特征是否主导了距离计算?为什么?
    • 标准化后,聚类结果是否更加合理?
    • 写出 100 字以内的结论。

练习 7:【独立实战】“层次聚类与树状图分析”

🎯 目标:使用层次聚类并学会解读树状图(Dendrogram)。 📂 数据:使用 make_blobs 生成 50 个样本、3 个簇的数据。

任务要求

  1. 生成数据make_blobs(n_samples=50, centers=3, cluster_std=0.5, random_state=42)

  2. 使用层次聚类AgglomerativeClustering,K=3):

    • 训练模型并可视化聚类结果(散点图不同颜色标记不同簇)。
  3. 绘制树状图

    1from scipy.cluster.hierarchy import dendrogram, linkage
    2linkage_matrix = linkage(X, method='ward')
    3plt.figure(figsize=(12, 5))
    4dendrogram(linkage_matrix)
    5plt.axhline(y=3, color='r', linestyle='--', label='切断线')
    6plt.legend()
    7plt.show()
  4. 分析树状图

    • 在纵轴 y=3 处画一条水平线,这条线与几条垂直线相交?答案:____ 条(这对应 K=____)。
    • 如果希望在 y=2 处切断,会得到几个簇?____
    • 观察树状图的“高度”差异,哪些样本被最先合并?这些样本有什么共同特点?
  5. 回答:层次聚类相比 KMeans 的主要优势是什么?主要劣势是什么?

Part B:不给定数据集的开放设计挑战(共 3 题)

练习 8:【造数据挑战】“客户分群 —— 从业务需求到聚类方案”

背景:某连锁超市的会员系统记录了 5000 名会员的消费数据,包含以下特征:年消费金额(元)、月均到店次数、平均客单价(元)、会员年限(年)。市场部希望将会员分为若干群体,以便制定精准营销策略。

任务要求

  1. 自行生成模拟数据

    • 使用 make_blobs 生成 5000 个样本、4 个特征。
    • 为了模拟真实情况,不同簇的样本数量应不均衡(如一个簇是大客户群体,数量较少;另一个簇是普通客户群体,数量较多)。提示:使用 make_blobscluster_std 和随机抽样来控制。
  2. 数据预处理

    • 四个特征的量纲不同(消费金额 vs 次数 vs 客单价 vs 年限),需要用 StandardScaler 进行标准化。
  3. 确定 K 值

    • 使用手肘法(K=1 到 15)确定最优 K 值。
    • 保存手肘图,标注出你选择的 K 值。
  4. 聚类与解读

    • 对标准化后的数据进行 KMeans 聚类(使用你选择的 K 值)。
    • 对每个簇,计算四个特征的均值,填写下表:
簇编号 样本数 平均年消费 平均到店次数 平均客单价 平均会员年限 业务解读
0 ____ ____ ____ ____ ____ ______
1 ____ ____ ____ ____ ____ ______
2 ____ ____ ____ ____ ____ ______
  1. 业务建议(100 字以内):
    • 针对每个客户群体,提出一条营销策略建议。

练习 9:【综合设计挑战】“形状挑战 —— KMeans vs DBSCAN 对比实验”

背景:某地理信息系统需要识别卫星图像中的“热点区域”——即点状分布密度较高的地区。数据呈现不规则的形状(可能包含月牙形、环形等),且存在大量噪声点。

任务要求

  1. 生成三种不同形状的测试数据

    • 数据集 A(球形簇)make_blobs,3 个球形簇。
    • 数据集 B(月牙形)make_moons,2 个月牙形簇。
    • 数据集 C(环形)make_circles,1 个内圈 + 1 个外圈。
    • 每个数据集大小 300 个样本,添加少量噪声。
  2. 分别用 KMeans 和 DBSCAN 对每个数据集进行聚类(共 6 次实验)。

  3. 可视化对比

    • 在 2×3 的网格中展示所有结果(行 = 数据集,列 = 算法)。
    • 每个子图标注算法名称和使用的参数。
  4. 性能统计

    • 对每个实验,记录:聚类数、噪声点数(DBSCAN 中标记为 -1 的数量)。
    • 填写下表:
数据集 算法 聚类数 噪声点数 效果评价(好/一般/差)
A(球形) KMeans ____ ____
A(球形) DBSCAN ____ ____ ____
B(月牙形) KMeans ____ ____
B(月牙形) DBSCAN ____ ____ ____
C(环形) KMeans ____ ____
C(环形) DBSCAN ____ ____ ____
  1. 结论(100 字以内):
    • KMeans 在哪种形状的数据上表现最好?在哪种形状上表现最差?
    • DBSCAN 的优势是什么?它的主要缺点是什么?
    • 如果这是一个实际项目,你会选择哪个算法?为什么?

练习 10:【综合设计挑战】“甲方需求 —— 电商商品自动归类系统”

背景:某电商平台有大量未分类的商品,需要根据商品的属性数据(数值型特征)自动将其归入若干类别,以改善用户体验和搜索效率。由于平台商品品类多样、新品不断涌现,甲方要求系统必须能够自动发现“合理”的类别数,并能够识别“异常商品”(即不属于任何主流类别的商品)。

【甲方需求书】

项目 内容
数据情况 公司提供 10000 条商品记录,包含 10 个数值型特征(如价格、销量、评分、重量、尺寸等)。
核心要求 不需要预先指定类别数(系统应自动发现合理分组);② 必须能够自动识别异常商品(如数据录入错误或极少数特殊品类);③ 结果需要可解释(业务人员需要看到每个类别的典型特征)。
硬性约束 ① 算法运行时间不能超过 5 分钟(在普通服务器上);② 各类别至少包含 50 个商品(拒绝碎片化的小簇)。
交付物 ① 每个类别的中心点(质心)及各维度的平均特征值;② 异常商品列表及异常原因;③ 聚类方法的选择理由。

任务要求

  1. 自行生成模拟数据

    • 使用 make_blobs + 额外噪声点生成 10000 个样本、10 个特征的数据。
    • 设置 5-8 个簇(真实簇),并额外添加 100-200 个随机噪声点(模拟异常商品)。
    • 不同簇的样本数量应不均衡(有的簇大、有的簇小)。
  2. 数据预处理

    • 10 个特征的量纲可能不同,使用 StandardScaler 标准化。
  3. 方法选型

    • 根据甲方需求,从 KMeans、层次聚类、DBSCAN 中选择最合适的算法(或算法组合)。
    • 必须明确说明:选了谁,放弃了谁,为什么(尤其要回答“如何满足‘不需要预设 K 值’和‘识别异常商品’两条需求”)。
  4. 实现与调参

    • 按照选型方案实现聚类。
    • 如果使用 DBSCAN,需要说明如何选择 epsmin_samples(可以结合 k-distance 图或经验法则)。
    • 如果使用层次聚类,需要说明如何从树状图确定 K 值。
  5. 交付物

    • 每个类别的中心点及 10 个特征的平均值(表格形式)。
    • 异常商品的数量及特征分布(与正常商品的对比)。
    • 聚类结果的可视化(由于维度为 10,可使用 PCA 降维到 2D 展示)。
    • 一份 200 字以内的“方法选型论证报告”。
  6. 扩展挑战(加分项)

    • 如果数据中某些簇的密度差异较大(有的密集、有的稀疏),DBSCAN 的固定 eps 参数可能失效。你有什么改进思路?简要说明。

📌 教师使用指南

练习题 难度 建议课时 对应教案 带步骤
练习 1 ★★☆ 0.5 课时 15.1(原理) ✅ 是
练习 2 ★★☆ 0.5 课时 15.1(原理) ✅ 是
练习 3 ★☆☆ 0.5 课时 15.2(代码) ✅ 是
练习 4 ★★☆ 0.5 课时 15.2(手肘法) ✅ 是
练习 5 ★★★ 1 课时 15.2(初始化) ❌ 否
练习 6 ★★☆ 0.5 课时 15.2(标准化) ❌ 否
练习 7 ★★☆ 0.5 课时 15.3(层次聚类) ❌ 否
练习 8 ★★★ 1.5 课时 15.1-15.2(综合) ❌ 否
练习 9 ★★★★ 1.5 课时 15.2-15.3(对比) ❌ 否
练习 10 ★★★★ 2 课时 全章(综合+选型) ❌ 否

建议

  • 练习 1-2 作为 课堂随堂练习(第一次课后布置)。
  • 练习 3-4 作为 课后作业(第二次课后布置)。
  • 练习 5-7 作为 实训课任务(第三次课的前半段)。
  • 练习 8-10 作为 项目/期末考核选题(3 选 1,建议 2 人一组完成)。

参考答案要点(供教师参考):

  • 练习 1:最终簇1={1,2,4,5}质心=3,簇2={8,9,10}质心=9。
  • 练习 2:最终簇1={A,B,C}质心≈(1.33,1),簇2={D,E}质心=(5.5,3.5)。
  • 练习 3random_state 改变会导致初始质心不同,可能影响结果。inertia_ 值越小说明簇内越紧凑。
  • 练习 4:手肘点通常在真实 K=4 处出现,K 继续增大 inertia 持续下降但边际收益递减。
  • 练习 6:原始数据中第2个特征主导距离计算,聚类结果可能不合理;标准化后两特征权重平衡。
  • 练习 7:纵轴切断线越高(合并距离越大),得到的簇数越少。
  • 练习 9:KMeans 对球形簇效果好,对月牙形/环形效果差;DBSCAN 能处理任意形状但需调 eps。
  • 练习 10:建议方案为 DBSCAN(自动识别噪声 + 无需预设 K),或先 DBSCAN 去噪再用层次聚类确定细分簇。