机器学习(21) SVM 示例2:【Octave】解决二分类(非线性SVM[边界清晰])

1 训练集ex6data2.mat可视化

绘制训练集函数plotData.m

机器学习(20)中的plotData.m

训练集可视化脚本GaussianSVM部分代码

%% Initialization

clear ; close all; clc

%% =============== Part 1: 加载并可视化数据 ================

fprintf('Loading and Visualizing Data ...\n')

% 从文件 ex6data2.mat中加载,会发现环境中有X,y变量值:

load('ex6data2.mat');

% 绘制训练集数据

plotData(X, y);

fprintf('Program paused. Press enter to continue.\n');

pause;

执行结果

可以看到这里的数据集分两类,但SVM的决策边界是个曲线。且边界清晰

2 SVM的高斯核函数gaussianKernel.m

function sim = gaussianKernel(x1, x2, sigma)

  % gaussianKernel(x1, x2, sigma)返回一个在x1和x2之间的径向基函数核,

  % 输入参数:   x1,x2 列向量。确保x1和x2是维度一致的列向量

  % 返 回 值:  sim 返回一个在x1和x2之间的高斯核

  x1 = x1(:); x2 = x2(:);

  % You need to return the following variables correctly.

  sim = 0;

  sim = exp(-sum((x1-x2).^2)/(2*sigma^2));

end

3 训练函数svmTrain.m

机器学习(20)中的svmTrain.m

4 预测函数svmPredict.m

function pred = svmPredict(model, X)

  % svmPredict(model, X)返回使用经过训练的SVM模型的预测向量

  % 输入: model  由svmTrain函数得出的模型

  %       X 训练矩阵,行数为样本数,列数为输入特征数

  % 输出: pred 是一个行数为样本数,列数为1的{0,1}值的预测列向量。

  % 检查我们是否得到了一个列向量,如果是,那么假设我们只有需要对单个例子进行预测

  if (size(X, 2) == 1)

    % Examples should be in rows

    X = X';

  endif

  % 数据集

  m = size(X, 1); %样本数

  p = zeros(m, 1); % 初始化列向量的元素为0

  pred = zeros(m, 1); % 初始化列向量的元素为0

  if strcmp(func2str(model.kernelFunction), 'linearKernel')

    % 如果使用线性核函数,我们可以直接使用权值和偏差

    p = X * model.w + model.b;

  elseif strfind(func2str(model.kernelFunction), 'gaussianKernel')

    % 矢量化RBF核

    % 这相当于在每一对例子上计算内核

    X1 = sum(X.^2, 2);

    X2 = sum(model.X.^2, 2)';

    K = bsxfun(@plus, X1, bsxfun(@plus, X2, - 2 * X * model.X'));

    K = model.kernelFunction(1, 0) .^ K;

    K = bsxfun(@times, model.y', K);

    K = bsxfun(@times, model.alphas', K);

    p = sum(K, 2);

  else

    % 其他非线性核

    for i = 1:m

      prediction = 0;

        for j = 1:size(model.X, 1)

          prediction = prediction + ...

            model.alphas(j) * model.y(j) * ...

            model.kernelFunction(X(i,:)', model.X(j,:)');

        endfor

      p(i) = prediction + model.b;

    endfor

  endif

  % 将预测转换为0 / 1

  pred(p >= 0) =  1;

  pred(p <  0) =  0;

end

5 可视化SVM决策边界函数visualizeBoundary.m

function visualizeBoundary(X, y, model, varargin)

  % visualizeBoundary绘制支持向量机学习到的非线性决策边界

  % 输入: X 训练矩阵,行数为样本数,列数为输入特征数

  %       y 训练集输出特征向量,是一个包含1和0的列向量,行数为样本数,列数为1

  %       model  由svmTrain函数得出的模型

  %       varargin

 

  plotData(X, y) % 绘制训练数据

  % 对一个值网格进行分类预测

  x1plot = linspace(min(X(:,1)), max(X(:,1)), 100)';

  x2plot = linspace(min(X(:,2)), max(X(:,2)), 100)';

  [X1, X2] = meshgrid(x1plot, x2plot);

  vals = zeros(size(X1));

  for i = 1:size(X1, 2)

    this_X = [X1(:, i), X2(:, i)];

    vals(:, i) = svmPredict(model, this_X);

  endfor

  % 绘制SVM决策边界

  hold on

  contour(X1, X2, vals, [0.5 0.5], 'b');

  hold off;

end

6 非线性SVM脚本GaussianSVM.m

%% Initialization

clear ; close all; clc

%% =============== Part 1: 加载并可视化数据 ================

fprintf('Loading and Visualizing Data ...\n')

% 从文件 ex6data2.mat中加载,会发现环境中有X,y变量值:

load('ex6data2.mat');

% 绘制训练集数据

plotData(X, y);

fprintf('Program paused. Press enter to continue.\n');

pause;

%% ==================== Part 2: 线性SVM训练 ====================

%  在实现了内核之后,我们现在可以使用它来训练SVM分类器。

% 从文件 ex6data2.mat中加载,会发现环境中有X,y变量值:

fprintf('\nTraining SVM with RBF Kernel (this may take 1 to 2 minutes) ...\n');

% Load from ex6data2:

% You will have X, y in your environment

load('ex6data2.mat');

% SVM 参数

C = 1; sigma = 0.1;

% 我们在这里将容忍度和max_passes设置得更低,

% 以便代码运行得更快。然而,在实践中,您将希望将训练运行到收敛。

model= svmTrain(X, y, C, @(x1, x2) gaussianKernel(x1, x2, sigma));

visualizeBoundary(X, y, model);

fprintf('Program paused. Press enter to continue.\n');

pause;

7 执行脚本GaussianSVM.m结果

左图无法用一个线性决策边界划分正负样本数据。
右图是用高斯核SVM训练的决策边界。这个决策边界能够正确分离大多数的正负样本,并且能很好的拟合数据。

猜你喜欢

转载自blog.csdn.net/luyouqi11/article/details/132173530
svm