2024年5月6日15:15:26
下图为Majorize-Minimization,即求上界的最小值:(构造的g(x)函数为f(x)的上界函数,求g(x)函数的最小值)
CSDN链接(讲MM和CCP)
知乎链接(讲MM)
min x f ( x ) − g ( x ) \min_{x} f(x) - g(x) xminf(x)−g(x)
其中 (f(x)) 和 (g(x)) 都是凸函数。
算法思路:
CCP 通过在每次迭代中线性近似凹的部分,并将问题转化为凸问题进行优化。基本步骤如下:
示例代码1(调用函数):
以下 Python 代码展示了如何使用 CCP 求解一个 DC 问题的示例:
import numpy as np
from scipy.optimize import minimize
# 定义目标函数
def f(x):
return np.sum(x**2)
def g(x):
return np.sum(np.abs(x))
# 定义凹凸部分的差值目标函数
def objective(x, g_grad, x_k):
return f(x) - (g(x_k) + g_grad.T @ (x - x_k))
# 定义梯度计算
def grad_g(x):
return np.sign(x)
# 函数来求解 DC 问题
def solve_dc(x0, max_iter=100, tol=1e-6):
x = x0
for k in range(max_iter):
g_grad = grad_g(x)
x_prev = x
result = minimize(objective, x, args=(g_grad, x_prev), method='L-BFGS-B')
x = result.x
if np.linalg.norm(x - x_prev) < tol:
print(f'Converged after {k + 1} iterations.')
break
return x
# 初始化和求解
x0 = np.array([5.0, -3.0, 2.0, -1.0])
x_opt = solve_dc(x0)
print("Optimal solution:", x_opt)
目标函数:
线性化的凹部分目标函数:
objective
函数来计算线性化后的目标函数。梯度计算:
grad_g
函数计算凹目标函数的梯度。CCP 算法:
solve_dc
函数实现了 CCP 算法,迭代优化目标函数。示例代码2(手写函数):
# time: 2024/5/9 10:51
# author: YanJP
import numpy as np
# 定义目标函数
def objective(x):
return x[0]**2 + x[1]**2
# 目标函数梯度
def grad_objective(x):
return np.array([2 * x[0], 2 * x[1]])
# 线性化凹部分 d(x, y) 的梯度
def grad_d(x):
if x[0]**2 > x[1]**2:
return np.array([x[0], -x[1]])
else:
return np.array([-x[0], x[1]])
# 计算线性化后的凸约束部分梯度
def constraint_linearized(x, grad_d, prev_x):
return 1 - 0.5 * (x[0]**2 + x[1]**2 - grad_d.T @ (x - prev_x))
# 凹凸过程 (CCP) 求解函数
def solve_ccp(x0, max_iter=100, tol=1e-6, step_size=0.1):
x = x0
for k in range(max_iter):
d_grad = grad_d(x)
grad = grad_objective(x)
# 线性化凹部分约束
g_lin = constraint_linearized(x, d_grad, x)
# 判断线性化后的约束是否满足
if g_lin > 0:
x_new = x - step_size * (grad + d_grad)
else:
x_new = x - step_size * grad
if np.linalg.norm(x_new - x) < tol:
print(f'Converged after {k + 1} iterations.')
break
x = x_new
return x
# 初始值
x0 = np.array([2.0, 2.0])
x_opt = solve_ccp(x0)
print("Optimal solution:", x_opt)
print("Objective value:", objective(x_opt))
添加链接描述。注意和MM进行对比:SCA 要求近似函数是凸函数 而MM要求近似函数在近似点是原函数的upper bound。
51blog
csdn(讲的可以)
比较专业
原文链接:
知乎(有代码)
在凸优化中,λ-representation(也称为Lagrange 表示)是一种用于描述凸集的方法。它通过使用一组凸组合的方式来表示凸集,其中每个凸组合的权重由一组非负的 Lagrange 乘子 λ i \lambda_i λi 决定。λ-representation 是在凸优化理论中广泛应用的概念,特别是在描述凸包、凸锥和凸函数等方面。
λ-representation 的一般形式可以表示为:
C = { x ∈ R n ∣ x = ∑ i = 1 m λ i x i , x i ∈ C , λ i ≥ 0 , ∑ i = 1 m λ i = 1 } C = \{ x \in \mathbb{R}^n \ |\ x = \sum_{i=1}^{m} \lambda_i x_i, \ x_i \in C, \ \lambda_i \geq 0, \ \sum_{i=1}^{m} \lambda_i = 1 \} C={x∈Rn ∣ x=i=1∑mλixi, xi∈C, λi≥0, i=1∑mλi=1}
其中, C C C 是凸集, x i x_i xi是 C C C 中的点, λ i \lambda_i λi 是非负的 Lagrange 乘子,且满足 ∑ i = 1 m λ i = 1 \sum_{i=1}^{m} \lambda_i = 1 ∑i=1mλi=1。这表示 C C C中的任意点都可以通过一组凸组合来表示。
λ-representation 的优点之一是它提供了一种紧凑且直观的表示凸集的方式,特别是在某些情况下,当凸集的结构比较复杂或难以直接描述时,λ-representation 可以提供一种简单的方法来描述凸集。
知乎
基本概念:
特征:
公式:
给定优化问题:
min x , z f ( x ) + g ( z ) , s.t. A x + B z = c \min_{x, z} f(x) + g(z), \quad \text{s.t.}\ Ax + Bz = c x,zminf(x)+g(z),s.t. Ax+Bz=c
ADMM 将其转化为以下形式:
u
是拉格朗日乘子,z
是引入的辅助变量,用于分解问题。通过 z
和 u
,可以将问题分解为更容易处理的子问题。在 LASSO 问题中,目标函数:
min β 1 2 ∣ X β − y ∣ 2 2 + λ ∣ β ∣ 1 \min_{\beta} \frac{1}{2} |X\beta - y|_2^2 + \lambda |\beta|_1 βmin21∣Xβ−y∣22+λ∣β∣1
目标函数被拆分成以下两个部分:
子问题 1(更新 (\beta)):
β k + 1 = arg min β 1 2 ∥ X β − y ∥ 2 2 + ρ 2 ∥ β − z k + u k ∥ 2 2 \beta^{k+1} = \arg\min_{\beta} \frac{1}{2} \|X\beta - y\|_2^2 + \frac{\rho}{2} \|\beta - z^k + u^k\|_2^2 βk+1=argβmin21∥Xβ−y∥22+2ρ∥β−zk+uk∥22
子问题 2(更新 (z)):
z k + 1 = arg min z λ ∥ z ∥ 1 + ρ 2 ∥ β k + 1 − z + u k ∥ 2 2 z^{k+1} = \arg\min_{z} \lambda \|z\|_1 + \frac{\rho}{2} \|\beta^{k+1} - z + u^k\|_2^2 zk+1=argzminλ∥z∥1+2ρ∥βk+1−z+uk∥22
更新 (u)(拉格朗日乘子):
u k + 1 = u k + ( β k + 1 − z k + 1 ) u^{k+1} = u^k + (\beta^{k+1} - z^{k+1}) uk+1=uk+(βk+1−zk+1)
完整的 Python 实现:
import numpy as np
# 生成随机数据
np.random.seed(0)
m, n = 100, 20
X = np.random.randn(m, n)
beta_true = np.random.randn(n)
y = X @ beta_true + 0.1 * np.random.randn(m)
# ADMM 参数
rho = 1.0
alpha = 1.0
lambda_lasso = 0.1
max_iter = 1000
abs_tol = 1e-4
rel_tol = 1e-3
# 初始值
beta = np.zeros(n)
z = np.zeros(n)
u = np.zeros(n)
# 定义软阈值算子
def soft_threshold(x, kappa):
return np.sign(x) * np.maximum(np.abs(x) - kappa, 0)
# 预计算常数
X_T_X = X.T @ X
L = np.linalg.cholesky(X_T_X + rho * np.eye(n))
def solve_admm(X, y, lambda_lasso, rho, alpha, max_iter, abs_tol, rel_tol):
n = X.shape[1]
beta = np.zeros(n)
z = np.zeros(n)
u = np.zeros(n)
X_T_X = X.T @ X
L = np.linalg.cholesky(X_T_X + rho * np.eye(n))
L_T = L.T
for k in range(max_iter):
# 更新 beta
q = X.T @ y + rho * (z - u)
beta = np.linalg.solve(L, np.linalg.solve(L_T, q))
# 更新 z
z_old = z.copy()
beta_hat = alpha * beta + (1 - alpha) * z_old
z = soft_threshold(beta_hat + u, lambda_lasso / rho)
# 更新 u
u += beta_hat - z
# 计算误差
r_norm = np.linalg.norm(beta - z)
s_norm = np.linalg.norm(-rho * (z - z_old))
eps_pri = np.sqrt(n) * abs_tol + rel_tol * max(np.linalg.norm(beta), np.linalg.norm(z))
eps_dual = np.sqrt(n) * abs_tol + rel_tol * np.linalg.norm(rho * u)
if r_norm < eps_pri and s_norm < eps_dual:
break
if k % 100 == 0:
print(f'Iteration {k}, r_norm = {r_norm:.4f}, s_norm = {s_norm:.4f}')
return beta
# 求解 LASSO 问题
beta_est = solve_admm(X, y, lambda_lasso, rho, alpha, max_iter, abs_tol, rel_tol)
print("Estimated coefficients:", beta_est)
solve_admm
函数:
numpy.linalg.solve
求解 \beta
子问题。soft_threshold
函数实现软阈值算子,解决 (z) 子问题。soft_threshold
函数:
Cholesky 分解:
交替方向乘子法 (ADMM) 和块坐标下降法 (BCD) 都是用于求解优化问题的分解方法,但它们在处理优化问题的方式和应用场景上存在显著区别。以下是两者的主要区别和应用场景:
基本概念:
特征:
公式:
对于优化问题:
min x f ( x 1 , x 2 , … , x k ) \min_{x} f(x_1, x_2, \ldots, x_k) xminf(x1,x2,…,xk)
其中 x = ( x 1 , x 2 , … , x k ) x = (x_1, x_2, \ldots, x_k) x=(x1,x2,…,xk)被划分成 (k) 个块,BCD 的过程如下:
该Python函数block_coordinate_descent实现了一个基于块坐标下降法(Block Coordinate Descent, BCD)的算法,用于求解具有正定矩阵Hessian的无约束优化问题。具体来说,它最小化的目标函数形式为:
f ( x ) = 1 2 x T Q x + c T x f(\mathbf{x}) = \frac{1}{2}\mathbf{x}^T\mathbf{Q}\mathbf{x} + \mathbf{c}^T\mathbf{x} f(x)=21xTQx+cTx
其中, ( Q ) (\mathbf{Q}) (Q)是一个正定矩阵, c \mathbf{c} c是一个常数向量,而 x \mathbf{x} x是我们要找的向量解。以下是函数详细步骤的分解:
输入参数说明:
特点与适用场景:
优点: BCD方法特别适合处理大规模优化问题,因为它每次只更新一个坐标,减少了每轮迭代的计算复杂度,尤其是在 Q \mathbf{Q} Q 是稀疏或具有特殊结构时。
适用性: 适用于具有大量变量但可以有效独立处理各个变量的优化问题,如稀疏信号恢复、机器学习中的正则化问题等。
综上所述,此函数提供了一个高效求解特定形式优化问题的实现,利用了块坐标下降法的迭代更新策略,旨在找到使目标函数取最小值的向量 x \mathbf{x} x。
更新公式: 根据牛顿法或梯度下降法,我们可以写出 (x_i) 的更新规则,即减去梯度方向上的一步大小。这里的目标函数关于 (x_i) 的梯度是 ( − Q i i x i − c i − ∑ j ≠ i Q i j x j ) (-Q_{ii}x_i - c_i - \sum_{j\neq i} Q_{ij}x_j) (−Qiixi−ci−∑j=iQijxj)。将 ( x i ) (x_i) (xi) 从梯度中分离出来,得到上述更新规则,即 (x_i) 的新值等于旧值乘以 (-1),再除以 ( Q i i ) (Q_{ii}) (Qii),并加上 Q i r e s t ∗ x i r e s t + c i Q_i^{rest} * x_i^{rest} + c_i Qirest∗xirest+ci 的相反数
更新第 i 个坐标
x[i] = - (Q_i_rest @ x_i_rest + c_i) / Q_ii
问题性质:
解的精度:
迭代方式:
应用场景:
ADMM 和 BCD 在处理复杂的优化问题时具有不同的优缺点和适用场景。选择合适的算法可以更好地解决优化问题。