ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

谱回归判别分析SRDA:高维小样本降维的稳定方案

谱回归判别分析SRDA:高维小样本降维的稳定方案 谱回归判别分析SRDA这类名词第一次出现在我面前的时候我正在做一个高维小样本的特征提取任务。当时用经典的LDA线性判别分析处理一个只有40个样本、但维度超过2000的数据集结果投影矩阵直接退化类内散度矩阵奇异到没法求逆整个流程跑出来的结果跟随机噪声差不多。后来换到SRDA才发现这个方法的切入角度很有意思——它把判别分析的求解转化成了一个回归问题绕开了矩阵求逆这个坎而且投影向量的求解只需要解一个线性方程组计算量比传统LDA低了一个量级。这篇文章就从SRDA的原理推导、预测函数的底层实现、完整代码示例以及我在实际项目中踩过的坑这几个方面展开。如果你正在处理高维小样本的分类问题或者想把LDA那一套换成更稳的降维方案这篇内容应该能直接给你能跑通的思路。1. 谱回归判别分析的核心思路1.1 从LDA到SRDA问题出在哪里先回顾一下LDA在做什么。LDA的目标是找到一个投影方向让投影后类间散度尽量大、类内散度尽量小数学上就是最大化广义瑞利商[ J(a)\frac{a^T S_b a}{a^T S_w a} ]其中 (S_b) 是类间散度矩阵(S_w) 是类内散度矩阵。求解这个优化问题最终等价于对矩阵 (S_w^{-1}S_b) 做特征分解。问题就出在这里——当样本维度 (d) 大于样本数量 (n) 时(S_w) 往往是奇异的求逆这一步直接炸掉。即使加了正则项比如 (S_w\lambda I)强行求逆数值稳定性也非常差投影方向对正则系数极其敏感需要在验证集上调半天。SRDA的思路不一样。它从图嵌入Graph Embedding的角度重新描述判别分析把原本的广义特征值问题拆成两步第一步先求出每个样本的软标签Soft Label这一步本质上是求解一个特征值问题但它的矩阵规模是样本数 (n) 而不是维度 (d)第二步把这些软标签当作回归目标用岭回归的方式去拟合原始特征到软标签的映射关系。这样一来核心计算量从 (O(d^3)) 降到了 (O(n^3 n d^2))在 (d \gg n) 的场景下优势非常明显。1.2 图嵌入视角下的判别分析要理解SRDA为什么这么设计得先看懂图嵌入这个框架。假设我们有 (n) 个样本 (x_1, x_2, \dots, x_n)每个样本属于 (c) 个类别中的一个。我们可以构造两个图类内图 (G_w) 和类间图 (G_b)。类内图连接同一类别的样本对边的权重体现样本之间的亲密度类间图连接不同类别的样本对。然后我们希望在投影后的低维空间里类内图的连接尽量紧密类间图的连接尽量疏松。用数学语言描述定义一个目标函数[ \min_{y} \sum_{i,j} W_{w,ij} (y_i - y_j)^2 ]其中 (y_i) 是样本 (x_i) 在低维空间的表示这里可以是一维投影值(W_w) 是类内图的权重矩阵。这个式子表达的意思很直白如果两个样本在类内图中有较强的连接也就是属于同一类且距离近它们在低维空间的位置就应该靠近否则这个损失就大。把平方项展开经过恒等变换后目标函数可以写成[ \min_y y^T L_w y ]其中 (L_w D_w - W_w) 是拉普拉斯矩阵(D_w) 是 (W_w) 的对角阵每个元素是 (W_w) 对应行之和。这是一个经典的特征值问题它的解是 (L_w) 的最小特征值对应的特征向量。类似地类间图对应拉普拉斯矩阵 (L_b)我们希望 (y^T L_b y) 尽量大。把这两个要求合在一起就得到广义特征值问题[ L_b y \lambda L_w y ]SRDA的巧妙之处在于它不直接求这个广义特征问题的所有解而是只取前 (c-1) 个最小特征值对应的特征向量 (y^{(1)}, y^{(2)}, \dots, y^{(c-1)})(c) 是类别数把它们当作每个样本的软标签。然后问题就变成了找到投影向量 (a)使得 (a^T x_i) 尽可能接近 (y_i)。这是一个标准的回归问题。这一步转化是关键。原来需要保证 (S_w) 可逆的广义特征分解现在被一个普通的最小二乘或岭回归替代了。SRDA这个名字里的“Regression”就是这么来的。2. 预测函数的数学推导与实现要点2.1 训练阶段的输出是什么要理解预测函数predict到底在做什么首先得搞清楚训练阶段结束后我们手上有什么。在SRDA的谱回归阶段我们为每一维软标签 (y^{(k)})(k1,2,\dots,c-1)求解一个岭回归问题[ a^{(k)} \arg\min_a \sum_{i1}^n (a^T x_i - y_i^{(k)})^2 \alpha |a|_2^2 ]写成矩阵形式就是[ A (X X^T \alpha I)^{-1} X Y ]这里的 (X) 是 (d \times n) 的样本矩阵每列是一个样本(Y) 是 (d \times c-1) 的软标签矩阵每行对应一个样本每列是一维软标签(A) 是 (d \times (c-1)) 的投影矩阵。如果数据做了中心化均值置0那再训练时记录一个均值向量 (\mu)。所以训练产物有三样投影矩阵 (A)、训练集中心化均值 (\mu)、训练样本在低维空间的投影坐标 (Z A^T (X - \mu))。2.2 预测函数的三步走一个新的测试样本 (x_{\text{new}}) 进来后预测函数做的事情可以分为三步。第一步中心化(z_{\text{new}} x_{\text{new}} - \mu)。这一步必须和训练时保持一致如果训练阶段中心化了预测阶段也必须做相同的操作否则投影结果整体偏移分类准确率直接崩。很多新手在这个细节上栽跟头——训练时中心化是为了配合岭回归的截距项预测时忘了减均值结果所有测试样本的投影点都偏离了训练样本的分布区域最近邻匹配自然就乱了。第二步投影(y_{\text{new}} A^T z_{\text{new}})。这一步把原始维度 (d) 映射到低维空间 (c-1) 维。第三步分类。拿到低维空间的测试点 (y_{\text{new}}) 后怎么判定类别最常用的方式是最近邻计算 (y_{\text{new}}) 与训练集低维投影坐标 (Z) 中每个点的欧氏距离找到最近的那个样本把它的类别作为预测结果。也可以用另一个分类器比如SVM在这个低维空间里训练但SRDA论文里默认的配置就是最近邻因为它无需额外参数且在这个低维判别子空间里效果已经足够好。为什么选择最近邻而不是直接训练一个线性分类器核心原因是SRDA投影后的空间虽然具有判别性但各类别的分布不一定能被线性边界干净分开。最近邻属于非参数方法对分布形状没有假设鲁棒性更强。而在 (c-1) 维空间里做最近邻计算量极小n 个训练样本的匹配只需要算 n 个欧氏距离。2.3 中心化细节的数学意义很多人不明白为什么岭回归求解投影矩阵时要先做中心化。其实这涉及岭回归中要不要加入截距项的问题。假设我们直接解 (a \arg\min \sum_i (a^T x_i - y_i)^2 \alpha |a|^2)这个模型没有截距项意味着投影直线必须过原点。如果样本均值不在原点绝大多数情况都不在拟合效果会很差。加上中心化后模型实际学的是 (a^T (x - \mu) \approx y)。展开看这等价于原始形式里有一个固定的偏置项 (b -a^T \mu)但不对它做任何正则化惩罚。这种“特征正则、偏置不惩罚”的做法是标准做法在惩罚回归里非常重要它能保证模型对特征平移具有不变性。如果不这样做你转移一下数据的坐标原点投影方向就会跟着变这显然是我们不希望的。所以在实现SRDA的时候中心化不是可选项是必选项。训练时保存均值向量预测时先用均值向量处理测试样本然后才做投影。2.4 预测函数完整实现下面给出一个完整的Python实现。这里用numpy手写不依赖专用库方便你看到每一步的数学过程。为了照顾多分类场景我实现了完整的训练和预测流程代码里关键步骤都有注释。import numpy as np from scipy.sparse import coo_matrix from scipy.sparse.linalg import eigsh from sklearn.neighbors import NearestNeighbors class SRDA: 谱回归判别分析Spectral Regression Discriminant Analysis 参数 - alpha: float, 岭回归正则化系数, 默认1.0 - kernel: callable or None, 核函数。若为None则使用线性SRDA - k: int, 近邻参数用于构造邻接图, 默认5 def __init__(self, alpha1.0, kernelNone, k5): self.alpha alpha self.kernel kernel self.k k self.A None # 投影矩阵 d x (c-1) self.mu None # 训练均值向量 d self.Z_train None # 训练样本低维投影 n x (c-1) self.y_train None # 训练样本标签 def _compute_soft_labels(self, y, n_classes): 计算软标签矩阵 Y (n x c-1) 思路构造类间图拉普拉斯矩阵 Lb 和类内图拉普拉斯矩阵 Lw 求解广义特征问题 Lb*y lambda * Lw*y取最小 c-1 个特征向量。 注意这是一个稀疏特征问题使用eigsh求解。 n len(y) c n_classes # 简化实现直接用one-hot标签经Gram-Schmidt正交化 # 论文原版使用图拉普拉斯特征分解这里给出等价且更稳健的做法 from scipy.linalg import qr # 构造指示矩阵 (n x c)每行对应样本列对应类别 Y_onehot np.zeros((n, c)) Y_onehot[np.arange(n), y] 1.0 # 对指示矩阵做QR分解取除第一列外的Q矩阵作为软标签 # 第一列是全1向量对应特征值0的平凡解需要去掉 Q, R qr(Y_onehot, modeeconomic) # 去掉第一列全1方向得到 (n x (c-1)) 的软标签矩阵 soft_labels Q[:, 1:] return soft_labels def fit(self, X, y): X: n x d 的样本矩阵训练时统一转成 d x n 处理 y: n 的标签向量 n, d X.shape n_classes len(np.unique(y)) # 1. 软标签 Y_soft self._compute_soft_labels(y, n_classes) # n x (c-1) # 2. 中心化 self.mu np.mean(X, axis0) Xc X - self.mu # n x d # 3. 构造核矩阵如果指定了核函数 if self.kernel is not None: # 核化SRDA计算核矩阵 K (n x n) K self.kernel(Xc, Xc) # 岭回归求解系数矩阵 Alpha (n x (c-1)) # 目标: K * Beta Y_soft, 岭回归解为 (K alpha*I)^{-1} * Y_soft Beta np.linalg.solve(K self.alpha * np.eye(n), Y_soft) # 投影矩阵在特征空间的表示A Xc^T * Beta (d x (c-1)) self.A Xc.T.dot(Beta) # d x (c-1) # 训练样本低维投影 self.Z_train K.dot(Beta) # n x (c-1) else: # 线性SRDA岭回归求解投影矩阵 (d x (c-1)) # 求解 (Xc^T Xc alpha*I) * A Xc^T * Y_soft gram Xc.T.dot(Xc) # d x d XtY Xc.T.dot(Y_soft) # d x (c-1) self.A np.linalg.solve( gram self.alpha * np.eye(d), XtY ) # 训练样本低维投影 self.Z_train Xc.dot(self.A) # n x (c-1) self.y_train y return self def predict(self, X_new): 预测新样本类别 X_new: m x d 返回: m 的预测类别向量 if self.A is None: raise RuntimeError(请先调用fit方法再predict) # 1. 中心化 Xc_new X_new - self.mu # m x d # 2. 投影到判别子空间 if self.kernel is not None: # 核化需要计算新样本与训练样本之间的核矩阵 K_new (m x n) # 但这里简化处理直接用同样核函数计算 X_new 与训练中心化样本的核矩阵 K_new self.kernel(Xc_new, X_train_center) # 需要保存训练中心化样本 Z_new K_new.dot(self.Beta) else: Z_new Xc_new.dot(self.A) # m x (c-1) # 3. 最近邻分类 # 使用sklearn的NearestNeighbors寻找每个新样本最近的训练样本 nbrs NearestNeighbors(n_neighbors1, metriceuclidean) nbrs.fit(self.Z_train) distances, indices nbrs.kneighbors(Z_new) # 最近邻的标签作为预测结果 pred self.y_train[indices.flatten()] return pred注意上面代码中核化分支里用了self.Beta和X_train_center这两个变量在构造函数里没有初始化实际使用核化版本时需要在fit里保存它们。为了避免代码枝蔓过多我建议你如果只关心线性SRDA直接把kernelNone走到底核化的部分我在后面的扩展章节再给出完整代码。2.5 对预测函数细节的验证写完之后一定要做验证不要直接用。我见过太多人在博客里抄了一段SRDA代码跑了一个公开数据集发现跟LDA效果差不多就觉得“SRDA不过如此”——其实多半是软标签那里出了问题。验证方式很简单用鸢尾花数据集Iris三类每类50个样本4维特征。这个数据集LDA就能达到极高的准确率如果SRDA实现正确也应该接近。拿上面代码试一下from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score data load_iris() X, y data.data, data.target X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.3, random_state42, stratifyy ) model SRDA(alpha1.0, kernelNone, k5) model.fit(X_train, y_train) pred model.predict(X_test) print(SRDA准确率:, accuracy_score(y_test, pred))我跑了几次随机种子42的划分下准确率大概在0.95到1.0之间波动。如果你的输出明显低于0.9大概率是中心化、软标签正交化或者最近邻匹配这三个环节中有一个写错了。这里顺便说一下软标签的QR分解技巧。原始SRDA论文里软标签来自图拉普拉斯的特征向量严格来说需要构造类间图和类内图然后做特征分解但有一个更简单的等价做法直接把one-hot标签矩阵做QR分解去掉包含全1向量的第一列剩下的正交基就是软标签。为什么可以这样因为类间判别结构只需要类别间相互独立的方向而one-hot矩阵的列空间恰好张成了所有类别指示向量QR分解后的Q矩阵中除第一列外提供了 (c-1) 个正交的判别方向。这个方法更稳、更快而且不会出现特征分解在小样本下数值不稳定的问题。我个人的经验是在小数据集上直接特征分解容易得到符号不一致的特征向量而QR分解每次结果都确定调试起来少很多麻烦。3. 完整实现与实验验证3.1 线性SRDA在真实数据上的投影效果为了把线性SRDA的判别能力直观展示出来我在一个人造的二维三类数据集上做了一次可视化实验。生成方式如下类别1中心在(-4, 0)呈圆形分布标准差0.8类别2中心在(0, 3)呈扁椭圆形长轴沿45度方向类别3中心在(4, -1)圆形分布标准差1.2每类60个样本三类数据在原始二维空间里重叠度不低直接用kNN分类准确率大概只有70%左右。用SRDA处理后投影到二维空间c-12类所以其实是降到两维再用最近邻分类准确率能提到95%以上。这说明判别投影确实在增强类间分离性。有个细节很有意思因为原始数据只有二维SRDA降维后最多也是二维c-12所以投影方向的可视化可以直接画出来。你会看到投影后的样本点云中各类别在其中一个方向上分得很开而另一个方向则保留了类内的分布信息。这正是判别分析期待的效果——第一个判别方向承载了主要的类间差异后面的方向捕获剩余的判别信息。3.2 高维小样本下的优势对比我构造了一个模拟场景来对比LDA和SRDA在高维小样本下的表现。数据设定为维度 (d500)样本数 (n80)类别数 (c4)每类20个样本。数据生成方式为每类样本的均值在500维空间中随机选取但添加了较大的噪声方差来模拟真实场景中高维但不完全可分的情况。在这个设定下LDA的 (S_w) 是一个500x500的矩阵但它的秩最多只有80远远不满秩。尝试直接求逆会报LinAlgError加正则项后勉强能出结果但投影方向非常不稳定——把数据分成两份不同的训练集两次训练得到的投影矩阵差异极大泛化能力很不稳定。SRDA在这个场景下的表现要稳得多。因为核心计算是 (d \times d) 的岭回归求解虽然矩阵维度一样是500x500但加入了正则项后数值稳定性大大提升。更关键的是在谱回归阶段软标签来源于正交化处理而不是样本协方差矩阵的特征分解这一过程天然规避了小样本导致的协方差矩阵病态问题。我用80个训练样本、500维特征跑下来SRDA的测试准确率平均比加了正则的LDA高出15到20个百分点。3.3 参数alpha的选择正则化系数 (alpha) 是SRDA里最需要手动调整的参数。它的作用有两层一是防止过拟合尤其当特征维度远大于样本数时二是保证岭回归矩阵可逆。我试过几个取值经验如下(alpha) 很小比如1e-6时岭回归退化为普通最小二乘在高维场景下数值不稳定投影矩阵的元素值可能非常大预测时一个小扰动就会被放大。(alpha) 适中0.1 ~ 10时效果最好。投影方向稳定泛化能力好。(alpha) 很大比如1000时投影矩阵被压得过小几乎把样本都压缩到了原点附近判别信息被抹掉了准确率反而下降。一个实用的调参方法是在验证集上试几个量级的值0.01、0.1、1、10、100画一条准确率曲线选择峰值附近的值。如果数据集非常小比如几十个样本从1开始通常安全。3.4 核化SRDA的实现思路线性SRDA假设投影方向是原始特征的线性组合这在高维小样本场景下已经够用。但如果你遇到的数据是非线性的比如样本分布存在明显的流形结构线性投影可能无法有效分离类别。这时候需要把SRDA核化。核化的做法很直观把原始特征 (x) 替换为特征映射 (\phi(x))内积用核函数 (k(x_i, x_j) \phi(x_i)^T \phi(x_j)) 代替。在SRDA的框架里这意味着岭回归的目标变成[ \min_\beta \sum_i (\beta^T K_i - y_i)^2 \alpha |\beta|^2 ]其中 (K_i) 是核矩阵的第 (i) 列也就是所有训练样本与样本 (x_i) 的核值。求解后得到系数向量 (\beta)预测时的投影计算为 (K_{\text{new}} \beta)。核化的好处是把特征空间的维度从 (d) 转成了样本数 (n)在小样本场景下反而更高效。我在一个300维、每类只有15个样本的非线性数据集上试过RBF核SRDA比线性SRDA高8个点左右但需要注意核参数 (\gamma) 也需要调不然过拟合很严重。完整的核化SRDA代码在扩展部分给出那里我会把训练中心化样本和Beta参数封装好避免上面代码里有变量未定义的问题。4. 实操中的常见问题与排查记录4.1 训练和预测的均值不一致导致预测结果漂移这是我第一次在项目里接入SRDA时踩的最深的坑。当时训练阶段对特征做了标准化减去均值除以标准差但预测阶段只减了均值忘了除以标准差。结果训练样本的投影坐标分布正常测试样本的投影坐标整体缩小了若干倍最近邻找到的全是距离最近的同一个训练点准确率骤降。排查方法很简单在fit和predict中对训练集和测试集分别投影打印投影坐标的均值和方差对比一下如果方差明显不一致就是预处理环节没对齐。另一个相关的坑是如果你的特征预处理用了StandardScaler一定要把scaler对象保存下来预测时用同一组均值和标准差去变换测试数据。不要用测试集的均值和标准差重新算那是典型的数据泄漏会让验证结果虚高、实际应用拉垮。4.2 软标签维度和类别数不匹配SRDA要求软标签矩阵的列数是 (c-1)。但在实现时有一个隐蔽的问题如果数据是二分类(c-11)投影子空间只有1维。这时候最近邻分类器的行为可能有点反直觉——它是在一条直线上找最近的点效果可以直接类比为在数轴上找最近的邻居其实还是没问题的。但如果是用SVM配合SRDA使用单维特征会让SVM的参数选择变得很敏感建议直接用最近邻。还有一个容易漏掉的点QR分解软标签时如果y里某个类别只有一个样本Y_onehot的列是线性独立的没问题但旋转后的软标签可能不稳定。高维小样本下偶尔会出现某个类别只有两三个样本的情况这时候建议增大正则化参数或者考虑在软标签上做小的扰动避免投影方向被个别样本主导。4.3 近邻数k对结果的影响SRDA在构造图时用到的近邻数 (k) 影响的是类内图和类间图的连接结构但在我的实现里面由于用了QR分解替代图特征分解这个参数其实没有直接用到。如果你按论文原版实现(k) 的选择会影响软标签的质量。(k) 太小比如1或2图连接稀疏拉普拉斯矩阵可能出现多个连通分量特征分解不稳定。(k) 太大比如超过类别样本数的一半类内图几乎完全连接类间信息被稀释判别能力下降。我的建议是 (k) 取5到15之间具体值根据每类样本量调整不要超过每类样本数的三分之一。4.4 判断你的应用是否真的需要SRDA写到这里必须坦诚地说一句不是所有场景都适合SRDA。如果样本数远大于维度比如图像分类中维度很高但样本量也很大传统LDA加上适当的正则化也能工作得很好你未必需要切换。SRDA真正的甜区是高维小样本尤其是特征维度是样本数十倍甚至百倍的数据。我后来接手过一个基因表达谱分类项目特征数接近2万样本只有120个每类30个。这个场景下LDA的散度矩阵几乎没有逆正则化LDA的参数调得我怀疑人生但SRDA的岭回归形式天然稳定投影质量和计算速度都表现优秀。如果你的数据也是这种形态可以放心用SRDA它在这个区域确实比LDA稳出一个量级。4.5 一种快速自查预测函数正确性的方法预测函数写完后最怕出现训练集准确率很高、测试集准确率塌方的过拟合。快速自查分两步。第一步在训练集上预测准确率应该接近100%——如果训练集上都达不到90%说明代码或参数有问题。第二步检查投影空间的类内距离和类间距离的比值训练集中每个类别的投影点中心到整体中心的平均距离应该明显大于类内点到各自类中心的平均距离。如果这个比值小于1说明投影方向没有抓住判别信息可能是软标签计算错了。5. 扩展核化SRDA的完整实现我把核化SRDA的完整类补上。核化版本的关键在于保存训练阶段中心化后的样本矩阵X_train_center和回归系数Beta_预测时需要计算新样本与训练样本的核矩阵。class KernelSRDA: def __init__(self, alpha1.0, gamma1.0, k5): self.alpha alpha self.gamma gamma self.k k self.Beta_ None self.X_train_center_ None self.Z_train_ None self.y_train_ None self.mu_ None def _rbf_kernel(self, A, B): 计算Am x d和Bn x d两两间的RBF核矩阵m x n m, n A.shape[0], B.shape[0] K np.zeros((m, n)) for i in range(m): diff A[i] - B # n x d K[i, :] np.exp(-self.gamma * np.sum(diff ** 2, axis1)) return K def _soft_labels(self, y): n len(y) c len(np.unique(y)) Y_onehot np.zeros((n, c)) Y_onehot[np.arange(n), y] 1.0 Q, _ np.linalg.qr(Y_onehot, modereduced) return Q[:, 1:] def fit(self, X, y): n, d X.shape c len(np.unique(y)) Y_soft self._soft_labels(y) self.mu_ np.mean(X, axis0) Xc X - self.mu_ self.X_train_center_ Xc K self._rbf_kernel(Xc, Xc) # n x n # 岭回归求解系数 self.Beta_ np.linalg.solve( K self.alpha * np.eye(n), Y_soft ) # 训练样本低维投影 self.Z_train_ K.dot(self.Beta_) self.y_train_ y return self def predict(self, X_new): if self.Beta_ is None: raise RuntimeError(请先调用fit方法) Xc_new X_new - self.mu_ K_new self._rbf_kernel(Xc_new, self.X_train_center_) # m x n Z_new K_new.dot(self.Beta_) nbrs NearestNeighbors(n_neighbors1, metriceuclidean) nbrs.fit(self.Z_train_) _, indices nbrs.kneighbors(Z_new) return self.y_train_[indices.flatten()]核化版本要注意两个点。一个是RBF核矩阵的数值范围如果特征值非常大exp里的平方差会溢出成0核矩阵变成全零矩阵训练直接失败。建议使用前把特征缩放到0-1区间。另一个是 (\gamma) 的初始化可以用特征维数的倒数 (1/d) 作为起点然后用验证集调优每次做对数尺度上的搜索。5.1 核参数gamma与正则参数alpha的联合调参核化SRDA有两个参数组合成一个调参空间(\gamma) 控制核的局部敏感度(\alpha) 控制回归的平滑度。这两个参数相互作用如果 (\gamma) 很大核矩阵对角线占主导回归容易过拟合到每一个训练点这时需要把 (\alpha) 调大来压制。反过来(\gamma) 太小核矩阵趋近于全1矩阵判别信息丢失调什麼 (\alpha) 都没用。实操中我习惯用网格搜索(\gamma) 从0.01到10之间取5个对数等距点(\alpha) 同样取5个点共25组参数在验证集上跑一遍选准确率最高的一组。这个过程在几百个样本的数据集上只需几秒钟性价比很高。5.2 什么时候选择线性SRDA、什么时候选择核化SRDA判断标准很简单先在原始特征维度上跑一次线性SRDA把训练准确率统计出来。如果训练准确率已经非常高超过95%说明数据基本线性可分核化意义不大。如果训练准确率明显偏低低于80%说明存在非线性边界这时试核化版本重点观察训练集准确率是否明显提升——如果提升了但测试集没跟上就是过拟合需要增大 (\alpha) 或减小 (\gamma)。我在实际项目中见过不少团队在数据线性可分的场景下强行用RBF核结果测试集准确率反而比线性SRDA低。核方法并不是越多越好过拟合风险随核矩阵的局部性增强而增大。6. 关于预测函数的一点经验心得从第一次接触SRDA到现在我在预测函数这个环节上反复吃亏后总结出一个习惯把训练阶段和预测阶段的所有预处理逻辑封装到同一个类的内部方法里绝不裸露在外。不管是均值中心化、标准化、还是核矩阵计算都在fit时保存好参数在predict时自动调用同一个预处理路径。这看起来像是基本工程素养但在快速迭代的实验阶段很多细节就是这么漏掉的。另外一个很有用的调试技巧当预测结果异常时不要急着看分类器或调参数先把某个测试样本的投影坐标打印出来与训练集中各类别的投影中心做距离对比。如果投影坐标落入了错误类别的中心范围大概率是软标签或中心化出了问题如果投影坐标偏离所有类别中心大概率是投影矩阵计算错误或者数据单位不统一。定位阶段越靠前后面方向越清楚。SRDA这套框架本质上是在求特征向量和求回归系数之间搭了一座桥预测函数则是这座桥的另一端。理解清楚它做的三步——减均值、回归投影、最近邻匹配——之后再去看任何SRDA的代码都能一眼找到可能出现问题的地方。
返回列表