【libsvm】使用与自定义核函数

复制代码
void exit_with_help()
{
    mexPrintf(
    "Usage: model = svmtrain(training_label_vector, training_instance_matrix, 'libsvm_options');\n"
    "libsvm_options:\n"
    "-s svm_type : set type of SVM (default 0)\n"
    "    0 -- C-SVC        (multi-class classification)\n"
    "    1 -- nu-SVC        (multi-class classification)\n"
    "    2 -- one-class SVM\n"
    "    3 -- epsilon-SVR    (regression)\n"
    "    4 -- nu-SVR        (regression)\n"
    "-t kernel_type : set type of kernel function (default 2)\n"
    "    0 -- linear: u'*v\n"
    "    1 -- polynomial: (gamma*u'*v + coef0)^degree\n"
    "    2 -- radial basis function: exp(-gamma*|u-v|^2)\n"
    "    3 -- sigmoid: tanh(gamma*u'*v + coef0)\n"
    "    4 -- precomputed kernel (kernel values in training_instance_matrix)\n"
    "-d degree : set degree in kernel function (default 3)\n"
    "-g gamma : set gamma in kernel function (default 1/num_features)\n"
    "-r coef0 : set coef0 in kernel function (default 0)\n"
    "-c cost : set the parameter C of C-SVC, epsilon-SVR, and nu-SVR (default 1)\n"
    "-n nu : set the parameter nu of nu-SVC, one-class SVM, and nu-SVR (default 0.5)\n"
    "-p epsilon : set the epsilon in loss function of epsilon-SVR (default 0.1)\n"
    "-m cachesize : set cache memory size in MB (default 100)\n"
    "-e epsilon : set tolerance of termination criterion (default 0.001)\n"
    "-h shrinking : whether to use the shrinking heuristics, 0 or 1 (default 1)\n"
    "-b probability_estimates : whether to train a SVC or SVR model for probability estimates, 0 or 1 (default 0)\n"
    "-wi weight : set the parameter C of class i to weight*C, for C-SVC (default 1)\n"
    "-v n: n-fold cross validation mode\n"
    "-q : quiet mode (no outputs)\n"
    );
}
复制代码

核函数及对应参数:
0 -- 线性核函数: K(u,v)=u'*v;没有专门需要设置的参数
1 -- 多项式核函数: K(u,v)=(gamma*u'*v + coef0)^d;
  -d用来设置多项式核函数的最高此项次数,默认值是3 
  -g用来设置核函数中的gamma参数设置,默认值是1/k(k是类别数)
  -r用来设置核函数中的coef0,默认值是0
2 -- RBF核函数: K(u,v)=exp(-gamma*||u-v||^2);
  -g用来设置核函数中的gamma参数设置,默认值是1/k(k是类别数)
3 -- sigmoid核函数: K(u,v)=tanh(gamma*u'*v + coef0)
  -g用来设置核函数中的gamma参数设置,默认值是1/k(k是类别数)
  -r用来设置核函数中的coef0,默认值是0
4 -- 自定义核函数

参考代码,同一个公式有不同的表达式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function K = kernels(X1, X2, kernel_type)
%计算核函数
switch lower(kernel_type)
    %线性核函数
    case 'linear'
        K = (X1' * X2);
        %多项式核函数,这里设置的3次核函数
    case 'polynomial'
        K = (X1' * X2).^3;
        %RBF核函数,需要设置核函数的带宽
    case 'rbf'
        K=zeros(size(X1,2),size(X2,2));
        for m=1:size(X1,2)
            for n=1:size(X2,2)
                K(m,n)=exp(-sum((X1(:,m)-X2(:,n)).^2)/0.345);%这里设置的核带宽σ=0.345
            end
        end
         
end
 
end

二、自定义核函数

函数的正确选取依赖产生分类问题的实际问题的特点,因为不同的实际问题对相似程度有着不同的度量,核函数可以看作一个特征提取的过程,选择正确的核函数有助于提高分类准确率。核函数的构造可以直接构造,也可以通过变换来得到。

下面来考虑这样一种情况,给定m个训练样本clip_image002,每一个clip_image004对应一个特征向量。那么,我们可以将任意两个clip_image004[1]clip_image006带入clip_image008中,计算得到clip_image010。i可以从1到m,j可以从1到m,这样可以计算出m*m的核函数矩阵(Kernel Matrix)。为了方便,我们将核函数矩阵和clip_image012都使用clip_image008[1]来表示。
如果假设clip_image008[2]是有效的核函数,那么根据核函数定义
clip_image016
可见,矩阵K应该是个对称阵。


使用-t 4参数时,可以使用自定义核函数,根据自定义核函数求出核矩阵。自定义核函数使用方法如下:

举例一

1.数据集:设训练集是train_data,设训练集有150个样本 , 测试集是test_data,设测试集有120个样本,则

1
2
3
4
5
load heart_scale.mat;
train_data = heart_scale_inst(1:150,:);
train_label = heart_scale_label(1:150,:);
test_data = heart_scale_inst(151:270,:);
test_label = heart_scale_label(151:270,:);

2.线性核函数

1
2
3
%% Linear Kernel
model_linear = svmtrain(train_label, train_data, '-t 0');
[predict_label_L, accuracy_L, dec_values_L] = svmpredict(test_label, test_data, model_linear);j

结果:Accuracy = 85% (102/120) (classification)

使用线性核函数 K(x,x') = (x * x')

训练集的核矩阵: ktrain = train_data*train_data'
测试集的核矩阵: ktest = test_data*train_data'

想要使用-t 4参数还需要把样本的序列号放在核矩阵前面 ,形成一个新的矩阵:

1
2
3
4
5
6
7
% 使用线性核函数 K(u,v) = (u' * v)
Ktrain = train_data * train_data';   
Ktrain = [(1:150)',ktrain];     %样本的序列号放在核矩阵前面
model = svmtrain(train_label, Ktrain, '-t 4');  % 输入 Ktrain
Ktest = test_data*train_data';  %求测试集核矩阵
Ktest = [(1:120)', Ktest];      %样本的序列号放在核矩阵前面
[predict_label, accuracy, P1] = svmpredict(test_label,Ktest,model); % 输入Ktest

结果:和上步中使用LibSVM提供的线性核得到的结果相同

3.RBF核函数  K(x,x')=exp(-gamma*||x-x'||^2);

1
2
3
4
5
6
7
8
%% RBF Kernel
[bestacc,bestc,bestg] = SVMcgForClass(train_label,train_data,0,10,-8,1,3,0.5,0.5,1);
 
cmd = [' -t 2',' -c ',num2str(bestc),' -g ',num2str(bestg),'-v',num2str(3)];
model = svmtrain(train_label, train_data,cmd);
 
[predict_label_1, accuracy_1, dec_values_1] = svmpredict(train_label, train_data, model);
[predict_label_2, accuracy_2, dec_values_2] = svmpredict(test_label, test_data, model);

结果:

Accuracy = 87.3333% (131/150) (classification)
Accuracy = 84.1667% (101/120) (classification)

bestc = 8; bestg = 0.011;

bestc,bestg带入下面代码中,Accuracy结果相同。 

1
2
3
4
5
6
7
8
9
10
%% RBF Kernel
[trainRow,Dim]=size(train_data);
[testRow,~]=size(test_data);
Kernel = @(X,Y) exp(-bestg .* pdist2(X,Y,'euclidean').^2);
Ktrain =  [ (1:trainRow)', Kernel(train_data,train_data)];
cmd = [' -t 4',' -c ',num2str(bestc),'-v',num2str(3)];
model = svmtrain(train_label, Ktrain,cmd);
ktest =  [ (1:testRow)', Kernel(test_data,train_data)];
[predict_label_1, accuracy_1, dec_values_1] = svmpredict(train_label, Ktrain, model);
[predict_label_2, accuracy_2, dec_values_2] = svmpredict(test_label, ktest, model);

4.使用的核函数 K(x,x') = ||x|| * ||x'||

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
% 使用的核函数 K(x,x') = ||x|| * ||x'||
% 核矩阵
ktrain2 = ones(150,150);
for i = 1:150
 for j = 1:150
 ktrain2(i,j) = sum(train_data(i,:).^2)^0.5 * sum(train_data(j,:).^2)^0.5;
 end
end
Ktrain2 = [(1:150)',ktrain2];
model_precomputed2 = svmtrain(train_label, Ktrain2, '-t 4');
  
ktest2 = ones(120,150);
for i = 1:120
 for j = 1:150
 ktest2(i,j) = sum(test_data(i,:).^2)^0.5 * sum(train_data(j,:).^2)^0.5;
 end
end
Ktest2 = [(1:120)', ktest2];
[predict_label_P2, accuracy_P2, dec_values_P2] = svmpredict(test_label, Ktest2, model_precomputed2);

Accuracy = 67.5% (81/120) (classification)

5.使用的核函数 K(x,x') = (x * x') / ||x|| * ||x'||

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
% 使用的核函数 K(x,x') = (x * x') / ||x|| * ||x'||
% 核矩阵
ktrain3 = ones(150,150);
for i = 1:150
 for j = 1:150
 ktrain3(i,j) = ...
 train_data(i,:)*train_data(j,:)'/(sum(train_data(i,:).^2)^0.5 * sum(train_data(j,:).^2)^0.5);
 end
end
Ktrain3 = [(1:150)',ktrain3];
model_precomputed3 = svmtrain(train_label, Ktrain3, '-t 4');
  
ktest3 = ones(120,150);
for i = 1:120
 for j = 1:150
 ktest3(i,j) = ...
 test_data(i,:)*train_data(j,:)'/(sum(test_data(i,:).^2)^0.5 * sum(train_data(j,:).^2)^0.5);
 end
end
Ktest3 = [(1:120)', ktest3];
[predict_label_P3, accuracy_P3, dec_values_P3] = svmpredict(test_label, Ktest3, model_precomputed3);

Accuracy = 84.1667% (101/120) (classification)

 6.总结

  1.对于自定义核函数,需要计算训练集、测试集的核矩阵,核矩阵由使用的核函数计算得。

  2.样本的序列号要放在核矩阵前面,形成一个新的矩阵。

 

举例二 混合核函数
多项式核函数有良好的全局性能,具有很强的外推能力,并且多项式的次数越低,其外推能力越强。而Gauss径向基核函数则是局部性强,其内推能力随着参数的减小而减弱。通过把两类核函数结合起来,发挥它们各自的优点,得到学习能力和推广性都很强,兼具良好的外推和内推能力的核函数,利用多项式核函数和径向基核函数构建混合核函数分类模型,表达式为:

式中:Kpoly 为多项式核函数;Krbf 为径向基核函数;λ∈(0,1)。当 λ 较大时,混合核函数的性能表现得优良一些。


————————————————————————————————————————————————————
参考文献:1.https://blog.csdn.net/xgf415/article/details/51417791

     2.LibSVM核函数 - 侯凯 - 博客园 (cnblogs.com)

       3.SVM的MATLAB实现和程序讲解 - 知乎 (zhihu.com)

posted @   学习记录本  阅读(605)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
点击右上角即可分享
微信分享提示