简介:这份数理统计大作业文档面向高校统计学、数据分析相关课程的学生,围绕经典鸢尾花数据集展开完整分析,可作为课程作业参考或统计方法实践范本。压缩包内共1个docx文件,约511KB,内容涵盖数据及符号说明、算法原理分析、数据处理与结果比对等章节,结构完整。文档系统运用马氏距离度量样本相似度,借助主成分分析与线性判别分析完成降维去噪,并以混合高斯模型在极大似然意义下聚类,最后用刀切法(留一法)比较不同降维方法与模型的差异,兼顾类间离差放大与类内离差缩小。已有1429人学习下载,适合需要理解统计方法如何落地到真实数据、对照实验流程与结论撰写作业的读者参考。
1. 鸢尾花降维分类:为什么四个特征里藏着两条“看不见的轴”
鸢尾花数据集常被当成入门练手的第一课,150 个样本、4 个数值特征、3 个类别,看起来简单到没什么可挖。但真正动手做过分类的人会发现一个反直觉的现象:把 4 维特征直接丢进分类器,效果往往不如先降到 2 维再分类。这不是玄学,而是因为花萼长度、花萼宽度、花瓣长度、花瓣宽度这四个量之间存在明显的线性相关,信息本身是冗余的。数理统计大作业里围绕鸢尾花做的这套分析,核心就在回答一个问题:降维到底降掉了什么、保留了什么,以及为什么带标签的降维比不带标签的降维更“懂”数据。搞懂这条链路,比背十个算法名字有用得多。
2. 马氏距离:为什么欧氏距离在相关特征上会翻车
2.1 欧氏距离的隐含假设
欧氏距离的公式是两点坐标差的平方和开根号,它默认了一件事:各个维度是同等重要、彼此独立的。这个假设在鸢尾花数据上直接翻车。花萼长度和花瓣长度高度正相关,一个样本在这两个维度上同时偏大,欧氏距离会把这份“同向偏移”重复计算两次,导致距离被放大。更麻烦的是量纲问题:如果某个特征用厘米、另一个用毫米,数值差几个数量级,欧氏距离几乎只由大数值那个维度决定,小维度等于被忽略了。
马氏距离要解决的就是这两件事。它把协方差矩阵 Σ 引入距离计算,本质上是先对数据做一次白化变换,把相关的、量纲不一的特征拉回到同一个标准正态空间里,再算距离。当 Σ 等于单位矩阵时,马氏距离退化成欧氏距离,这个退化关系恰好说明了欧氏距离是马氏距离的一个特例。
2.2 协方差矩阵如何“校正”距离
马氏距离的定义是 $d(x,\mu)=\sqrt{(x-\mu)^T\Sigma^{-1}(x-\mu)}$。关键在于 $\Sigma^{-1}$ 这个逆矩阵:协方差大的方向,逆矩阵对应元素小,距离被压缩;协方差小的方向,逆矩阵元素大,距离被放大。换句话说,它自动给“信息量大的方向”加权,给“噪声大的方向”降权。
这里有个容易踩的坑:Σ 必须是正定的才能求逆。样本量小于特征维度时,协方差矩阵会奇异,直接求逆会报错或者得到数值爆炸的结果。常见的处理是加一个很小的对角扰动(正则化),或者先做降维再算马氏距离。鸢尾花只有 4 维、150 个样本,Σ 是良态的,所以可以直接求逆,但换成高维小样本场景,这一步就是血泪经验的来源。
import numpy as np def mahalanobis(x, mu, cov, reg=1e-6): # cov 可能奇异,加对角扰动保证可逆 cov_reg = cov + reg * np.eye(cov.shape[0]) inv_cov = np.linalg.inv(cov_reg) diff = x - mu # 二次型 (x-mu)^T Σ^-1 (x-mu) return np.sqrt(diff.T @ inv_cov @ diff)这段代码里reg参数就是后悔药,数值一般取 1e-6 到 1e-3,太大则校正失效、退化成欧氏距离,太小则压不住奇异。diff.T @ inv_cov @ diff是标准的二次型写法,注意顺序不能反,矩阵乘法不满足交换律。
2.3 尺度无关性带来的实际好处
马氏距离是无量纲的,这一点在鸢尾花上体现得很直接:四个特征虽然都是厘米,但花萼长度跨度约 4.3 到 7.9,花瓣宽度只有 0.1 到 2.5,数值范围差了好几倍。不做标准化直接算欧氏距离,花瓣宽度几乎不起作用;马氏距离通过 Σ 自动完成了标准化,不需要手动做 z-score。这也是为什么后面用高斯混合模型时,判断样本归属用的是马氏距离而不是欧氏距离——它和协方差结构是自洽的。
3. 高斯混合模型:为什么聚类不能只找一个中心
3.1 从单高斯到混合分布
k-均值聚类的假设非常强:每个簇是一个球,球的大小一样、方向无关。鸢尾花三个类别里,Setosa 和另外两类分得很开,但 Versicolour 和 Virginica 在花瓣长度上有重叠,而且各类的协方差形状并不相同。用一个球去套所有簇,边界必然错位。
高斯混合模型换了个思路:不假设每个簇是球,而是假设每个簇服从一个多元高斯分布,有自己的均值 μ、自己的协方差 Σ、自己的混合权重 π。整个数据的分布是若干个高斯的加权和:
$$p(x)=\sum_{k=1}^{K}\pi_k \mathcal{N}(x|\mu_k,\Sigma_k)$$
Σ 是完整矩阵而不是对角阵,这意味着它同时刻画了每个维度自己的方差(不同方向上的散布)和维度之间的相关性(协方差)。这正是它比 k-均值强的地方:椭球可以倾斜、可以胖瘦不一,贴合真实簇的形状。
3.2 极大似然估计与 EM 的必然性
有了模型形式,下一步是求参数。直接对对数似然求导,会发现方程里出现了“样本属于某个高斯的后验概率”这个隐变量,导数方程没有闭式解。这就是为什么 GMM 的参数估计必须走 EM 算法:E 步用当前参数算每个样本属于各高斯的责任度(后验概率),M 步用责任度加权更新 μ、Σ、π,交替迭代直到似然收敛。
def e_step(X, weights, means, covs): # 计算每个样本对每个高斯的责任度 n, k = X.shape[0], len(weights) resp = np.zeros((n, k)) for j in range(k): diff = X - means[j] inv = np.linalg.inv(covs[j]) # 多元高斯密度(省略归一化常数,后面统一归一化) resp[:, j] = weights[j] * np.exp(-0.5 * np.einsum('ni,ij,nj->n', diff, inv, diff)) resp /= resp.sum(axis=1, keepdims=True) # 按行归一化成概率 return respeinsum('ni,ij,nj->n', diff, inv, diff)是批量计算马氏距离平方的紧凑写法,等价于对每个样本算二次型。resp.sum(axis=1)按行求和再归一化,保证每个样本对 K 个高斯的责任度加起来等于 1。M 步则用resp做加权平均更新均值和协方差,权重更新为各列责任度的均值。
3.3 协方差矩阵的退化风险
GMM 最脆弱的地方在 Σ。如果某个高斯只分到极少数样本,或者样本在某个方向上几乎共线,Σ 会接近奇异,求逆时数值不稳定,责任度计算直接崩掉。工程上的常见做法是给 Σ 加一个小的对角正则项,或者限制 Σ 为对角阵(代价是丢掉维度间相关性)。鸢尾花数据量足够、维度低,完整协方差是可行的,但换成高维数据,这个取舍就必须提前想清楚。
4. 主成分分析与线性判别分析:降维的两种世界观
4.1 PCA 在优化什么
PCA 的目标函数很纯粹:找一个投影方向 u,使得投影后的方差最大,即 $\max_u u^T\Sigma u$,约束 $u^Tu=1$。解是 Σ 最大特征值对应的特征向量。第二个主成分在与第一个正交的约束下继续最大化方差,依此类推。整个过程只用了 X,完全没看标签。
这带来一个根本性的局限:方差大的方向不一定是分类有用的方向。鸢尾花里花瓣长度方差很大,PCA 会优先保留它,但如果两个类别恰好在这个方向上均值接近、只是散布不同,PCA 帮不上分类的忙。更极端的情况是,判别信息藏在一个方差很小的方向上,PCA 会把它当噪声丢掉。
4.2 LDA 如何把标签信息编进目标函数
LDA 的目标函数换成了 Fisher 准则:最大化类间散度与类内散度的比值。定义类内散度矩阵 $S_w$ 和类间散度矩阵 $S_b$,目标是 $\max_u \frac{u^T S_b u}{u^T S_w u}$。解是 $S_w^{-1}S_b$ 的特征向量。
这个式子的物理意义很直白:分子希望投影后不同类别的中心离得远,分母希望同一类别内部的点聚得紧。PCA 只看分母(总方差),LDA 同时看分子和分母,所以它是在“为分类而降维”,而不是“为保留信息而降维”。鸢尾花上 LDA 通常只需要 2 个判别方向就能把三类分得很开,因为类别数减一就是判别方向数的上界。
def lda_fit(X, y): classes = np.unique(y) mean_all = X.mean(axis=0) Sw = np.zeros((X.shape[1], X.shape[1])) Sb = np.zeros_like(Sw) for c in classes: Xc = X[y == c] mean_c = Xc.mean(axis=0) # 类内散度:各类协方差之和 Sw += (Xc - mean_c).T @ (Xc - mean_c) # 类间散度:类中心相对总中心的加权外积 n_c = Xc.shape[0] diff = (mean_c - mean_all).reshape(-1, 1) Sb += n_c * (diff @ diff.T) # 求解广义特征值问题 Sw^-1 Sb eigvals, eigvecs = np.linalg.eig(np.linalg.inv(Sw) @ Sb) idx = np.argsort(eigvals.real)[::-1] return eigvecs[:, idx].realSw累加的是每个类内部去中心化后的外积,Sb累加的是类中心偏移的外积并按类样本数加权。np.linalg.eig返回的特征值可能是复数,取实部排序是常规操作。注意Sw同样可能奇异,实践中常加正则项或用伪逆。
4.3 降维即去噪的机制
把 4 维降到 2 维,丢掉的那两个方向是什么?对 PCA 来说,是最小特征值对应的方向,也就是方差最小、最可能是测量噪声的方向。对 LDA 来说,是类内散度大而类间散度小的方向,也就是“对分类没帮助的变异”。两种方法丢的东西不一样,但都起到了去噪作用。降维之后再做 GMM,参数数量大幅减少(4 维完整协方差有 10 个自由参数,2 维只有 5 个),小样本下的估计方差随之下降,这就是“降维提升聚类效果”的底层原因,不是什么玄学调参。
5. 刀切法比对:为什么留一法能给出更诚实的评价
5.1 回报法的乐观偏差
如果用训练集本身来评估分类器,准确率会虚高。模型在训练时已经“见过”这些样本,尤其是 GMM 这种参数多的模型,对训练样本的拟合天然偏好。回报法(resubstitution)就是这种评估方式,它的误差估计是有偏的、偏乐观的。
5.2 留一法的机制与代价
刀切法(留一法)每次从 n 个样本里剔除一个,用剩下 n-1 个训练,对被剔除的那个做预测,重复 n 次,统计判错个数。这样每个样本都恰好当过一次测试集,评估结果几乎无偏。代价是训练 n 次,计算量是回报法的 n 倍。鸢尾花只有 150 个样本,这个代价完全可接受;换成百万级样本,留一法就不现实了,得退到 k 折交叉验证。
在降维方法比对里,留一法的价值在于它把“降维 + 聚类 + 判别”整条链路当成一个整体来评估。PCA 降到几维、LDA 降到几维,每种组合都走一遍留一法,得到的判错率才是可比的。如果只在训练集上比,PCA 和 LDA 的差距会被系统性低估或高估。
提示:留一法评估时,降维的变换矩阵必须在每一折的训练集上重新拟合,不能在全量数据上先降维再切分,否则测试样本的信息会泄漏进训练过程,评估结果偏乐观。
6. 避坑与排查:这套流程里最容易翻车的几处
6.1 现象:PCA 降维后分类效果反而变差
原因:没有对数据做标准化,直接对原始协方差矩阵做特征分解,量纲大的特征主导了主成分方向。解决:用相关矩阵代替协方差矩阵,等价于先做 z-score 再 PCA,消除量纲影响。
6.2 现象:GMM 迭代过程中似然值不升反降或震荡
原因:协方差矩阵接近奇异,求逆数值不稳定,责任度计算出 NaN。解决:给 Σ 加对角正则项,或改用对角协方差;同时检查是否有高斯分到了零个有效样本,必要时重新初始化。
6.3 现象:LDA 求解时报矩阵奇异
原因:$S_w$ 不满秩,常见于样本数少于特征维度,或某个类别样本极少。解决:对 $S_w$ 加正则项,或用伪逆np.linalg.pinv代替直接求逆。
6.4 现象:留一法准确率异常高,接近 100%
原因:降维步骤在全量数据上先做了,测试样本信息泄漏进训练。解决:把降维拟合放进每一折的训练循环内部,严格隔离测试样本。
6.5 现象:马氏距离算出来是 NaN 或极大值
原因:协方差矩阵奇异导致求逆失败,或某个维度方差为零。解决:检查是否有常数列特征,加正则扰动,或先剔除零方差维度。
7. 设计取舍:降维程度到底该由谁决定
这套流程里最值得琢磨的取舍,是“降到几维”这个决定该由什么来定。PCA 降到 2 维还是 3 维,LDA 用 1 个还是 2 个判别方向,表面上是超参数,实际上反映的是你对“信息”和“噪声”边界的判断。PCA 的碎石图能告诉你方差贡献率,但方差大不等于分类有用;LDA 的判别方向数有理论上界(类别数减一),但上界之内选几个,仍然要靠留一法这类外部评估来定。
我一般的理解是:降维方法负责“生成候选表示”,评估方法负责“挑选表示”,两者不能混在一起。如果拿训练集上的聚类紧致度去选降维维度,等于让模型自己给自己打分,结果一定偏乐观。留一法在这里扮演的角色,就是一个不参与训练的裁判。
另一个取舍是 GMM 的协方差结构。完整协方差最灵活,但参数多、易奇异;对角协方差稳,但丢掉了维度间相关性。鸢尾花的四个特征相关性明显,完整协方差是合理选择;如果特征维度上升到几十维、样本量又不大,对角协方差或者先降维再建模,往往是更稳的路子。这个取舍没有标准答案,取决于你对数据相关结构的先验判断和样本量。
还有一个容易被忽略的点:马氏距离、GMM、LDA 三者其实共享同一个协方差假设。GMM 的每个高斯有自己的 Σ,LDA 用 pooled 的 $S_w$,马氏距离用全局 Σ。如果数据本身不满足高斯假设,这条链路的每一环都会打折扣。鸢尾花数值型、近似高斯,所以走得通;换成类别型或重尾分布的数据,就得换工具。
从那以后我每次做降维加聚类的流程,都会强制走一遍“先留出评估、再拟合变换”的顺序,哪怕数据量小到看起来没必要。这个习惯帮我避开了好几次信息泄漏导致的虚高准确率。希望帮到你。
本文还有配套的精品资源,点击获取