lassoactiveset.m

来自「lasso变量选择方法」· M 代码 · 共 221 行

M
221
字号
function [w,wp,iteration] = LassoActiveSet(X, y, t,varargin)% This function computes the Least Squares parameters% whose 1-Norm is less than t%% Method used:%   Local Linearization and Active Set Method%   Proposed in [Osborne et al., 2000], [Osborne et al., 2000b]%% Mode:%   0: Maintain QR Factorization of X'*X%   1: Maintain QR Factorization of X%% Modifications:%   The initial method treats all variables equally on the first iteration%   This implementation uses the heuristic suggested in Shevade/Perkins%   to introduce the first variable, this avoids much of the complications%   associated with sign infeasibility[maxIter,verbose,optTol,threshold,mode] = process_options(varargin,'maxIter',10000,'verbose',2,'optTol',1e-5,'zeroThreshold',1e-4,'mode',0);[n p] = size(X);iteration = 0;sigma_old = ones(p,1);% initializebeta = zeros(p,1);sigma = abs(beta) > threshold;theta = zeros(p,1);% Start logif verbose==2    fprintf('%10s %15s %15s %15s %5s %5s\n','iter','n(w)','n(step)','f(w)','opt(wi)','free');    k=1;    wp = beta;endXX = X'*X;Xy = X'*y;while iteration < maxIter    % Get the values associated with the active set    beta_sigma = beta(sigma);    theta_sigma = theta(sigma);    if sum(sigma-sigma_old) ~= 0        Xy_sigma = Xy(sigma);        % QR insert        if sum(sigma) <= 1            if mode == 0                [Q,R] = qr(XX(sigma,sigma),0);            else                [Q,R] = qr(X(:,sigma));            end        else            [junk qrPos] = max(abs(sigma(sigma)-sigma_old(sigma)));            if mode == 0                [Q,R] = qrinsert(Q,R,qrPos,XX(s,sigma_old),'row');                [Q,R] = qrinsert(Q,R,qrPos,XX(sigma,s),'col');            else                % The below seems to be really slow in matlab                [Q,R] = qrinsert(Q,R,qrPos,X(:,s),'col');            end        end    end    % Solve the local linerization    if mode == 0        [beta_t,h] = solveKKT(sigma,theta_sigma,beta_sigma,Xy_sigma,Q,R,y,t,beta);    else        [beta_t,h] = solveKKT2(sigma,theta_sigma,beta_sigma,Q,R,y,t,beta);    end    % ============================================================    % Code below is strictly to deal with the sign infeasible case    % (doesn't usually get used)    % ============================================================    while ~(sum(sign(beta_t(sigma)) == theta_sigma) == size(theta_sigma,1))        if verbose==2            fprintf('Not Sign Feasible\n');        end        % A1: Find first zero-crossing        min_gamma = 1;        min_gamma_i = -1;        for k = 1:size(beta,1)            if (abs(beta(k)) > threshold)                gamma = -beta(k)/h(k);                if gamma > 0 && gamma < min_gamma                    min_gamma = gamma;                    min_gamma_i = k;                end            end        end        % A1: set beta to h truncated at first zero-crossing        beta = beta + min_gamma*h;        % A2: reverse sign of first zero-crossing        theta(min_gamma_i) = -theta(min_gamma_i);        % A2: recompute h        theta_sigma = theta(sigma);        beta_sigma = beta(sigma);        if mode == 0            [beta_t,h] = solveKKT(sigma,theta_sigma,beta_sigma,Xy_sigma,Q,R,y,t,beta);        else            [beta_t,h] = solveKKT2(sigma,theta_sigma,beta_sigma,Q,R,y,t,beta);        end        if sum(sign(beta_t(sigma)) == theta_sigma) == size(theta_sigma,1)            if verbose==2                fprintf('Now it is Sign Feasible\n');            end        else            if verbose==2            fprintf('It is still Sign Infeasible\n');            end            % A3: Remove the first zero-crossing from the active set            sigma_old = sigma;            sigma(min_gamma_i) = 0;            beta(min_gamma_i) = 0;            % A3: Reset beta(min_gamma) and theta(min_gamma)            beta(min_gamma_i) = 0;            theta(min_gamma_i) = 0;            beta_sigma = beta(sigma);            theta_sigma = theta(sigma);            % A3: Recompute h            Xy_sigma = Xy(sigma);            % QR Update            if mode == 0                [Q,R] = qr(XX(sigma,sigma),0); % Could do a qr delete here instead                [beta_t,h] = solveKKT(sigma,theta_sigma,beta_sigma,Xy_sigma,Q,R,y,t,beta);            else                [Q,R] = qr(X(:,sigma)); % Could do a qr delete here instead                [beta_t,h] = solveKKT2(sigma,theta_sigma,beta_sigma,Q,R,y,t,beta);            end                        if verbose == 2                if sum(sign(beta_t(sigma)) == theta_sigma) == size(theta_sigma,1)                    fprintf('Finally, it is sign feasible\n');                else                    fprintf('It is still, STILL, not sign feasible\nGoing another round\n');                end            end        end    end    % =============================================    % End of Code to deal with sign infeasible case    % =============================================    iteration = iteration+1;    % compute violation    v_denom = norm(Xy_sigma-X(:,sigma)'*X*beta_t,inf);    if v_denom > 0        v_t = (Xy-XX*beta_t)/v_denom;    else        v_t = (Xy-XX*beta_t)*inf;    end    j = p-sum(abs(beta_t) < threshold & abs(v_t) > 1+threshold);    % update log    if verbose==2        fprintf('%10d %15.2e %15.2e %15.2e %5d %5d\n',iteration,sum(abs(beta_t)),sum(abs(beta_t-beta)),sum((X*beta-y).^2),sum(j),sum(sigma));        k=k+1;        wp(:,k) = beta_t;    end    % check for optimality    if j == p || t == 0        if verbose            fprintf('All Components satisfy condition\n');        end        break;    end    % find and add the most violating variable    % On the first iteration, all variables are equally violating    % so we're going to use the Shevade/Perkins trick to introduce    % a good first variable, this often means we may not have to deal with    % sign feasibility later issues later    if iteration == 1        g = computeSlope(beta,t,XX*beta-Xy,threshold);        [max_viol s] = max(abs(g));    else        [maxi s] = max(abs(sigma-1).*abs(v_t));    end    % update the active set    sigma_old = sigma;    sigma(s) = 1;    theta(s) = sign(v_t(s));    beta = beta_t;endif verbosefprintf('Number of iterations: %d\n',iteration);endw = beta_t;endfunction [beta_t,h] = solveKKT(sigma,theta_sigma,beta_sigma,Xy_sigma,Q,R,y,t,beta)% X'X = Q*R% mu = max(0, theta'(X'X)^-1X'y - t) / theta'(X'X)^-1 theta)% h = (X'X)^-1 * (X'(Y-Xw) - mu*theta)mu_denom = (theta_sigma'*(R \ (Q'*theta_sigma)));if mu_denom ~= 0    mu = max(0,((theta_sigma'*(R \ (Q'*Xy_sigma))) - t)/mu_denom);else    mu = 0;endh = zeros(length(beta),1);h(sigma == 1) = R \ (Q'*((Xy_sigma-Q*R*beta_sigma)-(mu*theta_sigma)));beta_t = beta+h;endfunction [beta_t,h] = solveKKT2(sigma,theta_sigma,beta_sigma,Q,R,y,t,beta)% X = Q*R% mu = max(0, theta'(X'X)^-1X'y - t) / theta'(X'X)^-1 theta)% h = (X'X)^-1 * (X'(Y-Xw) - mu*theta)mu_denom = (theta_sigma'*(R\(R'\theta_sigma)));if mu_denom > 0    mu = max(0,(theta_sigma'*((R\(Q'*y))) - t) / mu_denom);else    mu = 0;endh = zeros(length(beta),1);h(sigma == 1) = (R\(R'\(R'*(Q'*y-R*beta_sigma)-mu*theta_sigma)));beta_t = beta+h;end

⌨️ 快捷键说明

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