启发式选择

%%
%   svm 简单算法设计 --启发式选择
%%
clc
clear
close all
% step=0.05;error=1.2;
% [data, label]=generate_sample(step,error);
category=load(‘category.mat‘);
label=category.label;
feature=load(‘feature.mat‘);
data=feature.data;
[num_data,d] = size(data); % 样本数量,维度,维度在下面好像没有用到
%% 定义向量机参数
alphas = ones(num_data,1)-0.999999;
b = 0;
error = zeros(num_data,2);
tol = 0.001;
C = 600000;
iter = 0;
max_iter = 30;
alpha_change = 0;
entireSet = 1;%作为一个标记看是选择全遍历还是部分遍历

%第一个变量先遍历间隔边界(0<alpha<C)上的支持向量点(此时松弛变量等于0),检验其是否满足KKT条件,若全部满足再遍历整个样本
%第一个变量选取违反KKT条件最严重的样本点所对应的变量,意思是首先更新最糟糕的点
%选择第二个变量要使得|E1-E2|最大,即使得乘子的变化最大,要用启发式标准
%第二个变量的选择好像是先看有没有违反KKT条件的点,若有则选择,若没有则按照|E1-E2|来选择

while (iter < max_iter) && ((alpha_change > 0) || entireSet)
    alpha_change = 0;
    % -----------全遍历样本-------------------------
    if entireSet
        for i = 1:num_data
            Ei = calEk(data,alphas,label,b,i);%计算误差
            %此处的条件既是选取第一个变量的标准,首先考虑的是间隔边界(0<alpha<C)上的支持向量点中不满足KKT条件的点所对应的变量
            %该条件困扰了我两天,实际上原来的写法过于虚伪,让人看不透摸不清,实际上写清楚了让人一看就明了。
            if (label(i)*Ei<-0.001 && alphas(i)<C)||(label(i)*Ei>0.001 && alphas(i)>0)
            %if (0<alphas(i) && alphas(i)<C && label(i)*Ei~=0)%写成这个形式要让alphas的初值大于零否则进不来循环体。
                %选择下一个alphas
                [j,Ej] = select(i,data,num_data,alphas,label,b,C,Ei,entireSet);
                alpha_I_old = alphas(i);
                alpha_J_old = alphas(j);
                if label(i) ~= label(j)
                    L = max(0,alphas(j) - alphas(i));
                    H = min(C,C + alphas(j) - alphas(i));
                else
                    L = max(0,alphas(j) + alphas(i) -C);
                    H = min(C,alphas(j) + alphas(i));
                end
                if L==H
                    continue;end
                eta = 2*data(i,:)*data(j,:)‘- data(i,:)*...
                    data(i,:)‘ - data(j,:)*data(j,:)‘;
                if eta >= 0
                    continue;end
                alphas(j) = alphas(j) - label(j)*(Ei-Ej)/eta;
                %限制范围
                if alphas(j) > H
                    alphas(j) = H;
                elseif alphas(j) < L
                    alphas(j) = L;
                end
                if abs(alphas(j) - alpha_J_old) < 1e-4
                    continue;end
                alphas(i) = alphas(i) + label(i)*label(j)*(alpha_J_old-alphas(j));
                b1 = b - Ei - label(i)*(alphas(i)-alpha_I_old)*data(i,:)*data(i,:)‘- label(j)*(alphas(j)-alpha_J_old)*data(i,:)*data(j,:)‘;
                b2 = b - Ej - label(i)*(alphas(i)-alpha_I_old)*data(i,:)*data(j,:)‘- label(j)*(alphas(j)-alpha_J_old)*data(j,:)*data(j,:)‘;
                if (alphas(i) > 0) && (alphas(i) < C)
                    b = b1;
                elseif (alphas(j) > 0) && (alphas(j) < C)
                    b = b2;
                else
                    b = (b1+b2)/2;
                end
                alpha_change = alpha_change + 1;
            end
        end
         iter = iter + 1;
   % --------------部分遍历(alphas=0~C)的样本--------------------------
    else
        index = find(alphas>0 & alphas < C);
        for ii = 1:length(index)
            i = index(ii);
            Ei = calEk(data,alphas,label,b,i);%计算误差
            if (label(i)*Ei<-0.001 && alphas(i)<C)||...
                    (label(i)*Ei>0.001 && alphas(i)>0)
                %选择下一个样本
                [j,Ej] = select(i,data,num_data,alphas,label,b,C,Ei,entireSet);
                alpha_I_old = alphas(i);
                alpha_J_old = alphas(j);
                if label(i) ~= label(j)
                    L = max(0,alphas(j) - alphas(i));
                    H = min(C,C + alphas(j) - alphas(i));
                else
                    L = max(0,alphas(j) + alphas(i) -C);
                    H = min(C,alphas(j) + alphas(i));
                end
                if L==H
                    continue;end
                eta = 2*data(i,:)*data(j,:)‘- data(i,:)*...
                    data(i,:)‘ - data(j,:)*data(j,:)‘;
                if eta >= 0
                    continue;end
                alphas(j) = alphas(j) - label(j)*(Ei-Ej)/eta;
                %限制范围
                if alphas(j) > H
                    alphas(j) = H;
                elseif alphas(j) < L
                    alphas(j) = L;
                end
                if abs(alphas(j) - alpha_J_old) < 1e-4
                    continue;end
                alphas(i) = alphas(i) + label(i)*...
                    label(j)*(alpha_J_old-alphas(j));
                b1 = b - Ei - label(i)*(alphas(i)-alpha_I_old)*...
                    data(i,:)*data(i,:)‘- label(j)*...
                    (alphas(j)-alpha_J_old)*data(i,:)*data(j,:)‘;
                b2 = b - Ej - label(i)*(alphas(i)-alpha_I_old)*...
                    data(i,:)*data(j,:)‘- label(j)*...
                    (alphas(j)-alpha_J_old)*data(j,:)*data(j,:)‘;
                if (alphas(i) > 0) && (alphas(i) < C)
                    b = b1;
                elseif (alphas(j) > 0) && (alphas(j) < C)
                    b = b2;
                else
                    b = (b1+b2)/2;
                end
                alpha_change = alpha_change + 1;
            end
        end
        iter = iter + 1;
    end
    % --------------------------------
    if entireSet %第一次全遍历了,下一次就变成部分遍历
        entireSet = 0;
    elseif alpha_change == 0
        %如果部分遍历所有都没有找到需要交换的alpha,再改为全遍历
        entireSet = 1;
    end
    disp([‘iter ================== ‘,num2str(iter)]);
end

% 计算权值W
W = (alphas.*label)‘*data;
%记录支持向量位置
index_sup = find(alphas ~= 0);
%计算预测结果
predict = (alphas.*label)‘*(data*data‘) + b;
predict = sign(predict);
% 显示结果
figure;
index1 = find(predict==-1);
data1 = (data(index1,:))‘;
plot(data1(1,:),data1(2,:),‘+r‘);
hold on
index2 = find(predict==1);
data2 = (data(index2,:))‘;
plot(data2(1,:),data2(2,:),‘*‘);
hold on
dataw = (data(index_sup,:))‘;
plot(dataw(1,:),dataw(2,:),‘og‘,‘LineWidth‘,2);
% 画出分界面,以及b上下正负1的分界面
hold on
k = -W(1)/W(2);
x = -1.2:0.1:1.2;
y = k*x + b;
plot(x,y,x,y-1,‘r--‘,x,y+1,‘r--‘);
title([‘松弛变量范围C = ‘,num2str(C)]);
function Ek = calEk(data,alphas,label,b,k)
pre_Li = (alphas.*label)‘*(data*data(k,:)‘) + b;
Ek = pre_Li - label(k);
function [J,Ej] = select(i,data,num_data,alphas,label,b,C,Ei,choose)
maxDeltaE = 0;maxJ = -1;
if choose == 1 %全遍历---随机选择alphas
    j = randi(num_data ,1);
    if j == i
        temp = 1;
        while temp
            j = randi(num_data,1);
            if j ~= i
                temp = 0;
            end
        end
    end
    J = j;
    Ej = calEk(data,alphas,label,b,J);
else %部分遍历--启发式的选择alphas
    index = find(alphas>0 & alphas < C);
    for k = 1:length(index)
        if i == index(k)
            continue;
        end
        temp_e = calEk(data,alphas,label,b,k);
        deltaE = abs(Ei - temp_e); %选择与Ei误差最大的alphas
        if deltaE > maxDeltaE
            maxJ = k;
            maxDeltaE = deltaE;
            Ej = temp_e;
        end
    end
    J = maxJ;
end
时间: 2024-08-06 02:46:03

启发式选择的相关文章

统计学习笔记之支持向量机

支持向量机(SVM)是一种二分类模型,跟之前介绍的感知机有联系但也有区别.简单来讲,感知机仅仅是找到了一个平面分离正负类的点,意味着它是没有任何约束性质的,可以有无穷多个解,但是(线性可分)支持向量机和感知机的区别在于,支持向量机有一个约束条件,即利用间隔最大化求最优分离超平面,这时,支持向量机的解就是唯一存在的. 首先来看线性可分的支持向量机,对于给定的数据集,需要学习得到的分离超平面为: 以及对应的分类决策函数: 一般而言,一个点距离分离超平面的远近可以表示分类预测的确信程度.如果超平面确定

SVM之SMO算法(转)

支持向量机(Support Vector Machine)-----SVM之SMO算法(转) 此文转自两篇博文 有修改 序列最小优化算法(英语:Sequential minimal optimization, SMO)是一种用于解决支持向量机训练过程中所产生优化问题的算法.SMO由微软研究院的约翰·普莱特(John Platt)发明于1998年,目前被广泛使用于SVM的训练过程中,并在通行的SVM库libsvm中得到实现. 1998年,SMO算法发表在SVM研究领域内引起了轰动,因为先前可用的S

&lt;转&gt;SVM实现之SMO算法

转自http://blog.csdn.net/zouxy09/article/details/17292011 终于到SVM的实现部分了.那么神奇和有效的东西还得回归到实现才可以展示其强大的功力.SVM有效而且存在很高效的训练算法,这也是工业界非常青睐SVM的原因. 前面讲到,SVM的学习问题可以转化为下面的对偶问题: 需要满足的KKT条件: 也就是说找到一组αi可以满足上面的这些条件的就是该目标的一个最优解.所以我们的优化目标是找到一组最优的αi*.一旦求出这些αi*,就很容易计算出权重向量w

[笔记]关于支持向量机(SVM)中 SMO算法的学习(一)理论总结

1. 前言 最近又重新复习了一遍支持向量机(SVM).其实个人感觉SVM整体可以分成三个部分: 1. SVM理论本身:包括最大间隔超平面(Maximum Margin Classifier),拉格朗日对偶(Lagrange Duality),支持向量(Support Vector),核函数(Kernel)的引入,松弛变量的软间隔优化(Outliers),最小序列优化(Sequential Minimal Optimization)等. 2. 核方法(Kernel):其实核方法的发展是可以独立于S

广东海洋大学 电子1151 孔yanfei python语言程序设计 第十二周

八.SVM的实现之SMO算法 终于到SVM的实现部分了.那么神奇和有效的东西还得回归到实现才可以展示其强大的功力.SVM有效而且存在很高效的训练算法,这也是工业界非常青睐SVM的原因. 也就是说找到一组αi可以满足上面的这些条件的就是该目标的一个最优解.所以我们的优化目标是找到一组最优的αi*.一旦求出这些αi*,就很容易计算出权重向量w*和b,并得到分隔超平面了. 这是个凸二次规划问题,它具有全局最优解,一般可以通过现有的工具来优化.但当训练样本非常多的时候,这些优化算法往往非常耗时低效,以致

机器学习算法与Python实践之(四)支持向量机(SVM)实现

机器学习算法与Python实践之(四)支持向量机(SVM)实现 机器学习算法与Python实践之(四)支持向量机(SVM)实现 [email protected] http://blog.csdn.net/zouxy09 机器学习算法与Python实践这个系列主要是参考<机器学习实战>这本书.因为自己想学习Python,然后也想对一些机器学习算法加深下了解,所以就想通过Python来实现几个比较常用的机器学习算法.恰好遇见这本同样定位的书籍,所以就参考这本书的过程来学习了. 在这一节我们主要是

SMO算法总结

1.概述 SMO(Sequentil Minimal Optimization)算法在支持向量机中用来求解对偶问题,即 min 12∑Ni=1∑Nj=1αiαjyiyjK(xi,xj)?∑Ni=1αi s.t.∑αiyi=0 0?αiyi?C 在这个问题中,变量是拉格朗日乘子α,一个αi对应一个样本点(xi,yi),变量总数等于样本数量N. SMO算法是一个启发式的算法,它的基本思路是:如果所有变量的解都满足KKT条件,即: ?????????????????αi≥0yif(xi)?1+ξ≥0α

机器学习经典算法详解及Python实现--基于SMO的SVM分类器

原文:http://blog.csdn.net/suipingsp/article/details/41645779 支持向量机基本上是最好的有监督学习算法,因其英文名为support vector machine,简称SVM.通俗来讲,它是一种二类分类模型,其基本模型定义为特征空间上的间隔最大的线性分类器,其学习策略便是间隔最大化,最终可转化为一个凸二次规划问题的求解. (一)理解SVM基本原理 1,SVM的本质--分类 给定一些数据点,它们分别属于两个不同的类,现在要找到一个线性分类器把这些

【转载】支持向量机(五)SMO算法

支持向量机(五)SMO算法 11 SMO优化算法(Sequential minimal optimization) SMO算法由Microsoft Research的John C. Platt在1998年提出,并成为最快的二次规划优化算法,特别针对线性SVM和数据稀疏时性能更优.关于SMO最好的资料就是他本人写的<Sequential Minimal Optimization A Fast Algorithm for Training Support Vector Machines>了. 我拜