rbmatlab 0.10.01
|
00001 function [xnew, resnorm, residual, exitflag, output, tempsols] = gplmm(funptr, x0, params) 00002 % function [vnew, resnorm, residual, output, exitflags] = gplmm(funptr, vold, params) 00003 % Global projected Levenberg-Marquard method 00004 00005 if ~isfield(params, 'beta') 00006 params.beta = 0.1; 00007 end 00008 if ~isfield(params, 'sigma') 00009 params.sigma = 1e-4; 00010 end 00011 if ~isfield(params, 'gamma') 00012 params.gamma = 0.999995; 00013 end 00014 if ~isfield(params, 'mu') 00015 params.mu = 1; 00016 end 00017 if ~isfield(params, 'TolFun') 00018 params.TolFun = 1e-10; 00019 end 00020 if ~isfield(params, 'TolLineSearch') 00021 params.TolLineSearch = 1e-10; 00022 end 00023 if ~isfield(params, 'TolFuncCount') 00024 params.TolFuncCount = 1000; 00025 end 00026 if ~isfield(params, 'TolRes') 00027 params.TolRes = 1e-8; 00028 end 00029 if ~isfield(params, 'TolChange') 00030 params.TolChange = 1e-13; 00031 end 00032 if ~isfield(params, 'maxIter') 00033 params.maxIter = 300; 00034 end 00035 if ~isfield(params, 'rho') 00036 params.rho = 1e-8; 00037 end 00038 if ~isfield(params, 'armijo_p') 00039 params.armijo_p = 2.1; 00040 end 00041 if isfield(params, 'HessFun') 00042 compute_hess_matrix = 0; 00043 else 00044 compute_hess_matrix = 1; 00045 end 00046 00047 if ~isfield(params, 'debug') 00048 params.debug = false; 00049 end 00050 00051 00052 tempsols = []; 00053 xnew = []; 00054 xold = x0; 00055 k = 0; 00056 Fold = inf; 00057 stepsizes = []; 00058 foms = []; 00059 resmaxes = []; 00060 imaxes = []; 00061 00062 [F, J] = funptr(xold); 00063 %J = computed_jacobian(J, xold, funptr); 00064 [n, m] = size(J); 00065 f = sum(F.*F); 00066 nF = sqrt(f); 00067 funcI = 1; 00068 00069 while true; 00070 00071 % function converged to zero 00072 [max_F, max_i] = max(abs(F)); 00073 imaxes = [imaxes, max_i]; 00074 resmaxes = [resmaxes, max_F]; 00075 disp(['i = ', num2str(imaxes(end)), ' max = ', num2str(resmaxes(end))]); 00076 if resmaxes(end) < params.TolRes 00077 disp(resmaxes(end)); 00078 exitflag = 1; 00079 if isempty(xnew) 00080 xnew = xold; 00081 end 00082 disp('Found solution.'); 00083 disp(resmaxes(end)); 00084 % pause; 00085 break; 00086 end 00087 00088 % change in residual too small 00089 if max(abs(F-Fold)) < params.TolChange 00090 exitflag = 3; 00091 disp('Change in residual too small'); 00092 break; 00093 end 00094 00095 %one_rows = find(xold(1:400) > 1-100*eps); 00096 % if ~isempty(one_rows) 00097 % keyboard; 00098 % end 00099 % TI = repmat(one_rows', m, 1); 00100 % TI = TI(:); 00101 % TJ = repmat((1:m)', 1, length(one_rows)); 00102 % TJ = TJ(:); 00103 % T = sparse(TI, TJ, ones(1, length(one_rows)*m), n, m); 00104 00105 %J(sub2ind([n, m], one_rows, one_rows)) = 0; 00106 % J(:, one_rows) = 0; %= %J - (J & T); 00107 00108 % gradient f 00109 gf = J'*F; 00110 00111 setup.type = 'nofill'; 00112 setup.milu = 'row'; 00113 setup.droptol = 1e-4; 00114 if isempty(xnew) 00115 if compute_hess_matrix 00116 Hess = J' * J; 00117 % [L,U] = ilu(Hess, setup); 00118 % dkU = gmres(@(X) Hess * X, -gf, 3, 1e-10, min(2500, m), L, U); 00119 % dkU = cgs(Hess, -gf, [], [], L, U); 00120 dkU = Hess \ (-gf); 00121 else 00122 % [HessTemp, precond] = params.HessFun(params, J, [], []); 00123 HessFunWrap = @(X) params.HessFun(params, J, [], X); 00124 dkU = bicgstab(HessFunWrap, -gf, 1e-12, 600);%, 00125 % precond.L,precond.U); 00126 % dkU = cgs(HessFunWrap, -gf, [], 300); 00127 % dkU = gmres(HessFunWrap, -gf, [], 1e-12, min(2500, m));%, precond.L, precond.U); 00128 end 00129 if condest(Hess) > 1e-12 00130 xnew = params.Px(xold + dkU); 00131 else 00132 xnew = xold; 00133 end 00134 Fold = funptr(xnew); 00135 end 00136 muk = min(params.mu * (Fold'*Fold), 1) / (k+1); 00137 00138 % first order optimalities 00139 foms = [foms, max(gf)]; 00140 00141 if max(abs(Fold)) > params.TolRes 00142 if compute_hess_matrix 00143 Hess = J' * J + muk .* speye(m,m); 00144 % [L,U] = ilu(Hess, setup); 00145 % dkU = bicgstab(Hess, -gf, 1e-10, 600, L, U); 00146 % dkU = gmres(Hess, -gf, 2, 1e-10, min(2500, m), L, U); 00147 dkU = Hess \ (-gf); 00148 else 00149 % [HessTemp, precond] = params.HessFun(params, J, [], []); 00150 HessFunWrap = @(X) params.HessFun(params, J, [], X) + muk .* X; 00151 dkU = gmres(HessFunWrap, -gf, 2, 1e-12, min(2500, m));%, precond.L, precond.U); 00152 end 00153 end 00154 pxnext = params.Px(xold + dkU); 00155 00156 [Fcand, Jcand] = funptr(pxnext); 00157 % Jcand = computed_jacobian(Jcand, pxnext, funptr); 00158 if params.debug 00159 [OK, ok_mat] = check_jacobian(pxnext, funptr, Jcand); 00160 end 00161 00162 funcI = funcI + 1; 00163 fcand = sum(Fcand.*Fcand); 00164 nFcand = sqrt(fcand); 00165 00166 armijo_sk = pxnext - xold; 00167 if nFcand <= params.gamma * nF 00168 % found local iteration 00169 Fold = F; 00170 F = Fcand; 00171 f = fcand; 00172 nF = nFcand; 00173 J = Jcand; 00174 xnew = pxnext; 00175 00176 else 00177 if gf' * armijo_sk <= - params.rho * norm(armijo_sk)^params.armijo_p 00178 % type line search direction 00179 sdir = armijo_sk; 00180 % disp('armijo'); 00181 else 00182 % projected gradient line search direction 00183 sdir = -gf; 00184 % disp('gradient'); 00185 end 00186 00187 tkc = 1; 00188 while true 00189 % line search too small 00190 if tkc < params.TolLineSearch 00191 exitflag = -4; 00192 tk = 0; 00193 disp('Line search failed.'); 00194 break; 00195 end 00196 00197 xktkc = params.Px(xold + tkc*sdir); 00198 00199 [Fxktkc, J] = funptr(xktkc); 00200 % J = computed_jacobian(J, xktkc, funptr); 00201 funcI = funcI + 1; 00202 00203 if sum(Fxktkc.*Fxktkc) <= f + params.sigma * gf' * (xktkc - xold); 00204 Fold = F; 00205 F = Fxktkc; 00206 f = sum(F.*F); 00207 nF = sqrt(f); 00208 00209 xnew = xktkc; 00210 tk = tkc; 00211 break; 00212 else 00213 tkc = tkc * params.beta; 00214 end 00215 end 00216 if tk == 0 00217 break; 00218 end 00219 end 00220 00221 stepsizes = [stepsizes, norm(xnew - xold)]; 00222 % x change to small 00223 if max(abs(xnew - xold)) < params.TolChange 00224 exitflag = 2; 00225 disp('Step change too small.'); 00226 break; 00227 end 00228 xold = xnew; 00229 00230 tempsols = [tempsols, xold]; 00231 00232 % too many iterations 00233 k = k+1; 00234 if k > params.maxIter 00235 exitflag = 0; 00236 disp('Maximum number of iterations exceeded.'); 00237 break; 00238 end 00239 00240 if funcI > params.TolFuncCount 00241 exitflag = -1; 00242 disp('Maximum number of function evaluations exceeded.'); 00243 break; 00244 end 00245 00246 end 00247 00248 resnorm = f; 00249 residual = F; 00250 output.iterations = k; 00251 output.funcCount = funcI; 00252 output.stepsize = stepsizes; 00253 output.firstorderopt = foms; 00254 output.resmax = resmaxes; 00255 00256 %if nargout == 6 00257 % tempsols = PCA_fixspace(tempsols, [], [], 2); 00258 %end 00259 00260 end 00261 00262 function jac_comp = computed_jacobian(jac_test, X, fun) 00263 jac_comp = zeros(size(jac_test)); 00264 00265 for j = 1:size(jac_test, 2); 00266 addend = zeros(size(X)); 00267 addend(j) = 1e-10; 00268 jac_comp(:,j) = 1/(2e-10) .* (fun(X + addend) - fun(X - addend)); 00269 end 00270 end 00271 function [OK, ok_mat] = check_jacobian(Utest, fun, jac_test, epsilon) 00272 00273 if nargin <= 3 00274 epsilon = 5e-2; 00275 end 00276 00277 jac_comp = computed_jacobian(jac_test, Utest, fun); 00278 00279 nz_elements = abs(jac_comp) > 1e6*eps; 00280 ok_mat = zeros(size(jac_test)); 00281 ok_mat(nz_elements) = abs(jac_comp(nz_elements) - jac_test(nz_elements))./(abs(jac_comp(nz_elements))) > epsilon; 00282 ok_mat = ok_mat + (nz_elements) - (abs(full(jac_test)) > 100*eps); 00283 OK = all(~ok_mat(:)); 00284 00285 if ~OK 00286 disp('Jacobian incorrect: '); 00287 keyboard; 00288 end 00289 end