近端梯度法
近端梯度法(proximal gradient method)求解由光滑项和易作近端运算的凸项相加而成的问题。它对光滑项使用梯度信息,对可能不可微的项保留其原形求解小子问题;因此可以处理绝对值惩罚或凸约束,而不必把它们勉强求导。
平方误差加绝对值惩罚
以教学问题 为例。梯度是 ,其欧氏 Lipschitz 常数可取 。绝对值在零点不可微,但标量子问题 可以精确解出。若 ,导数为 ,得 ,要求 ;若 ,得到 ,要求 。其余 时,零点两侧导数夹住零,最小点为零。所以 这是软阈值:小量归零,大量向零缩减同样的绝对距离。
从局部上界推出更新
一般设 凸且可微, 为 -Lipschitz; 为闭、正常凸函数。“正常”指有效定义域非空,且不取负无穷。无穷值可用来表示禁止的点。取 ,用 近似目标。配方后,与 有关的部分等于 加常数。因此 该近端子问题因二次项强凸而有唯一解。若 为闭非空凸集的指示函数,近端运算就是欧氏投影。[1]
令 。近端最优性条件给出 ,由次梯度不等式 另一方面,将 Lipschitz 梯度沿线段积分可得 。两式相加便得到完整下降界 例如 时系数至少为 。如果迭代点不动,近端条件化为 ,再由凸性证明它全局最优。目标存在最小点及上述标准条件下,固定合适步长的算法有收敛理论;这里的下降推导与固定点证明说明了其核心机制。
与正文相同的数值更新
取 ,初点为 。先做梯度步得到 ,再按阈值 缩减,得到 。第二步梯度步为 ,阈值后得到 。目标依次从 降至 、。
从第一步起 不再变化,,所以趋向 。直接在正负两侧求导或检查次梯度,可验证唯一最优解为 ,最优值为 。图中梯度步和阈值步分开标出,二者合起来才是一次近端梯度更新。
参数变式与边界
把惩罚改为 ,,则坐标可分离地得到 、。变式取 ,两个坐标均为零;此时 位于 内,验证了零点最优性。
步长过大可失败。即使 、,取 也会得到 ,除初值为零外均发散。不存在最小点、近端子问题算得过粗或采用不同非凸分解时,也不能直接套用上述凸模型结论。若 未知,可通过检验光滑项上界来回溯步长。
标准库实现
下例输入初始两坐标、非负惩罚、步长及步数,返回更新轨迹,不改写输入。默认步长满足本例 ;每步成本为常数,保存 步为 。一般问题还应加上梯度和近端子问题的实际成本;近端映射没有便宜解时,算法未必有优势。
def proximal_gradient(start, lam=1.0, step=0.25, count=2):
if len(start) != 2 or lam < 0 or not 0 < step <= 0.25 or count < 0:
raise ValueError("invalid data or unsafe step for this quadratic")
x, y = map(float, start)
def soft(v, a):
return max(v-a, 0.0)-max(-v-a, 0.0)
def value(x,y):
return ((x-3)**2+4*(y+1)**2)/2+lam*(abs(x)+abs(y))
trace = [(x,y,value(x,y))]
for _ in range(count):
x = soft(x-step*(x-3), step*lam)
y = soft(y-step*4*(y+1), step*lam)
trace.append((x,y,value(x,y)))
return trace
for row in proximal_gradient((0,0)):
print(row)
assert proximal_gradient((0,0), lam=4, count=1)[-1][:2] == (0.0,0.0)
输出包含正文的前三个目标值。停止时可以检查梯度映射 ;它为零与本模型最优性等价,普通梯度则在非光滑最优点未必为零。
参考文献
- ↑ Parikh, N. and Boyd, S. (2014), Proximal Algorithms,§1.1、§4.2及§6.5.2。