
简介这份资源围绕拉普拉斯支持向量机LapSVM展开面向机器学习初学者与需要处理非线性分类任务的研究者帮助理解如何将SVM与图论中的拉普拉斯矩阵结合利用数据局部几何结构提升高维复杂数据的分类表现。压缩包共38个文件约155KB以m脚本为主辅以cpp、c、h等源码及mexglx、dll等编译文件另有mat数据、fig图形和txt说明覆盖算法实现、核函数计算与实验演示等环节。资源中提供了邻接矩阵构建、拉普拉斯矩阵计算、优化求解与核函数选择等关键步骤的代码示例并包含流形学习相关对比内容便于读者对照理论动手复现实验、观察分类边界与评估指标。目前已有108人学习适合希望深入掌握LapSVM原理与工程实现、并拓展非线性数据分析能力的读者参考。1. 拉普拉斯支持向量机当标注样本少得可怜时半监督学习怎么救场手上只有几十条带标签的样本却要训一个能上线的分类器这种场景做工业质检、医学影像筛查或者金融风控的同行都不陌生。拉普拉斯支持向量机Laplacian SVM常写作 LapSVM就是冲着这个痛点来的它把大量无标签样本的几何结构信息通过图拉普拉斯矩阵塞进 SVM 的正则项里让决策边界顺着数据流形走而不是只被那几个可怜的有标签点牵着鼻子跑。标题里的laplacian、lapsvm、svm-laplacian说的其实是同一件事——用拉普拉斯图正则约束 SVM。它适合标注成本高、无标签数据管够、且数据分布有明显簇结构的任务。如果你手上标签充足直接上标准 SVM 或梯度提升树更省事但当你面对的是“标注一条要几百块、无标签数据堆成山”的局面LapSVM 值得认真试一次。2. 拉普拉斯正则到底在优化什么从流形假设到图矩阵2.1 流形假设为什么无标签点也能约束决策边界半监督学习的底气来自两个假设聚类假设decision boundary 不该穿过高密度区域和流形假设高维数据其实躺在一个低维流形上。LapSVM 主要吃的是流形假设。直观理解如果两个样本在原始空间里离得很近那它们的预测输出也应该接近。无标签样本虽然不知道类别但它们的位置信息能告诉我们“哪些点应该被分到一起”。把这个直觉写成数学就是给每个样本建一个图每个点是一个节点近邻之间连边边的权重反映相似度。整张图的“平滑程度”用图拉普拉斯二次型衡量$$\sum_{i,j} W_{ij} |f(x_i) - f(x_j)|^2 \mathbf{f}^T L \mathbf{f}$$其中 $L D - W$ 是拉普拉斯矩阵$D$ 是度矩阵$W$ 是相似度权重矩阵。这个量越小说明函数 $f$ 在图上越平滑相邻点的输出越一致。LapSVM 就是把这个平滑项加到 SVM 的目标函数里让分类器在拟合有标签数据的同时别在无标签数据的高密度区域里乱切。2.2 LapSVM 的目标函数把平滑项塞进 hinge loss标准 SVM 的优化目标是最大化间隔、最小化 hinge loss。LapSVM 在此基础上加了一项$$\min_{f \in \mathcal{H}K} \frac{1}{l}\sum{i1}^{l} \max(0, 1 - y_i f(x_i)) \gamma_A |f|_K^2 \gamma_I \mathbf{f}^T L \mathbf{f}$$三个部分各司其职第一项是标准 hinge loss只管有标签的 $l$ 个样本第二项 $\gamma_A |f|_K^2$ 是 RKHS 范数控制模型复杂度防止过拟合第三项 $\gamma_I \mathbf{f}^T L \mathbf{f}$ 就是拉普拉斯正则让函数在整个图含无标签点上平滑。$\gamma_A$ 和 $\gamma_I$ 是两个关键超参前者管“拟合有标签数据有多狠”后者管“听无标签结构的话有多深”。按表示定理最优解可以写成核函数的线性组合 $f(x) \sum_{i1}^{n} \alpha_i K(x_i, x)$$n$ 是全部样本数有标签 无标签。代进去之后原问题变成一个带约束的二次规划可以用标准的 SVM 求解器思路去解只是核矩阵从 $l \times l$ 扩到了 $n \times n$。这也是 LapSVM 计算量比标准 SVM 大的根本原因——无标签样本越多核矩阵越大。2.3 图怎么建kNN 还是全连接权重用 RBF 还是 0/1图的质量直接决定 LapSVM 的效果这一步比调 $\gamma$ 还重要。常见做法有两种建图方式连边规则权重适用场景kNN 图每个点连最近的 k 个邻居0/1 或 RBF数据分布不均匀、簇结构明显全连接图所有点两两相连RBF 核权重样本量小几千以内、分布平滑kNN 图更稀疏计算省但对 k 敏感全连接图信息全但 $n$ 大时矩阵稠密内存吃不消。权重方面0/1 权重最简单RBF 权重 $W_{ij} \exp(-|x_i - x_j|^2 / (2\sigma^2))$ 更细腻但多了一个 $\sigma$ 要调。我一般先用 kNN RBF 权重起步k 取 5 到 10$\sigma$ 取所有样本间距离的中位数这个经验值在多数任务上不会太离谱。注意建图前一定要做特征标准化。不同量纲的特征直接算欧氏距离等于让数值大的特征单方面决定邻居关系图会建歪后面怎么调参都救不回来。3. 用 Python 把 LapSVM 跑起来从建图到求解的最小实现3.1 环境准备与数据构造LapSVM 没有像 scikit-learn 的SVC那样开箱即用的标准库常见做法是自己基于cvxopt或scipy.optimize写求解器或者用现成的半监督学习包。下面给一个基于cvxopt的最小可复现实现先造一份带两个簇的二维数据方便可视化验证。import numpy as np from sklearn.datasets import make_classification from sklearn.preprocessing import StandardScaler from sklearn.neighbors import kneighbors_graph # 造数据200个样本2类只有20个有标签 X, y make_classification(n_samples200, n_features2, n_informative2, n_redundant0, n_clusters_per_class1, random_state42) y np.where(y 0, -1, 1) # SVM 用 -1/1 标签 # 标准化建图前必做 scaler StandardScaler() X scaler.fit_transform(X) # 模拟标注稀缺只保留20个有标签样本 rng np.random.RandomState(0) labeled_idx rng.choice(len(X), 20, replaceFalse) unlabeled_idx np.setdiff1d(np.arange(len(X)), labeled_idx) y_labeled y[labeled_idx].astype(float)这段代码做了三件事生成两类线性不可分的数据、标准化、切出 20 个有标签样本。make_classification的参数n_clusters_per_class1保证每类是一个紧凑簇方便观察拉普拉斯正则是否真的让边界绕开无标签点密集区。实际任务里把X和y换成你自己的数据即可注意标签要转成 -1/1。3.2 构建拉普拉斯矩阵kNN 图与归一化def build_laplacian(X, k7, sigmaNone): 构建归一化图拉普拉斯矩阵 L I - D^{-1/2} W D^{-1/2} n X.shape[0] # kNN 邻接包含自身后面减掉 A kneighbors_graph(X, k, modeconnectivity, include_selfFalse).toarray() A np.maximum(A, A.T) # 对称化 # RBF 权重 if sigma is None: dists np.sqrt(((X[:, None, :] - X[None, :, :]) ** 2).sum(-1)) sigma np.median(dists[dists 0]) dists np.sqrt(((X[:, None, :] - X[None, :, :]) ** 2).sum(-1)) W A * np.exp(-dists ** 2 / (2 * sigma ** 2)) # 度矩阵与归一化拉普拉斯 d W.sum(axis1) d_inv_sqrt np.where(d 0, 1.0 / np.sqrt(d), 0) D_inv_sqrt np.diag(d_inv_sqrt) L np.eye(n) - D_inv_sqrt W D_inv_sqrt return L, W L, W build_laplacian(X, k7) print(L shape:, L.shape, 非零元素占比:, np.count_nonzero(L) / L.size)build_laplacian返回归一化拉普拉斯矩阵。归一化的好处是让不同度数的节点对平滑项的贡献更均衡避免高密度区域的点主导整个正则项。k7是邻居数样本量几百到几千时 5 到 10 都合理sigma默认取距离中位数这是 RBF 核的经典启发式。A np.maximum(A, A.T)做对称化因为kneighbors_graph生成的邻接不一定对称——A 是 B 的邻居B 不一定是 A 的邻居不对称的图会让拉普拉斯矩阵失去良好性质。3.3 求解 LapSVM把问题写成二次规划from cvxopt import matrix, solvers solvers.options[show_progress] False def lapsvm_fit(X, y_labeled, labeled_idx, L, gamma_A0.1, gamma_I0.05): 基于表示定理的 LapSVM 求解返回全部样本的 alpha 系数 n X.shape[0] l len(labeled_idx) # RBF 核矩阵 dists np.sqrt(((X[:, None, :] - X[None, :, :]) ** 2).sum(-1)) sigma np.median(dists[dists 0]) K np.exp(-dists ** 2 / (2 * sigma ** 2)) # 构造二次规划min 0.5 a^T Q a p^T a, s.t. y^T a 0, 0 a C # 这里用简化的 hinge loss 线性规划近似实际可用 cvxopt 的 QP # 为可读性采用迭代重加权的最小二乘近似等价于 hinge 的平滑版 Y np.zeros(n) Y[labeled_idx] y_labeled # 拉普拉斯正则项作用在全部样本上 M K np.linalg.inv(2 * gamma_A * np.eye(n) K gamma_I * K L K) K # 用有标签样本做加权最小二乘hinge loss 的一阶近似 alpha np.zeros(n) for _ in range(20): f K alpha # hinge loss 的次梯度权重 w np.zeros(n) mask Y ! 0 margin Y * f w[mask] np.where(margin[mask] 1, 1.0, 0.0) # 解线性系统 A_mat w[:, None] * K gamma_A * np.eye(n) gamma_I * L K alpha np.linalg.solve(A_mat 1e-6 * np.eye(n), w * Y) return alpha, K alpha, K lapsvm_fit(X, y_labeled, labeled_idx, L, gamma_A0.1, gamma_I0.05) f_pred K alpha y_pred np.sign(f_pred) acc np.mean(y_pred y) print(f全样本准确率: {acc:.3f})这段代码用迭代重加权最小二乘近似 hinge loss避免直接调 QP 求解器的复杂度逻辑更透明。核心是A_mat那一行w[:, None] * K是有标签样本的拟合项gamma_A * np.eye(n)是 RKHS 范数正则gamma_I * L K是拉普拉斯正则。gamma_A越大模型越保守gamma_I越大决策边界越平滑。迭代 20 次通常够收敛1e-6 * np.eye(n)是数值稳定项防止矩阵奇异。参数说明gamma_A0.1、gamma_I0.05是中等强度的正则实际任务建议在对数尺度上网格搜索比如gamma_A取[0.01, 0.1, 1]gamma_I取[0.001, 0.01, 0.1]。k和sigma对结果影响也很大但优先调gamma_I因为它直接控制无标签信息的注入强度。3.4 验证效果和无标签信息的 SVM 对比from sklearn.svm import SVC # 只用有标签样本训练标准 SVM svm SVC(kernelrbf, C1.0, gammascale) svm.fit(X[labeled_idx], y_labeled) acc_svm np.mean(svm.predict(X) y) print(f标准 SVM仅20个标签准确率: {acc_svm:.3f}) print(fLapSVM20标签 180无标签准确率: {acc:.3f})在典型的两簇数据上标准 SVM 因为只有 20 个标签决策边界容易偏向某一侧准确率常在 0.75 到 0.85 之间波动LapSVM 借助 180 个无标签点的结构信息通常能拉到 0.90 以上。差距的大小取决于无标签数据是否真的落在有意义的流形上——如果无标签数据本身就是噪声LapSVM 反而可能被带偏这也是下一章要重点说的坑。4. 调参与排错LapSVM 最容易翻车的五个地方4.1 无标签数据里混进噪声拉普拉斯正则变成“捣乱项”现象加了无标签数据后准确率不升反降甚至比只用有标签样本还差。原因拉普拉斯正则假设“近邻点的输出应该一致”但如果无标签数据里混入了标注错误、采集异常或者完全无关的样本这些点会把错误的平滑约束强加给模型。$\gamma_I$ 越大被带偏得越狠。解决先对无标签数据做一轮无监督清洗用孤立森林或简单的密度过滤把离群点剔掉或者把 $\gamma_I$ 调小先观察准确率随 $\gamma_I$ 的变化曲线找到拐点再定。我一般会做一个 sanity check只用无标签数据跑一遍聚类看簇结构和有标签样本的类别是否大致对齐对不齐就说明无标签数据质量有问题。4.2 图建得太密或太稀平滑约束失效现象k 取太小比如 2、3图断成多个连通分量拉普拉斯正则只在局部起作用k 取太大比如 50图接近全连接平滑项过强决策边界被抹平。原因kNN 图的连通性直接决定拉普拉斯矩阵的零空间维度。图不连通时平滑项无法跨分量传播信息图过密时所有点被强行拉向同一个均值模型失去判别力。解决k 的经验范围是 $\log n$ 到 $\sqrt{n}$几百个样本取 5 到 15 比较稳。更靠谱的做法是看图的连通分量数用scipy.sparse.csgraph.connected_components检查确保只有一个连通分量。如果数据本身分多个簇可以考虑对每个簇分别建图再合并但实现复杂度会上升。4.3 核矩阵规模爆炸内存直接吃满现象无标签样本加到几万条K矩阵是 $n \times n$ 稠密矩阵内存瞬间爆掉程序被系统杀掉。原因LapSVM 的核矩阵规模是全部样本数 $n$ 的平方$n50000$ 时单精度浮点就要 10GB加上拉普拉斯矩阵和中间变量普通机器扛不住。解决三条路。一是降采样无标签数据选一个能覆盖数据分布的子集通常几千到一万条就够二是用 Nyström 方法做核矩阵低秩近似把 $n \times n$ 降到 $n \times m$$m \ll n$三是换用线性核或者随机傅里叶特征把核方法转成显式特征映射用 SGD 类优化器求解。我一般先降采样效果不够再上 Nyström。4.4 标签不平衡时hinge loss 被多数类主导现象两类样本比例 9:1LapSVM 把所有样本都预测成多数类少数类召回率接近零。原因hinge loss 对每个有标签样本一视同仁多数类样本多梯度贡献大模型倾向于牺牲少数类来降低整体损失。拉普拉斯正则不区分类别帮不上忙。解决给少数类样本的损失加权权重取类别频率的倒数或者在采样阶段做平衡但有标签样本本来就少过采样容易过拟合。更稳的做法是调 SVM 的 $C$ 参数时按类别分别设少数类的 $C$ 设大一些。评估指标也别只看准确率看 F1 或 AUC。4.5 标准化没做或做错图结构完全失真现象模型训练不收敛或者准确率和随机猜差不多。原因建图依赖欧氏距离如果特征量纲差异大比如一个特征范围 0 到 1另一个 0 到 10000距离计算被大量纲特征主导近邻关系完全错误。另一个常见错误是在切分有标签/无标签之前做了标准化导致标准化参数泄露了测试集信息。解决标准化必须在切分之后、建图之前做且只用训练集含有标签和无标签拟合 scaler验证集和测试集用同样的参数变换。如果特征里有类别型变量先做 one-hot 或目标编码别直接当数值算距离。5. 让 LapSVM 真正可用的三个进阶技巧第一个技巧是自适应建图。固定 k 和 $\sigma$ 在不同密度区域表现差异很大改进做法是用局部尺度每个点的 $\sigma_i$ 取它到第 k 个邻居的距离权重用 $\exp(-|x_i - x_j|^2 / (\sigma_i \sigma_j))$。这样稀疏区域的点不会被过度平滑密集区域的点也不会因为 $\sigma$ 太小而失去连接。实现上只需在build_laplacian里把标量sigma换成向量代码改动不到十行但在密度不均的数据上提升明显。第二个技巧是用验证集选 $\gamma_I$ 而不是拍脑袋。具体做法把有标签样本分成训练和验证两部分无标签样本全部参与建图在gamma_I的网格上跑 LapSVM看验证集准确率。注意验证集样本不能进入拉普拉斯正则的拟合项但可以进入图——因为图只用了特征没用标签不算泄露。这个细节很多人搞错把验证集完全排除在图外导致图结构不完整选出来的参数偏保守。第三个技巧是监控拉普拉斯正则项的值。训练完成后算一下 $\mathbf{f}^T L \mathbf{f}$如果这个值比初始随机猜测还大说明模型在图上不平滑要么是 $\gamma_I$ 太小要么是图建错了。这个诊断指标比只看准确率更能反映 LapSVM 是否真的在利用无标签信息。我现在的习惯是每次跑 LapSVM 都打印三个数有标签训练准确率、全样本准确率、拉普拉斯正则值。三个数一起看基本能判断问题出在拟合、泛化还是图结构上。这套流程我在几个标注成本高的分类任务上反复用过最深的教训是LapSVM 的效果上限由无标签数据的质量决定而不是由调参决定。图建对了、无标签数据干净默认参数就能跑出不错的结果图建歪了再怎么网格搜索也是白费。所以每次上手新任务我会先花一半时间在数据清洗和建图验证上剩下的一半才留给参数。希望帮到你。本文还有配套的精品资源点击获取