%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % 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 . % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% 实例:罚函数法解基追踪问题 % 考虑基追踪问题: % % $$ \min\|x\|_1,\quad \mathrm{s.t.}\quad Ax=b,$$ % % 其为一个线性等式约束的非光滑优化问题,使用二次罚函数作用于等式约束则得到 LASSO 问题: % % $$\min \|x\|_1+\frac{\sigma}{2}\|Ax-b\|^2, $$ % 其中 $\sigma$ 为罚因子。 % % 令 $\mu = \frac{1}{\sigma}$,罚因子逐渐增加到无穷,则等价于 LASSO 问题中的 $\mu$ % 逐渐减小,对应于 LASSO 问题求解的连续化策略。当 $\mu$ 趋于 $0$ 时 LASSO % 问题的解收敛到 BP 问题的解。这里我们设定一个固定的 $\mu$(其越小逼近基追踪问题的质量越高)为目标,从一个较大的 $\mu$ % 逐渐减小到该值。 %% 生成 LASSO 问题 clear; %%% % 设定随机种子。 seed = 97006855; ss = RandStream('mt19937ar','Seed',seed); RandStream.setGlobalStream(ss); %%% % 构造 LASSO 优化问题 % % $$ \min_x f(x) :=\frac{1}{2}\|Ax-b\|_2^2 + \mu\|x\|_1, $$ % % 生成随机的矩阵 $A$ 和向量 $u$ 以使得 $b=Au$。 m = 512; n = 1024; A = randn(m, n); u = sprandn(n, 1, 0.1); b = A * u; x0 = zeros(n, 1); %% 罚函数法 % 罚函数法在这里对应于 LASSO 问题的连续化策略,我们从 $\mu=10$ 开始以 $\gamma = 10^{-1}$ % 的比例衰减到 $\mu=10^{-3}$,以逐渐近似求解原始的基追踪问题。对于每个 $\mu$对应的 LASSO 子问题,使用固定步长的次梯度法进行求解。 opts = struct(); opts.maxit = 600; opts.alpha0 = 0.0002; %%% % 固定步长的次梯度法求解子问题。 |f_val| 记录求解过程中 $\frac{f(x)}{\mu}$ 的值, |g_val| 记录约束违反度 $\frac{\|Ax^k-b\|}{\|b\|}$ 的值。 opts.step_type = 'fixed'; x = x0; f_val = []; g_val = []; for mu = [10, 1, 1e-1, 1e-2, 1e-3] addpath('../lasso_subgrad'); [x, out] = l1_subgrad(x, A, b, mu, opts); f_val = [f_val, out.f_hist_best(1:out.itr) / mu]; g_val = [g_val, out.g_hist(1:out.itr) / norm(b)]; end %% 次梯度法解 LASSO 问题 % 不适用连续化策略,直接对 $\mu=10^{-3}$时的 LASSO 问题利用次梯度法进行求解。将结果与罚函数法(LASSO 的连续化策略) % 的求解效果进行对比。 opts.maxit = numel(f_val); opts.ftol = 0; [x1, out] = l1_subgrad(x0, A, b, 1e-3, opts); f_val1 = out.f_hist_best / 1e-3; g_val1 = out.g_hist / norm(b); %% 结果可视化 fig1 = figure; x = 1:numel(f_val); semilogy(x, f_val, 'k-', x, f_val1, 'k--'); legend('罚函数法', '次梯度法'); ylabel('$\hat{f}^k/\mu$', 'fontsize', 14, 'interpreter', 'latex'); xlabel('迭代步'); print(fig1, '-depsc','penalty1.eps'); fig2= figure; semilogy(x, g_val, 'k-', x, g_val1, 'k--'); legend('罚函数法', '次梯度法'); ylabel('$\|Ax^k - b\|/\|b\|$', 'fontsize', 14, 'interpreter', 'latex'); xlabel('迭代步'); print(fig2, '-depsc','penalty2.eps'); %% 结果分析 % 从函数值和约束的违反度两个角度,罚函数法的效果均好于直接使用次梯度法。 % 在迭代初期,由于 $\mu$较大,这意味着约束 $Ax = b$可以不满足, % 从而算法可将优化的重点放到 $\|x\|_1$上;随着迭代进行, $\mu$ 单调减小, % 此时算法将更注重于可行性( $\|Ax -b\|_2$的大小)。直接取 $\mu = 10^{-3}$效果不佳, % 这是因为惩罚项 $\|Ax -b\|_2^2$的权重太大,次梯度法会尽量使得迭代点满足 $Ax = b$,而忽视了 $\|x\|_1$项的作用。 %% 参考页面 % 关于固定正则化系数 $\lambda$ 的 LASSO 问题次梯度法,请参考 % <../lasso_subgrad/l1_subgrad.html LASSO 问题的次梯度解法>。 % % 另外,LASSO 的连续化策略,请参考 % <../LASSO_con/LASSO_con.html LASSO 的连续化策略>。 % % 此页面的源代码请见: <../download_code/pm_bp/demo_cont.m demo_cont.m>。 %% 版权声明 % 此页面为《最优化:建模、算法与理论》、《最优化计算方法》配套代码。 % 代码作者:文再文、刘浩洋、户将,代码整理与页面制作:杨昊桐。 % % 著作权所有 (C) 2020 文再文、刘浩洋、户将