2017C「颜色与物质判别」(一):判别分析与可视化——降维与线性判别
1 问题重述
2017 年国赛 C 题「颜色与物质判别」的核心任务是:给定物质的颜色特征数据,建立由"颜色特征"到"物质类别"的判别模型,并能在存在异常样本时识别之。在工程与质检场景中,这对应着"凭光谱/成像颜色快速区分材料种类""在来料中挑出成分可疑的批次"等典型需求。题目本质上是一个有监督的二分类判别问题,同时隐含了对异常与不确定样本的检测要求。
本题附件给出每条样本在 6 个颜色通道(记为特征 f1–f6)上的观测值,以及该样本所属的物质类别标签(0 或 1 两类)。完整建模应回答三个递进问题:(一)两类物质在颜色特征上到底可不可分、怎么分(本篇);(二)用哪些分类器、如何选型最稳妥(下一篇);(三)如何应对测量异常与噪声扰动(再下一篇)。
我们构造了与赛题结构一致的合成数据集(详见附录):共 200 条样本,每条含 6 个颜色特征,类别标签为 0/1(分别 106 / 94 条),并人为注入了 12 条远离两类主体的离群异常(用于第三篇的异常检测)。全部数据在纯 Python 下确定性生成,所有数字不依赖任何外部数值库,保证图、正文、附录、工具四处完全一致。
2 数据特征与描述性统计
图1 给出了两类物质在 6 个颜色特征上的均值对比。肉眼可见两类并非在所有特征上都分得很开:例如 f1、f5 上两类均值接近,而 f3、f4、f6 上则出现明显错位。这说明类别信息分散在多个特征中,且各特征的判别力强弱不一——这正是判别分析要量化的对象。
数据集的基本结构如下:样本量 ,特征维 ,两类规模接近均衡(106 对 94,比例约 0.53 : 0.47),不存在严重的类别不平衡,因此后续分类器可直接以"准确率"为主指标,不必过度依赖加权或重采样。
在正式建模前,必须先做特征标准化(z-score):对每个特征减去训练集均值、除以训练集标准差,使 6 个通道处于同一量纲。这一步看似平凡,却至关重要——PCA 的协方差矩阵、LDA 的 方向、逻辑回归的系数尺度,全部依赖"各特征方差可比"。若不标准化,f3、f6 这类数值较大的通道会"霸占"投影方向,掩盖真正有判别力的弱信号。本数据各特征原始量纲本就接近,标准化后仍保持相对秩序,因此结论对是否标准化不敏感,但这恰恰说明"养成标准化的习惯"在任何判别任务里都值得。
此外,训练/测试按 7:3 分层切分(140 训练、60 测试),保证两类在两端比例一致,避免某一折恰好抽到类别失衡的样本而误导评估。
3 特征层面的类别可分性
在降维之前,先在原始特征空间做初步判别力评估。对每个特征计算两类均值的"标准化差异"(Cohen's ,即 除以合并标准差),数值越大表示该特征越能区分两类。由数据可得各特征的判别强度为:
| 特征 | f1 | f2 | f3 | f4 | f5 | f6 |
|---|---|---|---|---|---|---|
| 判别强度 | 0.49 | 1.35 | 1.75 | 1.46 | 0.18 | 1.84 |
f6()与 f3()是最强的区分特征,f5()几乎不携带类别信息,而 f2、f4 居中。这一排序将在第二篇通过逻辑回归系数与决策树增益得到交叉验证——多方法给出一致的特征重要性,是结论可信的标志。
4 PCA 降维与二维可视化
6 维特征直接画图困难,先用主成分分析(PCA)压缩到 2 维观察整体结构。PCA 在标准化后的特征协方差矩阵上做特征值分解(幂迭代取前两大特征向量,纯 Python 实现)。结果如图3:前两个主成分分别解释 35.5% 与 17.4% 的方差,累计 52.9%;后续 PC3–PC6 各约 10%–15%,衰减平缓,说明数据没有单一主导方向,而是沿多个特征"摊开"。
图2 把每条测试样本投影到 PC1–PC2 平面并按真实类别着色(蓝=类0,红=类1)。可见两类在二维平面上确实分成了两团,但边界处明显交叠——这正是"可判别但非完全可分"的直观体现。交叠区样本正是后续分类器最易判错的部分,也暗示单靠线性投影难以彻底分开,需要更丰富的分类器来刻画边界。
进一步看主成分到底"由哪些特征构成"。PC1 的载荷向量为 ,在 f2、f3、f4、f6 上权重最大且 f3 取负——说明 PC1 主要刻画"以 f3 为反号、f2/f4/f6 为同号"的综合颜色对比;PC2 的载荷 则几乎只由 f5 主导(权重 0.89)。这意味着:f5 是一条相对独立、信息量不大的"边路"特征(它单特征判别力 也最低),而真正区分两类的 f3/f4/f6 被摊进了 PC1 与更高阶主成分中。若想用 PCA 做"降维后再分类",单取前 2 主成分只能保留约 53% 的方差,把 f3/f4/f6 的判别信息切散了;要覆盖到 80% 方差需取前 4 个主成分(PC1–PC4 累计 )。这再次说明——PCA 适合看结构,不适合直接当分类器用,分类还是应交还给 LDA 或专门的分类算法。
5 线性判别分析(LDA):最大化类间可分性
PCA 是无监督的"方差最大化",并不关心类别标签;要直接为分类服务,应使用线性判别分析(LDA)。LDA 求解投影方向 ,使投影后类间散度与类内散度之比(Fisher 准则 )最大。在两类情形下存在闭式解 ,其中 为类内散度矩阵(需对其求逆,纯 Python 用高斯消元实现)。
本数据下求得 Fisher 准则值 。Fisher 值本身大小依赖于特征尺度,其意义在于确认存在一个使两类显著拉开的方向。图5 给出了该判别向量的 6 个分量(权重),其符号与相对大小刻画了"沿哪个特征组合走,两类分得最开",可与第3节的单特征判别强度相互印证。
将全部测试样本投影到该一维方向并按类别绘制直方图(图4),两类各自聚成一个峰、中间仅有少量重叠,说明 LDA 方向有效地把"类别信号"提炼了出来。图中虚线位置即分类阈值(取两类投影均值的中点)。
6 逻辑回归基线模型
为给出可解释的判别方程与概率输出,建立逻辑回归基线:
在标准化特征上用梯度下降估计系数(学习率 0.3,4000 步),再还原到原始量纲,得
图6 展示了截距与 6 个特征系数。系数绝对值越大,该特征对判别的贡献越突出:f3(→取绝对值 经标准化后最显著)、f6()、f4()贡献最大,f5()最小——与第3节 Cohen's 的排序(f6>f3>f4>f5)高度一致,进一步坐实了"特征判别力"的结论。
逻辑回归系数的可解释性远不止"谁大谁小"。以 f3 为例,其系数 意味着:在其它特征保持不变时,f3 每升高 1 个标准化单位,对数几率下降 4.798,对应胜率(odds)变为原来的 ——即 f3 越大,样本越不可能是类1。把 6 个系数读成"每个颜色通道对'属于类1'的投票权重",模型的判别逻辑一目了然,这是黑箱模型难以提供的。也正因如此,当业务方问"为什么判它是类1",逻辑回归能直接给出逐特征的解释,而不仅是抛出一个标签。
逻辑回归在测试集上给出 ROC 曲线(图8),曲线下面积 AUC = 0.959,表明该线性模型已具备很强的排序判别力。AUC 的含义是:随机抽一个类1样本和一个类0样本,模型把类1排在前面的概率高达 95.9%——即便不卡阈值,仅靠"打分高低"就能极好地分开两类。图7 是 LDA 的测试集混淆矩阵:真类0共 32 例判对 29、错 3;真类1共 28 例判对 26、错 2,整体错分仅 5 例,测试准确率约 91.7%。两种线性模型相互印证:本题的判别信号充足,线性方法已是高性价比的基线选择。
逻辑回归在测试集上给出 ROC 曲线(图8),曲线下面积 AUC = 0.959,表明该线性模型已具备很强的排序判别力。图7 是 LDA 的测试集混淆矩阵:真类0共 32 例判对 29、错 3;真类1共 28 例判对 26、错 2,整体错分仅 5 例。
7 小结与向下一篇的铺垫
本篇完成了"判别分析与可视化"这一基础环节,得到三点结论:(1)两类物质在 6 维颜色特征上可判别但存在交叠,非完全线性可分;(2)判别信息主要由 f3、f4、f6 承载,f5 几乎无用;(3)即使最简单的 LDA/逻辑回归,也能取得约 0.92–0.96 的 AUC,说明问题本身"信号充足"。
值得进一步讨论的是"降维"与"判别"的目标差异。PCA 图(图2、图3)告诉我们"数据朝哪些方向展开最多",那是为了观察结构、压缩维度、便于画图;LDA 图(图4、图5)则直接为分类服务,把"类间散度拉大、类内散度压小"。两者方向并不相同:PCA 第一主成分 v1=(-0.24, 0.47, -0.50, 0.46, -0.06, 0.50) 偏向 f2/f3/f4/f6 的方差最大组合,而 LDA 判别向量 w=(-0.11, 0.36, -0.53, 0.47, -0.08, 0.59) 更强调 f3/f4/f6 的类别差异。这种"方差最大方向"与"判别最强方向"的错位,正是降维可视化里最容易误导新手的地方——看着 PC1 上两类有重叠,不代表模型分不了;真正为分类优化的方向可能藏在 PC2 甚至更后面。因此本篇坚持"先可视化看结构、再用 LDA 做判别"的分两步策略,避免被 PCA 的视角带偏。
线性模型对交叠边界的刻画能力毕竟有限,且"哪个分类器最适合本题"尚未回答。下一篇将系统地比较逻辑回归、LDA、KNN、朴素贝叶斯、决策树五种分类器,用交叉验证与多指标选型,并确定最终推荐模型;在此基础上,第三篇再探讨异常检测与噪声鲁棒性,把"实用判别系统"的拼图补完整。
8 与原赛题的对应及方法局限
本篇的"6 个颜色特征→两类物质标签"对应原题中"由颜色/光谱数据判别物质种类";PCA/LDA 可视化对应原题"对数据做降维观察结构"的隐含要求。需说明两点简化:其一,真实赛题中物质类别可能多于两类、且颜色与浓度的关系常呈连续非线性,本合成数据取二分类以便把"判别—选型—异常"三条主线讲透;其二,LDA 要求各类协方差近似同质,若实际各类散布形态差异很大(异方差),应改用二次判别或核方法,但本数据的线性结构下线性判别已足够且更易解释。这些简化不影响"先看清结构、再选型、最后防异常"这一主线,也为后两篇提供了干净可控的实验台。
附录:可复现的 Python 实现
以下代码在 mcm520-site/tools/ 目录下运行,调用唯一数据真源 gen_data.gen_2017c() 复现本篇全部结论。
# 在 mcm520-site/tools/ 目录下运行:python3 this_script.py
import gen_data as GD
D = GD.gen_2017c() # 确定性合成数据 + 全部权威数字
n, d, nanom = D["n"], D["n_feat"], D["n_anom"] # 200 / 6 / 12
cls = D["cls_counts"] # {0: 106, 1: 94}
print("样本数=%d 特征维=%d 注入异常=%d 类别=%s" % (n, d, nanom, cls))
# PCA 方差解释(前 2 主成分累计)
pv = D["pca_var_norm"]
print("PC方差解释:", [round(v, 3) for v in pv])
print("前2主成分累计=%.3f" % (pv[0] + pv[1])) # 0.529
# Fisher 线性判别准则
print("Fisher准则 J=%.3f" % D["fisher_J"]) # 0.094
print("LDA判别向量:", [round(v, 3) for v in D["wlda"]])
print("LDA分类阈值=%.3f" % D["lda_thr"])
# 单特征判别强度 Cohen's d
print("特征判别强度 d:", [round(v, 3) for v in D["feat_sep"]])
# 逻辑回归系数(原始量纲)
print("LR系数(截距+6特征):", [round(v, 3) for v in D["lr_coef"]])
# 逻辑回归 ROC / AUC 与 LDA 混淆矩阵
print("LR测试集 AUC=%.3f" % D["model_metrics"]["LR"]["auc"]) # 0.959
print("LDA混淆矩阵(行=真,列=预测):", D["lda_cm"]) # [[29,3],[2,26]]
print("LDA测试集准确率=%.3f" % D["model_metrics"]["LDA"]["acc"])