编写了一个最小二乘支持向量机的程序,然后想先试一下有没有bug
于是选用了
X=[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20]
Y=[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20]T
其中X每一个数就是一个样本点,样本点在一维空间内,Y是值,这样其实就是一个y=x的函数,给了20个训练点
我首先使用了Gauss核函数进行LS-SVM拟合,
K=exp(-||X_i-X_j||^2/(2*σ^2)),σ=0.1,
结果Gauss核函数表现出了良好的局部特性,在训练点点的附近有很好的精度,但是当我要做预测时,比如输入一个X_i=25,得出来的结果完全不着边;
然后又试着使用混合核函数:采用Gauss核函数与多项式核函数相结合:
K=λ*exp(-||X_i-X_j||^2/(2*σ^2))+(1-λ)*(X_i•X_j+1)^d,σ=0.1,d=2,
我更改了好几个λ的值,但是加了多项式核函数之后,不仅没有使得预测性变好,甚至连训练点附近也变得不对了。
所以,以上我的使用有错误么?我检查了好像没有,为什么表现出这么差的预测性呢?是因为我的训练点取得太少了?针对这个简单的 y=x 的回归问题,应该怎么选取核函数?
1个回答
1.Guassian核函数是做interpolation,也就是预测点周围要有训练点去支撑。你可以去掉Gaussian试试。
2.对于x=25,其实是利用线性模型做extrapolation。所以你不需要核。
3.核方法是针对高纬线性不可分问题的。
-------------------------------------------------------------------------
引用论文里公式
我写的Matlab代码。
clear,clc,close all;
x=[1:20]';
y=[1:20]'+rand(20,1)*0;
omega_train=omega(x);
gamma=10^10;
n=20;
I=ones(n,1);
% As=t
A=[0 I'
I omega_train+1/gamma*eye(n)];
t=[0;y];
rank_A=rank(A)
s=inv(A)*t;
b=s(1)
lambda=s(2:end)
w=lambda'*x; % for linear kernel
figure;plot(lambda)
%% test
n_test=10;
x_test=100+[1:n_test]';
y_test=x_test;
y_test_hat=zeros(n_test,1);
for i=1:n_test
xi=x_test(i);
y_test_hat(i)=f1(xi,x,lambda,b);
end
figure;hold on
plot(x_test,y_test,'*')
plot(x_test,y_test_hat,'ro')
legend('ytest','ytest hat')
xlabel('x')
ylabel('y')
function K_out=K1(xi,xj)
% Gausssian kernel
% sigma_sqr=10^10;
% K_out=exp(-norm(xi-xj)^2/sigma_sqr);
% Linear Kernel
K_out=xi'*xj;
end
function omega_out=omega(x)
n=size(x,1);% number of data point
omega_out=zeros(n,n);
for i=1:n
for j=1:n
omega_out(i,j)=K1(x(i,:)',x(j,:)');
end
end
end
function f_out=f1(xi,x,lambda,b)
n=size(x,1);
f_out=b;
ttemp=zeros(n,1);
for i=1:n
ttemp(i,1)=K1(xi,x(i));
f_out=f_out+lambda(i)*ttemp(i);
end
end
在你的数据,y中的error都很小,接近(等于)0。根据公式7第3行,当$\xi$很小时$\gamma$需要很大,比如10^10.
如果用Gaussian核时,如果预测很远的值,比如x=100,需要$\sigma^2$=10^10,也就是Gaussian的方差很大。每一个训练点都可以影响很远的点。
对于你的数据,以下参数可以有较好的结果:当linear核时,$\xi$>=1; 当Gaussian 核时,$\xi$>=10^10,$\sigma^2$=10^10。