非线性支持向量机实现
假设我们面对的非线性问题是下面的二分类问题:


要求我们找到一个合适的曲线能够正确区分红色和蓝色样本点,毫无疑问,线性支持向量机是无法解决此类问题的,我们可以借助非线性支持向量机来求解问题,那么下面的核心问题就是找到合适的核函数,在不知道什么核函数合适的时候,优先使用高斯核函数是个好办法。即:



其实和线性支持向量机相比最大的差别就是将原来特征向量的内积换成了核函数的形式,所以在编程实现中也只是改变了一下计算方式,而且最后是不需要计算w ww的值的,只需要构造出决策函数即可。代码如下:


训练代码:

%% 非线性SVM测试二
%% 清空变量
clc;
clear;

%% 调用绘图函数并返回待数据
data = plot_Circle(10,10,4,2,100);
X = data(:,1:2);
y = data(:,3);

%% 借助核函数进行训练已有数据
cig = 1;
C = 10;
% 利用核技巧进行分类,任然是二次规划求解
% 构建二次系数矩阵H
H = [];
for i =1:length(X)
    for j = 1:length(X)
        H(i,j) = exp(-(norm(X(i,:) - X(j,:)))/(2*cig^2))*y(i)*y(j);
    end
end
% exp(-(norm(X(i,:) - X(j,:)))/(2*cig^2))
% 构造一次项系数f
f = zeros(length(X),1)-1;
A = [];b = []; % 不等式约束
Aeq = y';beq = 0; % 等式约束
ub = ones(length(X),1).*C;lb = zeros(length(X),1); % 自变量范围
[x,fval] = quadprog(H,f,A,b,Aeq,beq,lb,ub);
% x表示自变量的解,以及在x处的函数值
% 将很小的x直接赋值为0
x(x < 1e-5) = 0;
% 求解b的值
[a,~] = find(x~=0); % 找到可以求解b的值
B = 0;
for i =1:length(X)
    B = B + x(i)*y(i)*exp(-(norm(X(i,:) - X(a(1),:)))/(2*cig^2));
end
b = y(a(1)) - B;

测试代码:
%% 在测试集上进行测试
random = unifrnd(6,14,2000,2); % 生成待预测的数据
yuce = zeros(length(random),1);
for i =1:length(random)
    F = 0;
    for j =1:length(x)
        F = F + x(j)*y(j)*exp(-(norm(X(j,:) - random(i,:)))/(2*cig^2));
    end
    f = F + b;
    if f > 0
        yuce(i) = 1;
    elseif f < 0
        yuce(i) = -1;
    end
end
yuce_1 = [];
yuce_2 = [];
for i =1:length(yuce)
    if yuce(i) == 1
        yuce_1 = [yuce_1;random(i,:)];
    else
        yuce_2 = [yuce_2;random(i,:)];
    end
end
% 绘制测试集上的误差情况
figure(2)
scatter(yuce_1(:,1),yuce_1(:,2),'*');
hold on
scatter(yuce_2(:,1),yuce_2(:,2),'*');
xlim([4,16]);
ylim([4,16])

我把整体部分分为两个,第一个是训练数据,然后才是预测数据,由于非线性支持向量机学习过程不是显式学习,所以在求解过程中我们没法找到超平面的函数式,但是当我们使用测试集进行测试时,在二维平面上的结果就可以可视化出来,我在测试时是在范围内随机生成了20000个点,然后调用决策函数进行预测,结果如图:



从可视化的结果上也反映出此学习算法是可靠的,统计支持向量的个数发现,α>0的样本还有66个,但是这里没法给出支持向量机的显式方程。