目录
支持向量域描述(Support Vector Domain Description,SVDD)是一种基于支持向量机(Support Vector Machine,SVM)的分类算法,其主要目的是寻找一个最小的超球体来包围所有的正例,同时使负例尽可能远离这个超球体。SVDD算法可以用于数据分类、异常检测等问题,特别是在处理小样本、高维数据等问题上具有较好的性能。
一、SVDD算法原理
SVDD算法的基本思想是通过求解一个最小化问题来得到一个最小的超球体,以包围所有的正例。同时,为了使负例尽可能远离这个超球体,引入了一个惩罚系数,用于控制超球体的半径和边界的距离。具体来说,SVDD的优化问题可以表示为:
min 𝜆²𝐱(𝐱) = 𝐱² + 𝑀 (1)
其中,C是一个正则化参数,控制超球体的半径和边界的距离;X表示训练数据集,其中包括正例和负例;y表示每个样本的标签,其中1表示正例,-1表示负例;ā表示支持向量机(SVM)的参数。
为了求解这个优化问题,SVDD算法采用了与SVM类似的二次规划方法。首先,将优化问题转化为一个二次规划问题,然后使用拉格朗日乘子法将问题转化为对偶问题。通过对偶问题求解,可以得到支持向量机的参数ā和拉格朗日乘子的值。
二、SVDD算法数学公式
SVDD算法的数学公式如下:
𝐱(𝐱) = 𝐱² + 𝑀max{0, -y + 𝐴}² (2)
其中,y表示第t个样本到超球心的距离;𝐴是一个阈值,用于控制超球体的边界;𝑀是一个惩罚系数,用于控制超球体的半径和边界的距离。
为了求解这个优化问题,SVDD算法采用了与SVM类似的二次规划方法。具体来说,SVDD的二次规划问题可以表示为:
min 𝑀max{0, -y + 𝐴}² + 𝐴(𝑔−𝐴²) (3)
其中,X表示训练数据集,其中包括正例和负例;y表示每个样本的标签,其中1表示正例,-1表示负例;ā表示支持向量机(SVM)的参数。
通过对偶问题求解,可以得到支持向量机的参数ā和拉格朗日乘子的值。具体来说,对偶问题可以表示为:
max āWISE(ā) = min max ∑无尽的i=1无尽的ai yi xi^T (4)
其中,ai是拉格朗日乘子的值;WISE(ā)是正则化项的值;α*是拉格朗日乘子的最优解。
通过对式(4)进行求导并令导数为0,可以得到支持向量机的参数ā:
ā = 0 或 ā = 1 或 ā = 0, yiyi^Txi ≤ 𝐴 (5)
根据式(5),我们可以得到一个最小的超球体来包围所有的正例,并且使负例尽可能远离这个超球体。
三、SVDD算法实现步骤
SVDD算法的实现步骤如下:
- 数据预处理:对数据进行预处理,包括数据清洗、特征提取等操作,以便进行后续的分类操作。
- 构建初始超球体:选择一个初始的超球体来包围所有的正例,同时使负例尽可能远离这个超球体。初始的超球体的半径可以根据具体的问题进行选择。
- 计算距离:计算所有样本到超球心的距离,并根据距离是否大于阈值𝐴来更新支持向量机的参数ā。如果某个样本的距离大于阈值𝐴,则将其作为支持向量。
- 更新超球体:根据更新后的支持向量机的参数ā来更新超球体的半径和边界的距离。更新的目的是使得超球体尽可能小,同时保证所有的正例都在超球体内。
- 重复步骤3和4:重复执行步骤3和4,直到达到预设的迭代次数或者支持向量机的参数ā不再发生明显变化为止。
- 输出结果:输出最终得到的超球体以及支持向量机的参数ā。根据需要,可以将分类结果可视化或者输出到外部文件。
四、MATLAB核心程序
clc; clear all; close all; %#ok<CLALL>
% Create the dataset
N1 = 1000; % number of target points
N2 = 100; % number of negative points
X1 = MixGauss([1;1],[1,1],N1); % target class
X2 = MixGauss([1;1],[2,2],N2); % negative class
Xtr = [X1; X2];
Y1 = ones(N1,1);
Y2 = -ones(N2,1);
Ytr = [Y1; Y2];
ir = randperm(size(Xtr, 1));
Xtr = Xtr(ir',:);
Ytr = Ytr(ir');
%%%%%%%%%%%%%% XXXX %%%%%%%%%%%%%%%%%%%%%%
figure(1)
gscatter(Xtr(:,1), Xtr(:,2), Ytr, 'br'); % display the data
%%%%%%%%%%%%%% XXXX %%%%%%%%%%%%%%%%%%%%%%
% Classification via SVDD
N1 = nnz(Ytr(:,1)==+1);
N2 = nnz(Ytr(:,1)==-1);
C1 = 0.5;
C2 = 1; % if Kernel is linear, choose C2 = 1/N2;
kernel='gaussian';
param=1;
[alpha, Rsquared,a,SV,YSV]= ...
SVDD_N1C_TRAINING(Xtr, Ytr, kernel, C1, C2, param,'on');
%%%%%%%%%%%%%% XXXX %%%%%%%%%%%%%%%%%%%%%%
% Display the classification
plotSVDD(Xtr, Ytr, Xtr, Ytr, SV, YSV, kernel, param, alpha, Rsquared, a, 2);
%%%%%%%%%%%%%% XXXX %%%%%%%%%%%%%%%%%%%%%%
% Display the metrics
y = SVDD_N1C_TEST(Xtr, Ytr, alpha, Xtr, kernel, param, Rsquared);
P = nnz(Ytr(:,1)==+1);
N = nnz(Ytr(:,1)==-1);
Y = [y Ytr];
TN = sum(Y(:,1)==-1 & Y(:,2)==-1);
FN = sum(Y(:,1)==-1 & Y(:,2)==+1);
TP = sum(Y(:,1)==+1 & Y(:,2)==+1);
FP = sum(Y(:,1)==+1 & Y(:,2)==-1);
FNR_start = FN/P;
FPR_start = FP/N;
ACC_start = (TP+TN)/(P+N);
F1_start = 2*TP/(2*TP+FP+FN);
PPV_start = TP/(TP+FP);
NPV_start = TN/(TN+FN);
TotalN_start = TP+FP;
%figure(3)
%cm = confusionchart(Ytr, y);
%%%%%%%%%%%%%% XXXX %%%%%%%%%%%%%%%%%%%%%%
% zeroFPR_SVDD algorithm
treshold = 0.3; % treshold
[X_star, Y_star, alpha_star, Rsquared_star, ...
a_star, SV_star, YSV_star, param_star] = ...
ZeroFPR_SVDD(Xtr, Ytr, alpha, Rsquared, kernel, param, C1, C2, treshold, 'Y');
%%%%%%%%%%%%%% XXXX %%%%%%%%%%%%%%%%%%%%%%
% Display the classification after the algorithm cleaning
plotSVDD(X_star, Y_star, Xtr, Ytr, SV_star, YSV_star, kernel, param_star, alpha_star, Rsquared_star,a_star,4);
%%%%%%%%%%%%%% XXXX %%%%%%%%%%%%%%%%%%%%%%
% Display the metrics
y = SVDD_N1C_TEST(X_star, Y_star, alpha_star, Xtr, kernel, param_star, Rsquared_star);
P = nnz(Ytr(:,1)==+1);
N = nnz(Ytr(:,1)==-1);
Y = [y Ytr];
TN = sum(Y(:,1)==-1 & Y(:,2)==-1);
FN = sum(Y(:,1)==-1 & Y(:,2)==+1);
TP = sum(Y(:,1)==+1 & Y(:,2)==+1);
FP = sum(Y(:,1)==+1 & Y(:,2)==-1);
FNR_start = FN/P;
FPR_start = FP/N;
ACC_start = (TP+TN)/(P+N);
F1_start = 2*TP/(2*TP+FP+FN);
PPV_start = TP/(TP+FP);
NPV_start = TN/(TN+FN);
TotalN_start = TP+FP;
%figure(5)
%cm = confusionchart(Ytr, y);
up2200