☰
线性判别分析 LDA:从分类到有监督降维的完整实战指南
2026/10/14 7:43:24 网站建设 项目流程

我在用 LDA 帮一个多分类项目做特征降维时,发现一个普遍现象:问身边的人“线性判别分析是干嘛的”,十个人里八个会反问“是不是和 PCA 差不多”,剩下两个会说“哦,那个分类器”。这两个答案其实都对,但都只说了一半。基于 sklearn 的LinearDiscriminantAnalysis是一个同时具备两种身份的对象——它既可以用fit_transform做有监督的线性降维,也可以用predict做分类。这次我把一个完整使用过程串起来讲:从原理直觉、参数选择,到标准化、数据切分、评估可视化,再到那些文档里不会写、但实际项目里一定会遇到的坑。

LDA 的核心理念就一句话:寻找一组线性方向,让投影后的数据“类内紧凑、类间疏远”。一旦你把它和 PCA 的本质差异想明白——PCA 只关心方差,不关心标签;LDA 把标签考虑进去,只关心怎么分得开——你就知道它为什么在分类任务上往往比 PCA 更有用。这篇文章适合三类人:刚接触机器学习、准备用 sklearn 做分类的初学者;已经会用 PCA 但想搞清楚“有监督降维”该怎么用的朋友;还有在风控、图像特征、文本向量这类高维数据里反复做特征压缩的工程师。

1. LDA 到底解决什么问题:分类与降维的两副面孔

LinearDiscriminantAnalysis在 sklearn 里是一个类,但它天然承担了两种任务。很多入门教程把它拆成“分类器”和“降维方法”两章来讲,实际项目里你往往要同时用到这两面,不理解这一点,代码写起来会很别扭。

1.1 分类视角:一个自带贝叶斯概率的线性分类器

LDA 的出发点非常简单:假设每一类的数据大致服从正态分布,并且各类的协方差结构差不多,那么类别之间的最佳分界可以用一条直线(二维)或者一个超平面(高维)来表示。这条边界的数学基础是贝叶斯决策——它先估计每个类别的均值和共享协方差,再用马氏距离计算每个样本属于哪个类别的后验概率最大,把样本分给后验概率最高的那类。

举个例子你就明白了。假设你要根据身高和体重判断一个人是篮球运动员还是普通人。两类人都近似正态分布,篮球运动员整体身高体重都更高,普通人分布更扩散一些。LDA 做的事情不是简单画一条“身高>185 就算运动员”的规则,而是同时考虑两个特征的联合分布,找一条“综合身高和体重,哪个方向能把两类人分得最开”的线。这就是它和单变量阈值法最本质的区别。

1.2 降维视角:与 PCA 的根本区别

PCA 找的是方差最大的方向,完全没有利用标签信息。LDA 找的是“类间距离除以类内离散度”最大的方向,每一步都在利用y。

这个区别在真实数据上非常致命。假如你的数据里存在一个噪声维度,方差极大但和分类毫无关系,PCA 会把第一主成分浪费在这个噪声上;LDA 因为有标签约束,会直接无视这种“类内噪声”,优先去找真正能分开类别的方向。这也是为什么在有标签的场景里,用 LDA 降维后接分类器,往往比 PCA 降维后接分类器效果更稳。

对比维度LDAPCA
监督/无监督有监督,必须提供 y无监督,不需要 y
优化目标类间散度 / 类内散度 最大投影后方差最大
最多降维维度min(类别数 - 1, 特征数)特征数
擅长场景分类任务前的降维、特征压缩无标签数据压缩、去噪、可视化
对类别不平衡的敏感度敏感,需要调 priors不敏感

1.3 sklearn 里的实际用法预览

在 sklearn 里,同一个对象可以完成两件事:

from sklearn.discriminant_analysis import LinearDiscriminantAnalysis lda = LinearDiscriminantAnalysis(n_components=2) X_lda = lda.fit_transform(X_train, y_train) # 降维,注意这里传了 y y_pred = lda.predict(X_test) # 分类,直接预测

第一次从 PCA 转过来的人最容易懵的就是fit_transform为什么需要传y。PCA 是fit_transform(X),LDA 是fit_transform(X, y)。如果你把它当成 PCA 用,把 y 漏掉,sklearn 会直接报错,提醒你“有监督方法必须给标签”。记住这一点,后面代码就不会卡壳。

2. 核心原理拆解:类内散度、类间散度与 sklearn 的求解逻辑

网上有很多 LDA 的推导帖,但大部分人看完只记住了公式,没记住几何直觉。我换个讲法,先把两个散度矩阵是什么东西讲清楚,再解释为什么 sklearn 的求解方式会影响你的参数选择。

2.1 两个散度矩阵的几何直觉

先定义几个记号:全局均值 μ 是所有样本的中心,第 k 个类别的均值是 μ_k,第 k 类的样本数是 n_k。

类内散度矩阵 S_W 衡量的是“每个类别内部,样本偏离自己类中心的程度”,把你自己的每个点减去自己类的均值,求外积再求和。它越小,说明每一类内部越聚拢。

类间散度矩阵 S_B 衡量的是“各类中心偏离全局中心的程度”,按各类样本量加权求和。它越大,说明各类中心彼此分得越开。

LDA 的目标可以写成这样一个比值:

J(w) = (w^T S_B w) / (w^T S_W w)

翻译成人话就是:我要挑一个投影方向 w,让“类间分散程度”尽量大,同时“类内聚合程度”也尽量大,也就是分母小、分子大。数学上,这个最优化问题的解是矩阵 S_W^{-1} S_B 的特征向量,对应特征值最大的那几个方向就是我们要的判别方向。

我常用的一个类比是拍照:一群穿红衣服和一群穿白衣服的人混在一起,我要找一个拍摄角度,让两拨人在画面里尽量拉开距离,同时每一拨人内部别挤成一团乱麻。找这个角度的过程就是 LDA。

2.2 为什么二分类最多只有一个判别方向

这是 LDA 最容易被误解的地方之一。矩阵 S_B 的秩最大是 c-1,其中 c 是类别数。二分类时 c=2,S_B 的秩最多是 1,所以无论你的原始特征有几百维,二分类的 LDA 只能给出 1 个判别方向。三分类时最多 2 个,四分类最多 3 个。

这也是为什么鸢尾花、葡萄酒这类三分类数据集,设n_components=2就到顶了。如果你强行设n_components=3,新版 sklearn 会直接抛ValueError,老版本可能静默忽略导致结果莫名其妙。我第一次遇到这个问题时还以为是数据有问题,查了半天才发现是维度上限的约束。

所以记住一个速算规则:LDA 能降到的最大维度 = min(类别数 - 1, 特征数),不是由特征数单独决定的。

2.3 sklearn 的三种 solver 选择逻辑

LinearDiscriminantAnalysis的solver参数有svd、lsqr、eigen三个选项,这直接决定了求解路径和你能用哪些附加功能。

  • svd(默认):基于奇异值分解,不直接计算类内散度矩阵的逆,数值稳定性最好。样本数比特征数少时也能跑,但不支持shrinkage,也不会输出协方差相关的诊断信息。
  • lsqr:通过最小二乘形式求解广义特征问题,支持shrinkage。特征维度高、样本量小的场景,比如基因表达数据、文本 TF-IDF 矩阵,优先用它配合shrinkage="auto"。
  • eigen:经典的特征分解方式,需要求解或近似求解类内散度矩阵的逆,也支持shrinkage。当你需要做协方差诊断、想拿到各类协方差矩阵时,可以用它并设置store_covariance=True。

一个粗略的选择建议:默认直接上svd,数据量正常、特征量不大时它最快最稳;一旦出现“样本数 < 特征数”或者交叉验证波动大,就换成lsqr + shrinkage="auto";需要做模型诊断、想看协方差结构的时候才考虑eigen。

3. 基于 sklearn 的完整代码实现:从数据准备到分类评估

这一节直接上代码。我用 sklearn 内置的葡萄酒数据集做演示,它有 13 个特征、3 个类别、178 个样本,特征量纲差异非常大——有的特征数值在十几,有的能到上千。这种数据结构特别适合展示标准化对 LDA 的影响。

3.1 环境准备与数据集选择

环境没什么特殊要求,Python 3.8 以上,装好这几个库就行:

pip install scikit-learn numpy matplotlib pandas

数据集选择方面,葡萄酒数据集比鸢尾花更有代表性。鸢尾花只有 4 个特征,降维的冲击力不够;葡萄酒 13 个特征压到 2 维,效果一目了然。代码里直接用load_wine()读取,不需要额外下载数据文件。

3.2 第一步:标准化与分层划分

import numpy as np import pandas as pd import matplotlib.pyplot as plt from sklearn.datasets import load_wine from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from sklearn.discriminant_analysis import LinearDiscriminantAnalysis from sklearn.metrics import accuracy_score, classification_report, confusion_matrix wine = load_wine() X = wine.data y = wine.target print("特征矩阵形状:", X.shape) print("类别名:", wine.target_names) X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.3, random_state=42, stratify=y ) scaler = StandardScaler() X_train_sc = scaler.fit_transform(X_train) X_test_sc = scaler.transform(X_test)

这一步我想强调两件事。

第一,stratify=y是我在分类任务里的固定习惯。不设置它时,train_test_split是纯随机切分,样本少的时候很容易出现某个类别在训练集里占比失衡。加了分层切分,训练集和测试集里各类比例保持一致,评估结果才可信。

第二,标准化用的是“训练集 fit,测试集 transform”的流程,绝对不能对全部数据先做fit_transform再切分。这一点后面第 5 节专门讲,这里先把正确姿势摆出来。

为什么 LDA 要标准化?因为类内散度矩阵本质上是协方差矩阵的量级累加,如果不标准化,数值范围大的特征会在散度计算里占据绝对主导,判别方向会被它带偏。比如葡萄酒数据里某个特征动辄上千,另一个特征只有十几,前者几乎把后者“淹没”了。虽然solver='svd'数值上不至于算不出来,但结果的解释性和稳定性都会变差。我的经验是:无论用哪种 solver,先标准化基本不会错。

3.3 第二步:用 fit_transform 做监督降维

lda = LinearDiscriminantAnalysis(n_components=2) X_train_lda = lda.fit_transform(X_train_sc, y_train) X_test_lda = lda.transform(X_test_sc) print("LDA 降维后训练集形状:", X_train_lda.shape) print("各判别方向的贡献比例:", lda.explained_variance_ratio_)

注意两个细节:

  • fit_transform必须传入y_train,这是 LDA 区别于 PCA 的关键。
  • 测试集只调用transform,绝对不要重新fit,否则测试集的信息会被 LDA 的投影矩阵看见,评估结果会虚高。

explained_variance_ratio_这个属性在降维时特别有用。它告诉你每个判别方向承载了多少“类间判别信息”。在我本地跑出来的典型结果里,第一个判别方向通常就能解释 80% 以上的判别信息,第二个方向补充剩余部分。这说明葡萄酒数据的类别可分性几乎集中在一个方向上。

3.4 可视化二维投影与决策边界

降维之后第一件事就是画图,看看三类样本在判别空间里的分布:

plt.figure(figsize=(9, 6)) for i in range(3): idx = y_train == i plt.scatter(X_train_lda[idx, 0], X_train_lda[idx, 1], label=wine.target_names[i], edgecolor="white", alpha=0.7) plt.xlabel("LD1") plt.ylabel("LD2") plt.title("Wine 数据经 LDA 降维后的二维分布(训练集)") plt.legend() plt.grid(alpha=0.3) plt.show()

你会看到三个类别在判别空间里被拉得非常开,每一类内部又很紧凑。这就是 LDA “类内紧凑、类间疏远”目标的直接体现。

如果把 LDA 当分类器,我们还能在二维投影空间里把这个判别边界画出来,看看它长什么样:

lda_2d = LinearDiscriminantAnalysis() lda_2d.fit(X_train_lda, y_train) x_min, x_max = X_train_lda[:, 0].min() - 0.5, X_train_lda[:, 0].max() + 0.5 y_min, y_max = X_train_lda[:, 1].min() - 0.5, X_train_lda[:, 1].max() + 0.5 xx, yy = np.meshgrid(np.linspace(x_min, x_max, 400), np.linspace(y_min, y_max, 400)) Z = lda_2d.predict(np.c_[xx.ravel(), yy.ravel()]).reshape(xx.shape) plt.figure(figsize=(9, 6)) plt.contourf(xx, yy, Z, alpha=0.25, cmap="Set1") for i in range(3): idx = y_train == i plt.scatter(X_train_lda[idx, 0], X_train_lda[idx, 1], label=wine.target_names[i], edgecolor="white", alpha=0.8) plt.xlabel("LD1") plt.ylabel("LD2") plt.title("二维 LDA 投影空间中的线性决策边界") plt.legend() plt.grid(alpha=0.3) plt.show()

这里我先用 LDA 把原始特征压到二维,再在二维空间里训练一个新的 LDA 分类器,用网格预测画出边界。你会发现边界就是几条直线——LDA 的判决面天生是线性的,这是它简单、可解释、不容易过拟合的根本原因。

3.5 把 LDA 当分类器评估

LDA 不只是降维工具,它本身就是一个完整的分类器。直接用原始标准化特征去训练和预测:

lda_clf = LinearDiscriminantAnalysis() lda_clf.fit(X_train_sc, y_train) y_pred = lda_clf.predict(X_test_sc) print("测试集准确率: {:.4f}".format(accuracy_score(y_test, y_pred))) print(classification_report(y_test, y_pred, target_names=wine.target_names)) print(confusion_matrix(y_test, y_pred))

一组典型的输出长这样(你本地跑出来的数字会略有波动):

测试集准确率: 0.9815 precision recall f1-score support 0 1.00 1.00 1.00 18 1 0.96 1.00 0.98 22 2 1.00 0.94 0.97 14 accuracy 0.98 54 macro avg 0.99 0.98 0.98 54 weighted avg 0.98 0.98 0.98 54

葡萄酒数据集比较简单,LDA 直接跑出 98% 的准确率很正常。别急着高兴,真实项目里数据噪声大、边界交叠,准确率通常不会有这么好看。这个 Demo 的意义在于让你理解完整的评估流程:准确率看总体,classification_report看每个类别的精确率和召回率,confusion_matrix看具体在哪些类之间混淆。

3.6 一个值得做的实验:降维后喂给其他模型

LDA 降维到底保留了多少信息?有个很直观的验证方法:分别用原始 13 维特征和 LDA 压出来的 2 维特征训练同一个随机森林,比较测试集准确率:

from sklearn.ensemble import RandomForestClassifier rfc_13 = RandomForestClassifier(n_estimators=200, random_state=42) rfc_13.fit(X_train_sc, y_train) acc_13 = accuracy_score(y_test, rfc_13.predict(X_test_sc)) print("原始 13 维特征随机森林准确率:", acc_13) rfc_2 = RandomForestClassifier(n_estimators=200, random_state=42) rfc_2.fit(X_train_lda, y_train) acc_2 = accuracy_score(y_test, rfc_2.predict(X_test_lda)) print("LDA 2 维特征随机森林准确率:", acc_2)

我在类似的几组数据上试过,结果往往很接近——2 维特征甚至能跑出和 13 维原始特征差不多的效果。这恰好说明 LDA 把几乎所有的类间可分信息都压进了这两个方向,剩下的维度大多是判别价值很低的“冗余”或者“噪声”。

4. 参数调试与真实项目里的使用细节

默认参数能跑通 Demo,但真实数据不会那么温柔。这一节把n_components、explained_variance_ratio_、shrinkage和priors这几个关键点讲透。

4.1 n_components 的取值边界

n_components默认是None,此时 sklearn 会取min(类别数 - 1, 特征数)。如果你只把它当分类器用,不需要降维,保持默认就好;如果你要可视化,通常设 2,因为二维平面最好画。

边界条件再强调一遍:二分类最多 1 个,三分类最多 2 个。设大了会报错,这个不是 bug,是数学约束。比如你想给三分类数据降到 3 维去配合某个三维可视化工具,LDA 做不到,你需要换其他方法。

还有一个常见困惑:既然二分类只能降到 1 维,那 LDA 还能拿来画二维图吗?不能,老老实实换 PCA 或者选两个原始特征画散点图。这是很多人在做二分类可视化时才发现的限制。

4.2 explained_variance_ratio_ 的正确读法

这个属性和 PCA 的explained_variance_ratio_名字很像,但含义有微妙区别。PCA 的方差解释率衡量的是“数据本身的方差被保留了多少”,LDA 的这个比例衡量的是“类间判别信息被保留了多少”。

读法上有个实用技巧:如果第一个判别方向的贡献比例已经超过 90%,说明分类所需的信息非常集中,你可以只保留第一维,后面接一个简单的分类器就够了。如果两个方向各占 60% 和 40%,说明信息分布比较均衡,可视化时两个轴都有价值。别盯着数字纠结,它的核心用途是帮你判断“降维后丢了多少可分性”。

4.3 shrinkage:拯救小样本高维数据

小样本高维是最常见的 LDA 失败场景。假设你的数据是 100 个特征、每个类别只有 5 个样本,类内散度矩阵 S_W 的维度是 100x100,样本数远小于特征数,矩阵不可逆,eigen求解直接崩,svd勉强能跑但结果泛化很差。

这时候shrinkage就是救命的。它的原理是给类内散度矩阵加上一个小的正则化项,让矩阵变得可逆、估计更稳定。你可以这样用:

lda_shrink = LinearDiscriminantAnalysis(solver="lsqr", shrinkage="auto") lda_shrink.fit(X_train_sc, y_train)

shrinkage="auto"是让 sklearn 根据数据自动估计收缩强度,通常比手动试值靠谱。如果auto的结果不理想,再考虑手动指定 0 到 1 之间的浮点数。一个直观类比:解方程时除以一个接近 0 的数,结果会爆炸;shrinkage相当于在除数上加一个小常数,让结果变得可控。

4.4 priors 与类别不平衡

LDA 默认根据训练集里各类别的出现比例估算先验概率。如果数据严重不平衡,少数类别会被多数类别“吞掉”,决策边界严重偏向多数类。此时可以手动设置priors来校准:

lda_balanced = LinearDiscriminantAnalysis(priors=[0.5, 0.25, 0.25]) lda_balanced.fit(X_train_sc, y_train)

priors会同时影响判别方向和决策边界,因为它改变了各类在类间散度中的加权方式。你不需要让 priors 等于真实业务比例,而是可以通过调整它来平衡查全率。比如风控场景里欺诈样本只占 1%,如果你把欺诈类的 prior 调高,模型对欺诈的召回率会上升,代价是误报增加。这类取舍没有标准答案,用交叉验证去评估你真正关心的指标。

5. 最容易踩的几个坑与排查思路

LDA 的 API 简单到半小时就能跑通,但实际项目里的坑往往藏在数据本身。这一节讲的都是我自己踩过、或者帮别人排查过的问题。

5.1 数据泄漏:整个数据先 fit_transform 是头号错误

新手最常见的错误长这样:

# 错误示范,不要这样写 scaler = StandardScaler() X_scaled = scaler.fit_transform(X) # 先在整个数据集上标准化 lda.fit_transform(X_scaled, y) # 再在整个数据集上做 LDA

这么写的问题在于:LDA 的投影方向和标准化的均值和方差都用到了全部样本的信息,包括“测试集”的分布。你之后无论怎么切分,评估出来的准确率都是虚高的,模型上线后面对真正没见过的新数据,性能会明显回落。

正确姿势是三步走:先切分,再在训练集上fit标准化器和 LDA,最后用训练好的对象去transform测试集。更省心的做法是直接用Pipeline:

from sklearn.pipeline import make_pipeline pipe = make_pipeline( StandardScaler(), LinearDiscriminantAnalysis() ) pipe.fit(X_train, y_train) y_pred = pipe.predict(X_test)

用Pipeline的好处是它强制你按正确顺序执行,从机制上杜绝数据泄漏。我后来所有分类项目都习惯性地用Pipeline包裹,不只是为了省代码,更重要的是防自己手滑。

5.2 协方差相等假设不成立时:LDA 变 QDA

LDA 假设所有类别共享同一个协方差矩阵。现实中经常不是这样——一类数据非常集中,另一类特别分散,两类各自的“形状”差异很大。这时候线性边界就不够用了,应该考虑二次判别分析(QDA)。

QDA 给每个类别单独估计一个协方差矩阵,决策边界从直线变成二次曲线:

from sklearn.discriminant_analysis import QuadraticDiscriminantAnalysis qda = QuadraticDiscriminantAnalysis() qda.fit(X_train_sc, y_train) y_pred_qda = qda.predict(X_test_sc) print("QDA 测试集准确率:", accuracy_score(y_test, y_pred_qda))

怎么判断该不该换 QDA?我是这样做的:先分别用 LDA 和 QDA 做五折交叉验证,比较平均准确率;如果 QDA 明显更好,说明“类间协方差不等”的假设成立。需要注意,QDA 每类都要估计一个协方差矩阵,参数比 LDA 多,小样本时容易过拟合,样本量不足别硬上。

5.3 离群点、共线性与小样本

LDA 用均值作为类别位置的估计,而均值对离群点极其敏感。一个极端异常值就能把某个类的中心拉偏,导致整个判别方向跟着歪。遇到这种情况,先做离群点筛查或者用更稳健的标准化方式,别直接拿原始数据跑。

特征高度相关是另一个隐性坑。共线性特征会让散度矩阵变得病态,eigen求解可能直接出 NaN,svd虽然能算但结果也不稳。我的排查顺序是:先看特征相关矩阵,如果有一堆相关系数超过 0.9 的特征,要么先做 PCA 去相关,要么加shrinkage稳定求解。

小样本问题前面提过,再补一个判断标准:训练集准确率很高但交叉验证准确率波动巨大,十有八九是散度矩阵不稳定。换成lsqr + shrinkage="auto"之后波动通常会明显收窄。

5.4 不要拿 coef_ 当特征重要性直接解读

LDA 训练完会有一组coef_,很多人习惯把它当特征重要性来排序。这个用法在 LDA 上不太靠谱。coef_的意义是决策函数f(x) = coef_ · x + intercept_里的系数,它的符号和大小受标准化方式、特征相关性的影响。两个高度相关的特征会把重要性分摊,单看某个coef_的数字很容易得出错误结论。

如果你需要解释模型,更稳妥的做法是算置换重要性(permutation importance),或者直接用 SHAP 这类工具。LDA 的coef_更适合用来做快速的系数符号检查,而不是严谨的特征筛选。

6. 从 LDA 到 QDA:选型对比与一点实战经验

最后一个环节,把 LDA 放进更大的模型选型框架里看。很多读者会问:我到底该用 LDA、QDA 还是逻辑回归?这个问题没有万能答案,但有几个判断依据很明确。

6.1 LDA vs QDA vs 逻辑回归:关键取舍

模型决策边界协方差假设降维能力小样本表现优先选择场景
LDA线性各类共享可降到类别数-1较好样本少、特征多、需要可视化
QDA二次各类独立不支持一般各类方差差异明显、样本充足
逻辑回归线性无强分布假设不支持较好只需要概率、已有完整特征工程

QDA 不支持n_components参数,它只能当分类器用,不能输出降维后的坐标。逻辑回归本身不降维,但它对特征的分布假设比 LDA 宽松,而且输出的是经过校准的概率,很多业务场景更喜欢这个特性。

6.2 一个实际选型复盘

之前在某个内部模拟项目里,我遇到的数据大概是这样的:特征维度 30、样本量 200、三分类且类别不平衡。第一次直接用 LDA 默认参数,能跑,但交叉验证的准确率波动很大,明显是小样本导致的散度矩阵不稳定。我把 solver 换成lsqr并开启shrinkage="auto"之后,波动收敛了很多。后来检查各类协方差,发现某一类的方差明显比其他类大,又试了 QDA,交叉验证分数小幅提升,但换来的代价是特征交互和过拟合风险更高。最后我还是保留了 LDA + shrinkage 方案,因为项目里业务方需要一张二维的类别分布图来解释结果,LDA 正好能一边降维一边给出分类边界。这个案例说明:选模型不是选最好的,而是选“够用且能解释”的。

6.3 一点使用建议

最后分享几个我在实际操作中的习惯。

第一,LDA 降维出来的特征是“为分类而生”的,它只在有标签的场景下有判别意义。如果你想用降维后的特征做聚类或探索性分析,优先考虑 PCA 而不是 LDA。

第二,训练完之后多利用lda.means_。这个属性保存了每个类别在原始特征空间的中心点,配合投影矩阵就能算出类中心在判别空间里的坐标。给业务方讲“这两类到底差在哪”的时候,这个信息比一堆特征贡献度数字直观得多。

第三,遇到大型高维数据时,可以考虑“PCA 去噪 + LDA 分类”的组合。先用 PCA 把维度压到合理范围,去掉噪声和冗余,再在保留的维度上用 LDA,这个组合在有些项目里比直接硬跑 LDA 更稳。原因是 PCA 先把病态的散度矩阵“清理”了一遍,LDA 拿到的输入更干净。

LDA 这个工具,看起来朴素,但它是理解“有监督降维”思想的最佳入口。把它和 PCA 的对比想明白,很多后续的高级方法——比如偏最小二乘、流形学习里的监督变种——你都能举一反三。代码本身不复杂,复杂的是对数据形态的判断和对假设的检验。希望这篇内容能帮你把这两件事都拿捏住。

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

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

立即咨询