%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Copyright (C) 2020 Zaiwen Wen, Haoyang Liu, Jiang Hu % % This program is free software: you can redistribute it and/or modify % it under the terms of the GNU General Public License as published by % the Free Software Foundation, either version 3 of the License, or % (at your option) any later version. % % This program is distributed in the hope that it will be useful, % but WITHOUT ANY WARRANTY; without even the implied warranty of % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the % GNU General Public License for more details. % % You should have received a copy of the GNU General Public License % along with this program. If not, see . % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% 实例:利用梯度法解 LASSO 问题 % 考虑 LASSO 问题: % % $$ \displaystyle \min_x \frac{1}{2}\|Ax-b\|_2^2+\mu\|x\|_1. $$ % % 利用 Huber 光滑化方法通过以光滑函数逼近 $\ell_1$-范数,以在得到的可微函数上利用梯度下降法对原问题近似求解。 % 我们在此展示 Huber 光滑化梯度法的应用。 %% 构建 LASSO 问题 % 设定随机种子。 clear; seed = 97006855; ss = RandStream('mt19937ar','Seed',seed); RandStream.setGlobalStream(ss); %%% % 生成随机的矩阵 $A$ 和向量 $u$ 以使得 $b=Au$。第一次实验,给定正则化系数 $\mu=10^{-3}$。 m = 512; n = 1024; A = randn(m, n); u = sprandn(n, 1, 0.1); b = A * u; mu = 1e-3; %%% % $L$ 为 $A^\top A$ 的最大特征值,用于步长的选取。 L = eigs(A'*A, 1); x0 = randn(n, 1); %% 求解 LASSO 问题 % 首先在更严格的收敛条件下进行试验,将收敛时得到的函数值作为真实的最优值的参考 $f^*$。 opts = struct(); opts.method = 'grad_huber'; opts.verbose = 0; opts.maxit = 4000; opts.ftol = 1e-8; opts.alpha0 = 1 / L; %%% % 添加连续化策略函数所在的目录。 addpath('../LASSO_con') [x, out] = LASSO_con(x0, A, b, mu, opts); f_star = min(out.fvec); %%% % Huber 光滑化的梯度法(包括 BB 步长和非精确线搜索), |out.fvec| 记录迭代过程中的目标函数值。 opts.verbose = 0; opts.maxit = 400; if opts.verbose fprintf('mu=1e-3\n'); end [x, out] = LASSO_con(x0, A, b, mu, opts); data1 = (out.fvec - f_star)/f_star; k1 = min(length(data1),400); data1 = data1(1:k1); %%% % 将 $\mu$ 修改为 |1e-2| 重复实验。 mu = 1e-2; opts = struct(); opts.method = 'grad_huber'; opts.verbose = 0; opts.maxit = 4000; opts.ftol = 1e-8; opts.alpha0 = 1 / L; [x, out] = LASSO_con(x0, A, b, mu, opts); f_star = min(out.fvec); opts.verbose = 0; opts.maxit = 400; if opts.verbose fprintf('\nmu=1e-2\n'); end [x, out] = LASSO_con(x0, A, b, mu, opts); data2 = (out.fvec - f_star)/f_star; k2 = min(length(data2),400); data2 = data2(1:k2); %% 结果可视化 % 可视化优化过程:观察目标函数值随迭代次数的变化。同时展示求解优化问题得到的解各个分量的大小。 fig = figure; semilogy(0:k1-1, data1, '-', 'Color',[0.2 0.1 0.99], 'LineWidth',2); hold on semilogy(0:k2-1, data2, '-.','Color',[0.99 0.1 0.2], 'LineWidth',1.5); legend('\mu = 10^{-3}', '\mu = 10^{-2}'); ylabel('$(f(x^k) - f^*)/f^*$', 'fontsize', 14, 'interpreter', 'latex'); xlabel('迭代步'); print(fig, '-depsc','grad.eps'); figure; subplot(2, 1, 1); plot(u, 'Color',[0.2 0.1 0.99], 'Marker', 'x', 'LineStyle', 'none'); xlim([1, 1024]); title('精确解'); subplot(2, 1, 2); plot(x, 'Color',[0.2 0.1 0.99], 'Marker', 'x', 'LineStyle', 'none'); xlim([1, 1024]); title('梯度法解'); saveas(gcf, 'solu-smoothgrad.eps'); %% 结果分析 % 采取连续化策略之后,光滑化梯度法在 400 步左右收敛到了最小值。注意到在 $\mu$ 减小到 % $10^{-2}$ 之前,两次优化的过程是完全相同的(图像不重合而是平行是由于对应的最小值不同), % 并且在每次 $\mu$ 减小后,函数值都有迅速的下降。 % 这一现象与采用连续化策略的其它优化方法是完全相同的。 % % 另外,右图展示解的分量大小,其大部分的分量集中在 $0$ 的附近。 % 这证实通过 $\ell_1$-范数正则,算法确实得到了稀疏性良好的解。 %% 参考页面 % Huber 光滑化梯度法的算法实现参考 , % 连续化策略参考 <..\LASSO_con\LASSO_con.html LASSO 问题连续化策略>。 % % 此页面的源代码请见: <../download_code/lasso_grad/demo.m demo.m>。 %% 版权声明 % 此页面为《最优化:建模、算法与理论》、《最优化计算方法》配套代码。 % 代码作者:文再文、刘浩洋、户将,代码整理与页面制作:杨昊桐。 % % 著作权所有 (C) 2020 文再文、刘浩洋、户将