11-3 几何与空间距离(三):综合实战——KNN 与 LDA 对比实验

🎯 教学目标与重难点…

【三维目标】

  • 📚 知识目标
    1. 巩固 KNN 和 LDA 的核心原理与代码实现。
    2. 掌握完整机器学习项目的标准流程:数据加载 → 预处理 → 降维 → 建模 → 评估
    3. 理解不同算法在同一数据集上的表现差异及其原因。
  • ⚙️ 能力目标
    1. 能独立完成从数据加载到模型对比的完整实验。
    2. 能根据评估结果(准确率、训练时间)选择更优模型。
    3. 能用可视化图表(降维散点图)解释模型效果差异。
  • 💡 素养目标
    1. 建立“没有最好的算法,只有最适合的算法”的工程认知。
    2. 强化“对比实验”意识——基于数据评估结果选择模型。

【重点与难点】

  • 🟢 教学重点
    1. 完整流程的代码实现(本节课的核心产出)。
    2. KNN、LDA、PCA 三种方法在同数据集上的对比分析。
  • 🟡 教学难点
    1. 理解 LDA 降维后 KNN 准确率提升的原因(去除了噪声和冗余特征)。
    2. 理解 PCA 和 LDA 降维后 KNN 表现差异的原因(有监督 vs 无监督)。

📌 一、 课程导入(5 分钟)

复习前两课时内容

  • 第一课时:KNN 算法——基于距离投票的分类方法,对特征尺度敏感。
  • 第二课时:LDA 算法——有监督降维方法,目标是类间距离大、类内距离小。

本课任务: 使用葡萄酒数据集(Wine Dataset),设计一组对比实验,评估以下五种方案在分类任务上的表现:

序号 方案名称 策略描述
1 原始 KNN 直接使用原始 13 个特征 + KNN
2 标准化 KNN 标准化处理后 + KNN
3 PCA + KNN PCA 降维到 2 维 + KNN
4 LDA + KNN LDA 降维到 2 维 + KNN
5 LDA 分类器 LDA 直接作为分类器

数据集简介

  • 来源:意大利同一地区三种不同品种的葡萄酒。
  • 特征数量:13 个化学特征(酒精、苹果酸、灰分、镁含量等)。
  • 样本数量:178 条。
  • 目标变量:3 个类别(三种葡萄品种)。

实验目的:通过对比五种方案的准确率,验证以下假设:

  1. 标准化对 KNN 的影响程度。
  2. 有监督降维(LDA)与无监督降维(PCA)在分类任务上的效果差异。
  3. 降维后使用 KNN 与直接使用 LDA 分类器的效果对比。
  • 👨‍🏫 教师活动
    1. 介绍葡萄酒数据集的基本信息。
    2. 展示五种实验方案的对比表格。
    3. 要求学生观察实验过程中各方案的准确率变化,并记录最终排名。
  • 🧑‍🎓 学生活动
    1. 听讲并记录实验方案的对比表格。
    2. 对五种方案的优劣做出初步猜测,作为实验验证的参照。

本环节的教学目标为:通过引入一个经典多分类数据集,建立对比实验的框架,使学生带着明确的问题进入代码实践环节。

💻 二、 解决问题过程:完整实战代码(逐步拆解)

准备工作:导入库和加载数据

 1import numpy as np
 2import matplotlib.pyplot as plt
 3from sklearn.datasets import load_wine
 4from sklearn.model_selection import train_test_split
 5from sklearn.preprocessing import StandardScaler
 6from sklearn.decomposition import PCA
 7from sklearn.discriminant_analysis import LinearDiscriminantAnalysis as LDA
 8from sklearn.neighbors import KNeighborsClassifier
 9from sklearn.metrics import accuracy_score
10
11# 加载数据
12X, y = load_wine(return_X_y=True)
13print(f"数据集形状: {X.shape}")  # (178, 13)
14print(f"类别数: {len(np.unique(y))}")  # 3
15
16# 划分训练集和测试集
17X_train, X_test, y_train, y_test = train_test_split(
18    X, y, test_size=0.3, random_state=42
19)

方案 1:原始 KNN(无标准化)

1knn_raw = KNeighborsClassifier(n_neighbors=5)
2knn_raw.fit(X_train, y_train)
3y_pred_raw = knn_raw.predict(X_test)
4acc_raw = accuracy_score(y_test, y_pred_raw)
5print(f"方案 1 (原始 KNN) 准确率: {acc_raw:.4f}")

方案 2:标准化 + KNN

1scaler = StandardScaler()
2X_train_scaled = scaler.fit_transform(X_train)
3X_test_scaled = scaler.transform(X_test)
4
5knn_std = KNeighborsClassifier(n_neighbors=5)
6knn_std.fit(X_train_scaled, y_train)
7y_pred_std = knn_std.predict(X_test_scaled)
8acc_std = accuracy_score(y_test, y_pred_std)
9print(f"方案 2 (标准化 KNN) 准确率: {acc_std:.4f}")

方案 3:PCA 降维 + KNN

 1pca = PCA(n_components=2)
 2X_train_pca = pca.fit_transform(X_train_scaled)
 3X_test_pca = pca.transform(X_test_scaled)
 4
 5knn_pca = KNeighborsClassifier(n_neighbors=5)
 6knn_pca.fit(X_train_pca, y_train)
 7y_pred_pca = knn_pca.predict(X_test_pca)
 8acc_pca = accuracy_score(y_test, y_pred_pca)
 9print(f"方案 3 (PCA + KNN) 准确率: {acc_pca:.4f}")
10print(f"PCA 保留方差比例: {pca.explained_variance_ratio_.sum():.4f}")

方案 4:LDA 降维 + KNN

1lda = LDA(n_components=2)
2X_train_lda = lda.fit_transform(X_train_scaled, y_train)
3X_test_lda = lda.transform(X_test_scaled)
4
5knn_lda = KNeighborsClassifier(n_neighbors=5)
6knn_lda.fit(X_train_lda, y_train)
7y_pred_lda = knn_lda.predict(X_test_lda)
8acc_lda = accuracy_score(y_test, y_pred_lda)
9print(f"方案 4 (LDA + KNN) 准确率: {acc_lda:.4f}")

方案 5:LDA 直接分类

1lda_clf = LDA()
2lda_clf.fit(X_train_scaled, y_train)
3acc_lda_clf = lda_clf.score(X_test_scaled, y_test)
4print(f"方案 5 (LDA 分类器) 准确率: {acc_lda_clf:.4f}")

实验结果汇总

 1results = {
 2    '原始 KNN': acc_raw,
 3    '标准化 KNN': acc_std,
 4    'PCA + KNN': acc_pca,
 5    'LDA + KNN': acc_lda,
 6    'LDA 分类器': acc_lda_clf
 7}
 8
 9print("\n" + "="*50)
10print("实验结果汇总(按准确率降序排列)")
11print("="*50)
12sorted_results = sorted(results.items(), key=lambda x: x[1], reverse=True)
13for i, (name, score) in enumerate(sorted_results, 1):
14    print(f"{i}. {name}: {score:.4f}")

PCA 与 LDA 降维效果可视化对比

 1fig, axes = plt.subplots(1, 2, figsize=(14, 5))
 2
 3# PCA 降维散点图
 4axes[0].scatter(X_train_pca[:, 0], X_train_pca[:, 1], c=y_train, cmap='viridis', edgecolors='k')
 5axes[0].set_title(f'PCA 降维 (准确率: {acc_pca:.3f})')
 6axes[0].set_xlabel('PC1')
 7axes[0].set_ylabel('PC2')
 8
 9# LDA 降维散点图
10axes[1].scatter(X_train_lda[:, 0], X_train_lda[:, 1], c=y_train, cmap='viridis', edgecolors='k')
11axes[1].set_title(f'LDA 降维 (准确率: {acc_lda:.3f})')
12axes[1].set_xlabel('LD1')
13axes[1].set_ylabel('LD2')
14
15plt.tight_layout()
16plt.show()
  • 👨‍🏫 教师活动
    1. 逐段运行代码,每完成一个方案,要求学生记录该方案的准确率。
    2. 运行结束后,展示 PCA 与 LDA 降维散点图对比,提问:“哪张图中三类数据的分离效果更好?”(预期答案:LDA)。
    3. 引导学生对比分析:为什么 LDA 降维后的散点图分离效果优于 PCA?
  • 🧑‍🎓 学生活动
    1. 在 Jupyter Notebook 中完整运行全部代码。
    2. 记录五种方案的准确率,填写实验记录表。
    3. 四人一组讨论以下问题:
      • 方案 1 与方案 2 的准确率差异说明了什么?
      • 方案 3 与方案 4 的准确率差异说明了什么?
      • 方案 4 与方案 5 的差异说明了什么?
    4. 每组派代表汇报讨论结论。

本环节的教学目标为:通过对比实验,使学生在代码实践中理解标准化、降维(PCA/LDA)对分类效果的影响机制,并通过散点图可视化强化“有监督降维优于无监督降维”的直观认知。

✍️ 三、 课堂练习——K 值对两种方案的影响对比

📝 任务一:K 值调参对比实验…

背景与题目: 在方案 2(标准化 KNN)和方案 4(LDA + KNN)中,分别尝试不同的 K 值(1 到 20),绘制两条“K 值 vs 准确率”曲线,观察两种方案的最佳 K 值是否一致。

 1k_values = range(1, 21)
 2acc_std_list = []
 3acc_lda_list = []
 4
 5for k in k_values:
 6    # 标准化 KNN
 7    knn = KNeighborsClassifier(n_neighbors=k)
 8    knn.fit(X_train_scaled, y_train)
 9    acc_std_list.append(knn.score(X_test_scaled, y_test))
10    
11    # LDA + KNN
12    knn_lda = KNeighborsClassifier(n_neighbors=k)
13    knn_lda.fit(X_train_lda, y_train)
14    acc_lda_list.append(knn_lda.score(X_test_lda, y_test))
15
16plt.figure(figsize=(10, 6))
17plt.plot(k_values, acc_std_list, 'bo-', label='标准化 KNN')
18plt.plot(k_values, acc_lda_list, 'ro-', label='LDA + KNN')
19plt.xlabel('K 值')
20plt.ylabel('测试集准确率')
21plt.title('K 值对两种方案准确率的影响')
22plt.legend()
23plt.grid(True)
24plt.xticks(k_values)
25plt.show()
🔍 查看参考结果与解析…

观察结果

  • 标准化 KNN 的最佳 K 值通常在 3~7 之间。
  • LDA + KNN 的最佳 K 值可能与标准化 KNN 不同(降维后数据分布改变)。
  • LDA + KNN 的准确率曲线通常整体高于标准化 KNN。

结论:降维改变了数据的分布形态,因此最佳 K 值也可能随之改变。参数调优需要结合具体的数据形态进行。

📝 四、 课堂小结(5 分钟)

flowchart TB
    root["📊 对比实验结果汇总"]

    root --> C1["准确率排名(典型结果)"]
    C1 --> C1a["1. LDA 分类器 / LDA + KNN(约 0.98)"]
    C1 --> C1b["2. 标准化 KNN(约 0.96)"]
    C1 --> C1c["3. PCA + KNN(约 0.87)"]
    C1 --> C1d["4. 原始 KNN(约 0.72)"]

    root --> C2["核心结论"]
    C2 --> C2a["1. KNN 必须进行标准化处理"]
    C2 --> C2b["2. LDA 降维可提升分类准确率"]
    C2 --> C2c["3. 有监督降维(LDA)优于无监督降维(PCA)"]
    C2 --> C2d["4. 模型选择应基于对比实验数据"]

    style root fill:#4b6cb7,stroke:#253b6e,color:#fff
    style C1 fill:#e3f2fd,stroke:#2196f3
    style C2 fill:#e8f5e9,stroke:#4caf50

✏️ 随堂检测与互动练习

点击展开:随堂测试题(带解析)

一、 单选题

  1. 在本课的对比实验中,原始 KNN(未标准化)准确率最低。直接原因是什么?
  • A. 训练数据量不足
  • B. 不同特征的尺度差异导致大数值特征主导距离计算
  • C. K 值设置不合理
  • D. 数据集类别数过多
【答案】

【解析】B。KNN 基于距离计算,特征尺度不同时,数值较大的特征会主导距离。

  1. LDA + KNN 的准确率通常高于 PCA + KNN,原因是?
  • A. LDA 的代码执行效率更高
  • B. LDA 利用了标签信息,投影方向服务于分类目标
  • C. PCA 只能处理图像数据
  • D. LDA 不需要数据标准化
【答案】

【解析】B。LDA 是有监督降维,利用标签信息寻找最佳分类方向。

二、 简答题

题目:某分类任务包含 50 个特征、5 个类别,共 10000 条样本。请给出技术方案建议,并说明理由。

【答案】

【解析】

  1. 数据标准化:KNN 对尺度敏感。
  2. LDA 降维:5 类数据最多可降至 4 维,利用标签信息提升分类效果。
  3. 模型选择:对比 LDA 分类器和 LDA + KNN 两种方案。
  4. 评估:使用测试集准确率作为最终选择依据。

📮 五、 课后作业与拓展

📮 课后作业…
  1. 基础代码题:使用 load_digits 手写数字数据集(10 类),运行本课的对比实验框架,记录五种方案的准确率。
  2. 对比分析题:在 LDA + KNN 方案中,将降维维度分别设为 1、2、3、4,绘制“维度 vs 准确率”曲线,观察最佳降维维度。
  3. 思考题:本课实验中,LDA + KNN 的准确率超过了使用全部 13 个特征的标准化 KNN。这个现象说明什么?是否意味着特征越少越好?(答案:说明降维去除了噪声和冗余特征,但降维过度会丢失有用信息)。
  4. 预习任务:下一章内容为 “规则与组合力量:决策树与随机森林”
  5. 职高衔接拓展:某零售企业有 80 个客户特征用于流失预测,要求模型在准确性和可解释性之间取得平衡。推荐使用 LDA 还是手动删除特征?说明理由。

📋 六、 板书设计

🛠️ 板书设计…
 1第十一章 几何与空间距离
 2第三课时:综合实战——KNN 与 LDA 对比实验
 3
 4一、实验方案(5 种)
 5   1. 原始 KNN
 6   2. 标准化 + KNN
 7   3. PCA 降维 + KNN
 8   4. LDA 降维 + KNN
 9   5. LDA 分类器
10
11二、实验结果(葡萄酒数据集)
12   1. LDA 分类器 / LDA + KNN  ≈ 0.98
13   2. 标准化 KNN              ≈ 0.96
14   3. PCA + KNN               ≈ 0.87
15   4. 原始 KNN                ≈ 0.72
16
17三、核心结论
18   1. KNN 必须标准化
19   2. LDA 降维提升分类效果
20   3. 有监督降维 > 无监督降维(分类任务)
21   4. 模型选择基于对比实验
22
23四、完整流程
24   加载数据 → 划分数据集 → 标准化 → 降维 → 建模 → 评估

本课用到的单词

单词 发音 专业英语解释(中文)
Benchmark /ˈbentʃmɑːrk/ 基准。用于对比和评估模型性能的参考标准。
Redundancy /rɪˈdʌndənsi/ 冗余。特征之间的重复或高度相关信息。
Trade-off /ˈtreɪd ɔːf/ 权衡。在模型复杂度、准确率、可解释性之间的取舍。