⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mslinearsolve.m

📁 一个简洁好用的SVM代码
💻 M
字号:
function [x,y,flag,z,s,w] = mslinearsolve(c,A,b,C),% Simple Linear Optimization for Franke and Wolfe's multi-label SVM method% % USAGE  :   [x,y,flag,z,s,w] = mslinearsolve(c,A,b,C)%% PARAMETERS:%          c = (n,1) vector%          A = (m,n) matrix %          b = (m,1) vector%          C = (n,1) vector (with finite values)%%          x = primal variables%          y = lagrangian coeff of equality constraints%          z = dual variables of x%          s = primal auxiliary variable (only if C < Inf)%          w = dual variable of s%          flag = integer value, set to 1 if no problem (-1 if unbounded and 0 otherwise)%            % DESCRIPTION:%                minimize c'*x + 0.5*trdoff*(x-alpha)'*(x-alpha)%%                subject to A*x=b%                           0<= x(i) <= C(i)%                %            The optimization method is a predictor-corrector method with a logarithmic barrier.%            For separable problems such as this, this method is quite fast. It tends to minimize%            the dot product c'*x. %            The term trdoff controls the trade-off between both parts. Here, trdoff=0 and alpha=0. %%% EXTRA PARAMETERS:%%        It is possible to add init values for [x,y,z] and for [s,w] (columnwise). For instance, one could use:%        %        >[x,y,flag,z,s,w] = mslinearsolve(c,A,b,C,x0,y0,z0);%           %        Or%%        >[x,y,flag,z,s,w] = mslinearsolve(c,A,b,C,x0,y0,z0,s0,w0);%%        The first command executes slinearsolve with x0,y0 and z0 as init values (these vectors are%        not required to satisfy the contraints A*x=b, they are just init values for the corrector%        predictor method). They are (n,1) real vectors. %% ERRORS AND BUGS:%            As for the method squadsolve.m, this procedure is iterative and the max. number of iteration%            is stored in max_iter. If it is reached (which is unlikely to happen), the output of the procedure%            may give a suboptimal solution.%% NOTES:     %            The heuristics used to set the barrier parameter and the init value are taken from LOQO's method. %            The other tricks (such as putting all parameters away from zero) are taken from HOPDM %            of Altman and Gondzio.%%            This code should be read with the tech. report:%                "Regularized Symmetric Indefinite Systems in Interior Point%                 Methods for Linear and Quadratic Optimization", %                 A. Altman and J. Gondzio, Logilab Tech. Report 1998.6%%            The quadratic term is not used in this implementation. However, if one wants to add it, just %            change the value of trdoff and of alpha.%% Andre Elisseeff, May. 2001% aelissee@barnhilltechnologies.com    % init values  verbose = 0; % if 1 then print information  flag=0;   n = size(A,2);  m = size(A,1);  mu = 1;  maxiter = 50;   itref = 1;  cont = 1;    clean_eps = 10^(-8);  trdoff = 0;  alpha = zeros(n,1);  % init from LOQO  x=100*ones(n,1);  z=100*ones(n,1);  y=100*ones(m,1);  if min(C) < Inf,    s=100*ones(n,1);    w=100*ones(n,1);  else    s=[];w=[];  end; % Values of the original HOPDM of Gondzio and Altman    dinf = 10^(-14);  smallz = 10^(-14);  smallt = 2.3*10^(-16);    opttol = 10^(-6);  % Description of variables:%% theta (real) (n,1) vector  -> diagonal matrix (thus stored as vector) to%                               be inverted to compute the predictor and the%                               corrector step. See tech. report of Altman and%                               Gondzio for further details.% mu         -> barrier parameter% u          -> vector of upper bounds on x (if C < Inf)% pobj       -> primal objective function% pobjo      -> old primal objective function% dobj       -> dual objective function% dobjo      -> old dual objective function% dlgap      -> dual gap% oldgap     -> old dual gap% objQ       -> 0.5*x'*x% n          ->   number of variables in the initial pb (size of x)% m          ->   number of constraints in A% Q          ->   number of classes% x,s  (real) (n,1) vector  ->   primal variables% z,w  (real) (n,1) vector  ->   dual variables% dinf       ->   smallest acceptable values for x,y,s etc...% smallz     ->   smallest acceptable values for z in the inversion%                 of theta% smallt     ->   smallest acceptable values for t in the computation%                 of the matrix theta% clean_eps  ->   precision to clean x (at the end of the procedure)% opttol     ->   acceptable tolerance for optimality conditions% itref      ->   iteration counter% maxiter    ->   maximum number of iterations% cont       ->   boolean value to continue in the loop% flag       ->   set to 1 => computation ok, set to 0 => pb in the computation%                 set to -1 => solution unbounded.%                 example: maxiter has been reached (flag=0).% trdoff     ->   trade-off between the linear and the quadratic part of the objective%                 function% ind_tmp_Y  ->   indices corresponding to alpha_{c(p)p}  %## AE : scale the problem, has been tested and seems to work%## better : more stable...         u = C;     % init values of primal and dual objective functions   objQ = 0.5*trdoff*x'*x;   % add the alpha term in the linear part   c = c - trdoff*alpha;      pobjo = abs(c'*x+objQ) + 1;  if C < inf,    dobjo = abs(-objQ+b'*y - u'*w) +1;  else    dobjo = abs(b'*y-objQ) +1;  end;%###############%## MAIN LOOP%###############  while (cont)&(itref<=maxiter)  % Compute the primal objective function    objQ = 0.5*trdoff*x'*x;    pobj = c'*x + objQ;    if (C<Inf)      dobj = b'*y - u'*w -objQ;    else      dobj = b'*y -objQ;    end;    dlgap = pobj - dobj;    dp = abs(pobj)/(abs(pobjo)+1);    dd = abs(dobj)/(abs(dobjo)+1);    dobjo = dobj;    pobjo = pobj;    if verbose,        if C<Inf,            disp(sprintf('%d - pobj : %f - dobj : %f\n',itref,pobj,dobj));        else               disp(sprintf('%d - pobj : %f - dobj : %f\n',itref,pobj,dobj));        end;    end;      % Check if the solution are bounded        if (dp > 10^6)       disp(sprintf('Solution not bounded in the primal. Exit.\n'));      flag=-1;      return;    end;    if (dd > 10^6)       disp(sprintf('Solution not bounded in the dual. Exit.\n'));      flag=-1;      return;    end;      % test if optimality        oldgap = dlgap;    dp = abs(dobj) + 1;    if (abs(dlgap)/dp) <= opttol & itref > 1        if verbose,          disp(sprintf('Optimal solution found. Exit.\n'));        end;        cont = 0;        break;    end;        dp = dp + abs(pobj);    T = abs(dlgap)/dp;      % put the variables away from zero (from QHOPDM)    if (itref <= 3)      ax = 2*10^(-3);      az = 10^(-3);    elseif (T >= 0.8)      ax = 2*10^(-4);      az = 10^(-4);    elseif (T >= 0.1)      ax = 2*10^(-5);      az = 10^(-5);    elseif (T >=0.01)      ax = 2*10^(-6);      az = 10^(-6);    elseif (T>=0.001)      ax = 2*10^(-7);      az = 10^(-7);    elseif (T>=0.0001)      ax = 2*10^(-8);      az = 10^(-7);    elseif (T>=0.00001)      ax = 2*10^(-9);      az = 10^(-9);    else      ax = T*10^(-5);      az = ax;    end;      % consider only variables that can be changed    x = x + ax;    z = z + az;    if C < Inf      s = s + ax;      w = w + az;    end;  % Compute the values of xi_b, xi_c and xi_u      % These variables are not described here. See tech.  % report of Altman and Gondzio for further details.      xi_b = -A*x + b;        xi_c = c - A'*y - z + trdoff*x;    xi_z =  - x.*z;    if C < Inf,      xi_c=xi_c + w;      xi_u = u - x - s;      xi_w = - s.*w;    end;      % Compute theta = xs/(zs + wx)      % for bounded variables    if C<Inf,      dp = x;      if (max(abs(dp))<= smallz)        disp(sprintf('Conditioning problem to invert theta. Abort.\n'));        return;      end;      dpp= s;      if (max(abs(dpp))<= smallz)        disp(sprintf('Conditioning problem to invert theta. Abort.\n'));        return;      end;      theta=z./dp + w./dpp;    end;      % for unbounded variables    if C==Inf,      dp = x;      if (max(abs(dp))<= smallz)         disp(sprintf('Conditioning problem to invert theta. Abort.\n'));        return;      end;      theta = z./dp;    end;    tmp = ones(size(theta));    theta = tmp./(trdoff*(tmp)+theta);       % neglect small elements of theta array        neglect = find(theta < smallt);    if ~isempty(neglect)      theta(neglect)=zeros(size(neglect));    end;      % and control large elements of theta        neglect = find(theta >= 10^8);    if ~isempty(neglect)      theta(neglect)=(10^4)*sqrt(theta(neglect));    end;  % solve the system for mu = 0            if C < Inf,      f = xi_c-xi_z./x+(xi_w - xi_u.*w)./s ;      h = xi_b;    else      f = xi_c - xi_z./x;      h = xi_b;    end;    AA = zeros(size(A));    for i=1:size(A,1),      AA(i,:) = A(i,:).*theta';    end;    to_inv = AA*f + h;    AAA = AA*A';    dy = AAA\to_inv;    dx = AA'*dy - f.*theta;    dz = (xi_z-z.*dx)./x;    if C<Inf,      ds = xi_u - dx;      dw = (xi_w-w.*ds)./s;    end;          % end of solving the system      % determine the maximum step size apk (primal) and  % adk (dual) to stay in feasible region  % (x,s,z,w must be positive and greater than dinf)    indz = find(dz<0);        indx = find(dx<0);    inds=[];mins=1;    indw=[];minw=1;    if C < Inf,      inds = find(ds<0);      indw = find(dw<0);      if ~isempty(inds)        mins = min(-(s(inds)-dinf)./ds(inds));      else        mins = 1;      end;      if ~isempty(indw)        minw = min(-(w(indw)-dinf)./dw(indw));      else        minw = 1;      end;          end;    if ~isempty(indx)      minx = min(-(x(indx)-dinf)./dx(indx));    else      minx = 1;    end;    apk = min([minx,mins,1]);    if ~isempty(indz),      minz = min(-(z(indz)-dinf)./dz(indz));    else      minz = 1;    end;    adk = min([minw,minz,1]);        ax = sum(x.*z);    as = sum((x+apk*dx).*(z+adk*dz));    az = sum(dx.^2+dz.^2);    if C < Inf,      ax = ax + sum(s.*w);      as = as + sum((s+apk*ds).*(w+adk*dw));      az = az + sum(ds.^2+dw.^2);    end;      % check if complementary gap is less than opttol        if (as <= opttol)      if verbose,        disp(sprintf('Complementary gap is less than %f\n',opttol));      end;      cont = 0;      x = x + apk*dx;      y = y + adk*dy;      z = z + adk*dz;      if C < Inf,       s = s + apk*ds;       w = w + adk*dw;      end;    % get out of the while loop      break;    end;          % Set the barrier parameter : LOQO's heuristic    ap = min(apk,adk);    mu = (ax/(2*n))*(0.95*(1/ap) -1)^2/(0.95*(1/ap)+10)^2;  % HOPDM heuristic:    mu = (as/ax)^2*as/n;      % Compute the new direction (algo. of Mehrotra) of order 1    xi_z =  - x.*z + mu*ones(size(x)) - dx.*dz;    f = xi_c - xi_z./x;    if C < Inf      xi_w = - s.*w + mu*ones(size(s)) - ds.*dw;      f=f+ xi_w./s - (w.*xi_u)./s;    end;    h = xi_b;      % solve the system for mu different from zero              AA = zeros(size(A));    for i=1:size(A,1),      AA(i,:) = A(i,:).*theta';    end;    to_inv = AA*f + h;    AAA = AA*A';    dy = AAA\to_inv;    dx = AA'*dy - f.*theta;    dz = (xi_z-z.*dx)./x;    if C<Inf,      ds = xi_u - dx;      dw = (xi_w-w.*ds)./s;    end;            % end for solving      % determine the maximum step size apk (primal) and  % adk (dual) to stay in feasible region  % (x,s,z,w must be positive)        indz = find(dz<0);        indx = find(dx<0);    if C < Inf,      inds = find(ds<0);      indw = find(dw<0);      if ~isempty(inds)        mins = min(-s(inds)./ds(inds));      else    mins=1;      end;      if ~isempty(indw)        minw = min(-w(indw)./dw(indw));      else    minw=1;      end;    end;    if ~isempty(indx)      minx = min(-x(indx)./dx(indx));    else      minx=1;    end;    alpha_p = min([minx,mins,1]);    if ~isempty(indz)      minz = min(-z(indz)./dz(indz));    else      minz=1;    end;    alpha_d = min([minw,minz,1]);        spd = min(alpha_p,alpha_d);  % Compute step factors       %      fp =0.95*spd;  %      fd =0.95*spd; (from QHOPDM)    fp = 0.95*spd;    fd = 0.95*spd;          x = x +fp*dx;          y = y +fd*dy;    z= z + fd*dz;    if C < Inf,      w = w + fd*dw;      s = s +fp*ds;          end;    itref=itref+1;end;%#####################%### End Main Loop%#####################  if (cont==0)    flag=1;  end;  % clean x  tmp = find(x < clean_eps/n | x < 100*eps);  if ~isempty(tmp)    x(tmp) = zeros(size(tmp));  end;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -