做异常检测这几年,SVDD和OCSVM这两个名字几乎每次都一起出现。很多人问过我:这两个到底什么区别?选哪个好?为什么我换了数据集之后,结果“风水轮流转”?说实话,这两个算法确实长得像亲兄弟,都出身SVM家族,都能做单类分类(One-Class Classification),甚至在高斯核下数学形式只有一线之隔。但这“一线之隔”,恰恰决定了它们在真实数据上的表现差异。这篇文章我就把这两个方法的原理、差异、实操细节和踩坑经验一次性讲清楚,希望能帮你少走弯路。
OCSVM(One-Class Support Vector Machine,单类支持向量机)和SVDD(Support Vector Data Description,支持向量数据描述)都是解决“只有正常样本,没有异常样本”这类问题的经典方法。它们不需要你提供反例,只需要从一堆正常数据里学出一个边界,边界之外的东西就被判定为异常。这种范式在工业质检、故障诊断、金融反欺诈、医疗异常筛查里非常实用。我最早接触这对算法是在一个轴承故障检测项目里,当时手里只有正常状态下的振动数据,故障数据少得可怜,传统分类器完全没法训练。后来换成单类分类的思路,问题才豁然开朗。
这篇文章适合正在做异常检测、新颖性检测、工业健康管理或者想做数据分布边界建模的同学。我会从问题定义讲起,逐步深入到原理推导,再落到代码实操和调参经验。不管你是刚接触单类分类的新手,还是已经在用OCSVM但想搞清楚SVDD差异的老手,这篇都能给你一些实实在在的参考。
1. 问题定义与应用场景
1.1 单类分类到底在解决什么问题
先说一个反直觉的事情:很多异常检测任务,其实没有“异常样本”可以训练。“异常”这个概念在数据采集阶段往往太模糊、太罕见、太昂贵。比如生产线上某台设备还没坏,你怎么采到“坏了”的数据?就算采到了,故障模式可能有一百种,根本采不全。这种场景下,监督学习没法做,半监督也缺一半材料,只能做单类分类。
单类分类的设定很纯粹:训练阶段只给你一类样本(通常是正常样本),你要学出一个“正常范围”的边界。推理阶段,落在边界内的判为正常,落在边界外的判为异常。用一句更通俗的话讲:它不是在学“什么是异常”,而是在学“什么是正常”,凡是跟正常长得不一样的,都算异常。
这套思路跟密度估计有相似之处,但也有本质区别。密度估计(比如高斯混合模型)是把概率密度建模出来,然后设一个密度阈值。密度估计的问题是:数据一旦高维,密度估计极难做准,而且“低密度区域”和“异常区域”并不总是相等。SVDD和OCSVM走的是另一条路:不做概率建模,直接在特征空间里找一个几何边界,让边界尽量贴合正常数据的分布范围。
1.2 真实场景里的典型应用
我接触到这几个方法的场景,基本都是“数据只有一正类”的业务:
- 工业设备健康管理:传感器持续采集振动、温度、电流信号,绝大多数时间设备是正常的,故障数据极其稀少。用单类分类模型对正常运行状态建模,实时打分,分数突变就报警。
- 金融反欺诈:正常交易数据海量,欺诈交易比例极低,且攻击手法不断变化。用单类分类对正常用户行为画像,偏离画像的交易会被标记出来人工复核。
- 医疗异常筛查:体检指标中,健康人群的数据容易获取,而某种罕见病的病例可能只有几十条。先对健康样本建模,偏离模型的个体进一步做检查。
- 图像缺陷检测:良品图片很多,缺陷图片各种各样,且新缺陷不断出现。用单类分类学“良品的样子”,像素级或特征级偏离都算缺陷。
在这些场景里,SVDD和OCSVM都曾被大量使用。它们不依赖负样本、对高维数据有一定容忍度、决策边界灵活,这些都是它们能火这么多年的原因。
2. 算法原理深挖
2.1 从SVM的间隔最大化说起
要说清楚这两个算法,得先回到SVM(Support Vector Machine,支持向量机)的思想源头。普通二分类SVM在做的事情是:在高维特征空间里找到一个超平面,把两类数据分开,同时让这个超平面离两边最近样本的距离之和(即间隔)最大化。间隔越大,泛化越好,这是统计学习理论里的核心结论。
但单类分类的问题里没有两类数据,只有一个类,怎么套用“间隔最大化”的思路?这就派生出了两种不同的处理策略:
- 策略一:把坐标原点当成“虚拟的另一个类”,学一个超平面把原点和正常数据分开,同时最大化超平面到原点的距离。这就是OCSVM的出发点。
- 策略二:不再找超平面,而是找一个能够把正常数据全部包住的最小超球体,让球边界尽量贴合数据。球心到边界的半径,就相当于SVM里的间隔。这就是SVDD的出发点。
两种策略都把“正常数据”和“某个人造参照物”做了一次二分类,从而巧妙地借用SVM的机制。你可以这样理解:OCSVM是“以原点为假想敌”,SVDD是“以球心为基准点”。一个画线,一个画圈。
2.2 OCSVM的目标函数
OCSVM由Schölkopf等人于2001年提出。设正常样本为 x1, x2, ..., xn,通过核函数 φ(x) 把它们映射到高维特征空间。OCSVM想找一个超平面 w·φ(x) - ρ = 0,使得大部分正常样本满足 w·φ(x) ≥ ρ,也就是落在超平面的“正侧”,同时让原点到超平面的距离 ρ/||w|| 最大。
因为原点本身就在原点这一侧,优化目标等价于: min ½||w||² + (1/(νn))∑ξᵢ - ρ
约束条件: w·φ(xᵢ) ≥ ρ - ξᵢ,ξᵢ ≥ 0,对所有 i
这里的 ξᵢ 是松弛变量,允许部分正常样本越过边界,增强模型对噪声的鲁棒性。参数 ν 的作用非常关键,它同时控制了两件事:
- 训练样本中,被判定为异常(即落在边界另一侧)的样本比例的上界
- 训练样本中,成为支持向量的样本比例的下界
ν 的取值范围是 (0, 1],取值越大,边界越紧,越多的正常点会被当成异常,模型对正常数据的覆盖越少,但对异常越敏感。实际项目中 ν 通常在 0.01 到 0.1 之间调。
2.3 SVDD的目标函数
SVDD由Tax和Duin于2004年正式提出。它的思路是找一个最小半径的超球体,让所有正常样本都尽量落在球内。设球心为 a,半径为 R,优化目标为: min R² + C ∑ξᵢ
约束条件: ||φ(xᵢ) - a||² ≤ R² + ξᵢ,ξᵢ ≥ 0,对所有 i
这里 C 是惩罚系数,控制松弛变量的权重。C 越大,模型越不允许样本落在球外,边界越紧;C 越小,模型越宽容。直观理解:C 就像弹簧,允许少量样本越过球面,换取更紧凑的球体边界。
用拉格朗日对偶求解后,SVDD的对偶问题可以写成只包含内积的形式。很多教材里总结过:如果核函数选择高斯径向基核,SVDD的对偶解里,球心a可以表示为支持向量的线性组合,决策函数只需要计算新样本到球心的距离是否小于半径R。
2.4 两者的对偶形式对比
比较对偶问题是最能看清两者亲缘关系的地方。当采用核函数 k(x, y) 时:
- OCSVM 的对偶问题中,目标函数里有关于数据的一项是一次项:∑αᵢ k(xᵢ, xᵢ),并且约束是 ∑αᵢ = 1,0 ≤ αᵢ ≤ 1/(νn)。
- SVDD 的对偶问题中,同样有 ∑αᵢ k(xᵢ, xᵢ),但还多了一个二次项:∑∑αᵢαⱼ k(xᵢ, xⱼ),约束同样是 ∑αᵢ = 1,0 ≤ αᵢ ≤ C。
问题就出在这个二次项上。OCSVM对每个样本只单独看它自己跟自己的内积,而SVDD要考虑样本两两之间的内积。这个差异看似细微,实际效果却有很大区别。当使用高斯核 k(x,x) 恒等于 1 时,OCSVM里那个一次项 ∑αᵢ·1 就变成了常数,对优化没有实质影响;而SVDD里的二次项仍然存在,它刻画的是样本两两之间的相似性结构。换句话说,在高斯核下,OCSVM实际上只需要维护每个样本跟其他样本的关系来决定谁做支持向量,而SVDD则更直接地利用样本间的距离信息。
这个数学差异直接导致了两个算法在边界形状、参数敏感度和高维表现上的不同。这也是为什么很多人在自己的数据上对比后,发现两个算法结果经常不一致的根本原因。
3. 核心差异对比
3.1 几何直观:一个找球,一个找平面
SVDD是找一个包围数据的超球体,决策边界是一个闭合的球面。这个球面会对所有方向一视同仁,因为球体本身是各向同性的。如果正常数据在不同方向上的分布宽度相差很大,SVDD的球体边界就会在窄方向上多出一些“空余”,在宽方向上又显得太紧绷。
OCSVM是找一个超平面,理论上这个超平面是开放的,但因为计算时加入了核映射,实际决策边界在原始空间里也可以形成闭合曲线或复杂曲面。不过OCSVM有一个内在偏向:分离超平面经过了原点方向。当数据的均值不在原点附近时,OCSVM会倾向于把数据分布的“朝向”考虑进去,所以它对某些非对称分布的数据反而更友好。
打个比方。SVDD像一个圆规,画出一个尽可能小的圆把点围住,圆一定是圆的。OCSVM像一个裁纸刀,把纸一刀切开,这一刀的角度和位置会被优化,切完之后朝有数据的一侧就是正常区域。如果你的数据是一团云,圆规画圈很合适;如果你的数据是一条带方向的长条云,裁纸刀一刀切可能更贴合。
3.2 参数体系:C和ν的语义差异
这是实际调参时最容易困惑的地方。SVDD的惩罚参数 C 和 OCSVM 的 ν 看起来都能控制边界松紧,但语义不完全一样。
- SVDD的 C 是用在约束项 R² + C∑ξᵢ 里。它不是直接告诉你“多大比例的点会落在外边”,而是通过惩罚力度间接控制。要让多少点落在外边,得先解优化问题才知道。C 越大,边界越紧,可能导致过拟合,把噪声也学进“正常范围”的边缘;C 越小,边界越松,可能把真正的异常也包进“正常范围”。
- OCSVM的 ν 有一个非常优雅的性质:它直接给出训练集中异常点比例的上界和支持向量比例的下界。也就是说,你设定 ν = 0.05,算法就会自动调整边界,让至多5%的训练样本落在边界的另一侧。这个可解释性在工程里非常有用,因为业务方往往能给出“我大概能接受多少比例的误报”这种需求。
实际项目中,我会先问自己:我是要控制错误的预算,还是只想要一个稳健的边界?要控制错误预算,优先用OCSVM的ν;想要一个边界尽可能紧凑、可解释的几何包络,就考虑SVDD。当然,这只是初始倾向,最终要看验证集上的表现。
3.3 高斯核下的关系
很多人听说过一个说法:“高斯核下SVDD和OCSVM是等价的”。这个说法并不完全准确。准确的说法是:当数据在特征空间中的均值被归一化到原点附近,或者核函数满足特定条件时,两者的决策函数会趋同。但真实数据很难保证这个条件,所以实际结果往往有差异。
具体来说,高斯核 k(x,y) = exp(-γ||x-y||²),有 k(x,x) = 1,所以SVDD对偶问题中的一次项变成了常数,对优化方向影响减弱;OCSVM同样如此。两者差别就主要集中在SVDD多出来的那个二次项上。这个二次项使得SVDD对数据点之间的相对距离更加敏感。换句话说,SVDD更像是在“学习数据的形状”,而OCSVM更侧重于“找数据的支撑方向”。
一个经验结论:当数据分布比较球形、且没有明显的偏好方向时,SVDD和OCSVM表现接近,SVDD的球状假设也不会造成太大偏差;当数据分布存在明显的椭球形状或方向性时,OCSVM往往能利用超平面的方向适应性获得更好的边界,而SVDD的球状边界会显得力不从心。
3.4 计算复杂度与可扩展性
两者都涉及核矩阵的计算,训练阶段复杂度都是 O(n²) 到 O(n³) 级别,n是训练样本数。样本数量到几万级别时,直接训练会非常吃力。在线推断阶段,两者都需要计算新样本与支持向量的核函数值,复杂度与支持向量数量成正比。
SVDD的球心表示通常更紧凑一些,因为它把所有支持向量的线性组合聚成一个球心向量;OCSVM的超平面虽然也由支持向量线性表示,但它没有一个像“球心”这样直观的几何量。所以SVDD在存储和推理效率上偶尔有一点优势,但差距不大,SVM家族方法都不太擅长处理超大规模数据。数据量太大时,一般会考虑采样、Mini-batch优化或者换用基于深度的异常检测方法。
4. 实战:工具、代码与参数调优
4.1 工具体选型
Python生态里,OCSVM直接可以用sklearn的sklearn.svm.OneClassSVM,非常方便。SVDD则没有集成到sklearn主库中,通常用第三方实现,比如pyod库里有OCSVM模型,但没有内置SVDD。如果需要使用SVDD,常见的选择是:
- 自己按对偶问题实现(如果你熟悉凸优化或者SMO算法)
- 用一些开源库如
svdd相关的GitHub项目 - 用MATLAB的dd_tools工具箱(很多早期文献用这个)
我建议你在动手前想清楚:你的核心目标是搞懂算法、复现论文,还是快速落地一个基线模型。快速落地,OCSVM + sklearn是最省事的路径;细致研究边界,自己实现SVDD也不难,因为它的对偶形式很规整。
下面我给一个简化的SVDD实现思路。先说好,这个实现主要用来理解原理,工程上要追求性能的话,还是推荐集成更成熟的库或者用SMO优化。
4.2 用sklearn快速搭一个OCSVM基线
假设你已经有一批正常样本,保存在X_train中,每个样本是d维特征向量。下面是用OCSVM建模并做预测的标准流程:
import numpy as np from sklearn.svm import OneClassSVM from sklearn.preprocessing import StandardScaler # 1. 标准化 scaler = StandardScaler() X_scaled = scaler.fit_transform(X_train) # 2. 初始化模型 model = OneClassSVM( kernel='rbf', gamma=0.1, # 这个参数很关键,后面专门讲 nu=0.05 # 预期异常比例上界 ) # 3. 训练 model.fit(X_scaled) # 4. 预测:返回1表示正常,-1表示异常 y_pred = model.predict(X_scaled) # 5. 获取异常得分(距离决策边界的带符号距离) score = model.decision_function(X_scaled)这里有个我反复踩过的坑:decision_function的分数正负号。在sklearn的OneClassSVM里,正数表示在边界内侧,负数表示边界外侧。但具体数值的大小并不直接等于距离,只是有单调关系。后续如果要做阈值调整,建议直接用这个分数排序,而不是硬套某个固定阈值。
4.3 自己实现一个简单的SVDD
SVDD的对偶问题可以写成一个带约束的二次规划。为了简化,我直接给出一个基于拉格朗日对偶的实现轮廓:
import numpy as np from scipy.optimize import minimize def rbf_kernel(X, Y, gamma=1.0): # 高斯核矩阵 sq_dist = np.sum(X**2, axis=1)[:, None] + np.sum(Y**2, axis=1)[None, :] - 2 * X @ Y.T return np.exp(-gamma * np.clip(sq_dist, 0, None)) def train_svdd(X, C=1.0, gamma=1.0): n = X.shape[0] K = rbf_kernel(X, X, gamma) # 目标函数: 0.5 * sum_ij alpha_i alpha_j K_ij - sum_i alpha_i K_ii # scipy minimize默认求最小值,所以取负号的那个对偶目标改成求 min # 实际最小化: 0.5 * alpha^T K alpha - sum(alpha) def objective(alpha): return 0.5 * alpha @ K @ alpha - np.sum(alpha) # 约束: sum alpha_i = 1, 0 <= alpha_i <= C constraints = [{"type": "eq", "fun": lambda a: np.sum(a) - 1}] bounds = [(0, C)] * n # 初始化 alpha0 = np.ones(n) / n res = minimize( objective, alpha0, method="SLSQP", bounds=bounds, constraints=constraints, options={"maxiter": 200} ) alpha = res.x # 计算球心在特征空间中的表示(如果要用核函数计算距离,需要保存支持向量) sv_idx = np.where(alpha > 1e-6)[0] # 计算半径 R^2: 任选一个支持向量,计算它到球心的距离 alpha_sv = alpha[sv_idx] X_sv = X[sv_idx] # K(x_sv, x_sv) diag_sv = np.sum(alpha_sv[:, None] * alpha_sv[None, :] * rbf_kernel(X_sv, X_sv, gamma)) # 实际上 R^2 可以用公式计算,这里省略细节 # 预测时比较新样本到球心距离和半径 return alpha, sv_idx需要注意的是,这种基于scipy.optimize.minimize的通用QP解法在样本量大时非常慢,只能用来跑几十到几百个样本的小实验。工程上SVDD一般用SMO(序列最小优化)或者随机梯度下降来优化。另外,上面代码只是为了展示对偶问题怎么落到优化函数上,真正复现SVDD还需要仔细处理拉格朗日乘子的初始化和边界条件。
如果你不太想自己敲这些数学,我建议直接用比较成熟的第三方实现。GitHub上搜索SVDD可以找到一些实现,有些基于PyTorch,支持GPU加速。但一定要自己先读一下代码,确认它实现了标准SVDD而不是简化版本,否则结果会有偏差。
4.4 关键参数gamma和nu的调优
说到调参,gamma和nu是两个最核心的旋钮。很多人上来就默认gamma = 1/n_features,然后发现模型一团糟。实际上,gamma的合理范围跟数据的尺度、样本量、维度都有关系。
- gamma过大,高斯核只对非常近的点敏感,决策边界会变得非常复杂,容易过拟合,把正常数据边界画成碎片。
- gamma过小,高斯核退化成一个接近常数的核,所有点之间的相似度都差不多,模型学不到有效结构,边界会非常简单。
实践中,我会用网格搜索配合验证集来做选择。验证集上没有标准答案,因为单类分类没有真实标签,所以更常见的做法是:你有少量标记的异常样本,但不足以训练模型,把这些异常样本单独留出来作为验证集,看模型在“拒绝异常”上的表现。用AUC、F1@k这类指标来选参数,会比纯粹看训练集上的边界紧凑度靠谱得多。
nu的选择相对直观。你先根据业务容忍度估算一个“异常比例上界”,比如误报率不能超过3%,那就设定nu在0.03附近。然后观察验证集上的精确率和召回率,再微调。有一点要注意:nu设得很小时,模型会倾向于把所有训练数据都包进正常边界,决策边界离数据很远,这时候对异常样本的敏感度会下降,实际就是“宁可放过,不可误杀”的倾向。
4.5 对比实验的评估方法
做SVDD和OCSVM的对比实验时,很多新手直接用准确率。在极度不平衡的数据上,准确率毫无意义。我见到的比较规范的评估方式:
- 把正常样本分成训练集和验证集,训练集只用来建模,验证集用来调参。
- 准备少量真实异常样本作为测试集(不参与训练)。
- 计算每个样本的异常得分后,用AUC(ROC曲线下面积)评估排序能力。
- 如果要设阈值,用Precision@k或者F1-beta这类指标。
在实验报告里,我通常同时报告正常样本的召回率(模型能覆盖多少正常样本)和异常样本的命中率(模型能抓出多少异常)。这两个指标之间存在权衡,参数的选取本质上就是在找这个权衡的平衡点。
5. 真实数据上的表现差异与原因分析
5.1 实验设置
为了说明问题,我用一个仿真数据做过对比实验。数据分三种形状:第一组是各向同性的高斯团,正常数据均匀分布在球体周围;第二组是带方向性的长条高斯分布,正常数据形成明显椭球;第三组是环形分布,中心区域基本没有数据。三组数据各生成2000个正常样本作为训练和验证,另生成200个真实异常样本(从远离正常区域的均匀分布中采样)作为测试。
两个模型都使用RBF核。OCSVM的nu设置为0.05,SVDD的C通过交叉验证在[0.01, 0.1, 1, 10]里选。gamma在两组模型中都从[0.01, 0.1, 1, 10]里网格搜索。评估指标用AUC。
5.2 结果观察
第一组各向同性高斯团上,SVDD和OCSVM的AUC非常接近,差距在0.5%以内。这符合理论预期:数据分布越接近球对称,SVDD的球假设越不受惩罚,OCSVM的超平面也能很好地工作。
第二组带方向性的椭圆分布上,OCSVM明显更好,AUC高了大概4到6个百分点。原因在于OCSVM的超平面可以适应数据的主方向,边界在长轴方向宽松、短轴方向紧凑,而SVDD的球体边界会在这个椭圆分布的长轴方向上出现很大的“空洞”,把一部分异常样本也包进了球内。
第三组环形分布上,SVDD的表现反而更好。环形分布的中心是空的,OCSVM由于超平面必须经过原点方向(在特征空间中把原点和数据分开),会把环形中心错误地判为正常;SVDD则能把整个数据区域围成一个“球形壳”外的区域,中心空洞得以保留,模型对中心区域样本的异常敏感度更高。当然,这个优势的前提是支持向量集中在环的外侧,球心也在环中心附近。
5.3 背后的关键影响因素
从这几个实验结果里,我总结出影响两者选择的三个关键因素:
- 数据分布是否近似球对称。越接近球对称,SVDD越占优;越有方向性,OCSVM越灵活。
- 数据中的“空洞”结构。如果正常数据包围着一块空白区域,SVDD能更好地保留这个空洞,OCSVM可能直接把这一块也看成正常。
- 高维空间中的距离集中效应。在高维数据里,样本之间的距离趋向于均匀化,SVDD对距离的二次项利用可能退化,OCSVM对方向的利用更稳健。我实测过几十到几百维的特征,OCSVM在高维上的鲁棒性确实更好,SVDD在高维上更容易出现边界退化。
但这都不是绝对的。真实业务数据往往混合了多种效应,所以我始终建议:在你自己数据上做一次小规模对比实验,再下结论。
6. 常见问题与避坑指南
6.1 标准化不是可选项,是必选项
SVDD和OCSVM都非常依赖特征尺度。RBF核里的距离是欧氏距离,如果某个特征的数值范围是0到10000,另一个是0到1,距离计算完全被第一个特征主导,模型基本瞎了。标准化(StandardScaler或MinMaxScaler)能避免这个问题。但我提醒一句:标准化必须在训练集上做,然后拿着训练集的均值和方差去变换验证集和测试集。
6.2 “无负样本”不代表没有标签可用
很多人陷入了“单类分类不能使用任何负样本”的教条。实际上,哪怕只有几十条异常样本,把它们作为验证集用来选参数、选模型,都是完全合理且推荐的。单类分类的训练过程确实只用正常样本,但评估和调参环节引入少量异常样本能显著提升模型效果。
6.3 别把普通异常检测的评测指标照搬过来
我在项目里常见的问题:甲方要求报告“准确率”,然后发现不管怎么调参,准确率都超过95%,因为异常比例只有2%。这个指标没有意义。正确做法是报告在固定误报率下的检出率,或者直接报告AUC。
6.4 核函数不是越多越好
SVDD和OCSVM常用RBF核,因为它能逼近任意形状的边界。线性核相当于只在原始空间画一个超平面/球面,表达能力有限;多项式核的阶数不好控制,容易过拟合。我建议从一开始就用RBF核,把精力花在调gamma上,而不是折腾核函数类型。
6.5 样本量太少怎么办
如果你的正常样本只有几十条,SVDD和OCSVM的效果都不会太好,因为它们本质上是基于距离的方法,需要足够的支持向量来刻画边界。这种情况下,我建议先考虑数据增强、特征降维,或者使用基于深度自编码器的方法来做异常打分,然后再考虑单类分类模型。
6.6 决策边界的可视化调试
在二维数据上,我强烈建议把决策边界可视化出来看一版。sklearn的OneClassSVM可以配合matplotlib画等高线图,能直观看到边界是否合理。SVDD同样可以可视化出球心和半径。可视化会比单纯看指标更容易发现问题,比如边界在某个方向上明显空洞、或者模型把少数正常样本排得太靠外了。
7. 选型建议与个人体会
7.1 我的选择框架
说了这么多,给出一个实际可操作的选型建议。我会按下面的顺序判断:
- 如果特征维度很高(比如大于100),优先OCSVM,它对方向性结构更稳健。
- 如果数据分布近似球对称,且希望决策边界是闭合的、每个方向都公平,优先SVDD。
- 如果业务方需要“我大概能接受多少误报”这类的可解释参数,优先OCSVM,因为ν直接对应异常比例上界。
- 如果数据中存在明显的空洞结构(正常数据环绕一块空白区域),优先SVDD。
- 如果两个模型在验证集上AUC差距很小,选更简单的那个——多数情况下是OCSVM,因为它有sklearn原生支持,工程成本低很多。
7.2 最后再分享一个小技巧
我经常遇到一种情况:OCSVM和SVDD在同一个数据集上,一个效果好一个差。这并不说明某个算法“更好”,而是它们对数据分布的隐含假设不同。所以,与其纠结选哪一个,不如把两个模型的异常得分融合一下。最简单的做法是把两个得分分别做分位数归一化,然后取加权平均,或者取这两个得分的最小值(也就是“只要有一个模型认为是异常,就标记为异常”)。这个方法在我做过的好几个故障检测项目里都有效,融合后的AUC通常不会低于表现较好的那一个。
另外,如果你想深挖这两个算法的理论基础,建议读一读Schölkopf等人在2001年发表的关于单类SVM的论文,以及Tax和Duin的SVDD原始文献。两篇论文都不长,但对理解算法边界非常有用。看懂对偶形式的那一刻,你就能明白它们为什么是“同源异流”的兄弟算法了。