zoukankan      html  css  js  c++  java
  • 6.LibSVM核函数

    libsvm的核函数类型(svmtrain.c注释部分):

    "-t kernel_type : set type of kernel function (default 2) "
    "    0 -- linear: u'*v "
    "    1 -- polynomial: (gamma*u'*v + coef0)^degree "
    "    2 -- radial basis function: exp(-gamma*|u-v|^2) "
    "    3 -- sigmoid: tanh(gamma*u'*v + coef0) "
    "    4 -- precomputed kernel (kernel values in training_instance_matrix)

    linear:线性核函数(linear kernel)
    polynomial:多项式核函数(ploynomial kernel)
    RBF:径向基核函数(radical basis function)
    sigmoid: 神经元的非线性作用函数核函数(Sigmoid tanh)
    precomputed :用户自定义核函数
    究竟用哪一种核函数取决对数据处理的要求,不过建议一般都是使用RBF核函数。因为RBF核函数具有良好的性态,在实际问题中表现出了良好的性能。

    下面来考虑这样一种情况,给定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参数后,需要根据核函数给出核矩阵即可。比如:线性核函数是 K(x,x') = (x * x'),设训练集是train_data,设训练集有150个样本, 测试集是test_data,设测试集有120个样本。
    训练集的核矩阵是 ktrain1 = train_data*train_data'
    测试集的核矩阵是 ktest1 = test_data*train_data'
    想要使用-t 4参数还需要把样本的序列号放在核矩阵前面 ,形成一个新的矩阵。然后使用svmtrain建立支持向量机,再使用svmpredict进行预测即可。形式与使用其他-t参数稍有不同,如下。

    clear;
    clc;
    
    %%
    load heart_scale.mat;
    % Split Data
    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,:);
     
    %% 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);
     
    %% Precomputed Kernel One
    % 使用的核函数 K(x,x') = (x * x')
    % 核矩阵
    ktrain1 = train_data*train_data';
    Ktrain1 = [(1:150)',ktrain1];
    model_precomputed1 = svmtrain(train_label, Ktrain1, '-t 4');
    ktest1 = test_data*train_data';
    Ktest1 = [(1:120)', ktest1];
    [predict_label_P1, accuracy_P1, dec_values_P1] = svmpredict(test_label, Ktest1, model_precomputed1);
    % 这样得到的结果和上步中使用LibSVM提供的线性核得到的结果相同。
    
    %% Precomputed Kernel Two
    % 使用的核函数 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);
    
    %% Precomputed Kernel Three
    % 使用的核函数 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);

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

  • 相关阅读:
    C# 日期帮助类【原创】
    C# 发送邮件
    每日一题力扣453
    每日力扣628
    每日一题力扣41巨坑
    每日一题力扣274
    每日一题力扣442有坑
    每日一题力扣495
    每日一题力扣645
    每日一题力扣697
  • 原文地址:https://www.cnblogs.com/houkai/p/3392407.html
Copyright © 2011-2022 走看看