机器学习一 牛顿法与拟牛顿法

牛顿法与拟牛顿法

优化问题是机器学习中非常重要的部分,无论应用何种算法,构建何种模型,最终我们的目的都是找到最优解的. 那优化算法是无法回避的. 当今机器学习,特别是深度学习中, 梯度下降算法(gradient descent algorithm) 可谓炙手可热. 不过优化算法不只其一种,其他算法也很常用,也很优秀,比如今天介绍的牛顿法(Newton methods)与拟牛顿法(Quasi Newton methods).

关于此算法的文献很多, 这里算是一个分享,也算是对自己知识的复习. 本文主要参考 peghoty 的博文.

考虑如下的约束问题:

[a^* = arg max_{a} f( a) ]

其中 (f(a): mathbb R^N ightarrow mathbb R) 为优化函数, 而 a 是待优化参数向量 $ a = (a_1,a_2,dots,a_N)^T in mathbb{R}^N$

(Ps: 这里回避了 用 x 表示待优参数, 因为x 在机器学习中一般指的是数据,而 实际问题中, 待优化的几乎都是模型参数而非数据). 这里要求 f 是凸的, 且是二阶连续可微的(否则后面用到的二阶偏导无法满足).

牛顿法

牛顿法的基本思想是 用泰勒展开式来替代原有函数: 在现有极小值点附近对 (f(x)) 二阶展开(忽略高阶项,因此是一种近似). 这样的做的好处是可以很容易找到优化条件,并且可以用到二阶偏导条件:

[psi(a) = f(a^*) + abla_{a^*} f cdot(a - a^*) + frac{1}{2}(a - a^*)^Tcdot abla^2_{a^*} fcdot (a - a^*) ]

其中(psi(a)) 是原始待优化函数; (a^*) 是当前极小值点(估计值). 由极值条件:

[ abla_apsi = 0 ]

即:

[ abla_{a^*}f + (a - a^*)^Tcdot abla_{a^*}^2 f = 0 \ Longrightarrow a^T= {a^*}^T - ( ( abla_{a^*}^2f )^{-1})^T cdot abla_{a^*} f^T ]

可见这里要求 二阶偏导矩阵(hessian 矩阵可逆(非奇异), 幸好在实际中这个经常满足).

为简化, 梯度向量(gradient vector) 与海森矩阵(hessian matrix) 分别用 (g_k = abla_{a^*} f^T , H_k = ( ( abla_{a^*}^2f )^{-1})^T) 表示.则上式可写成:

[a = a^* - H_k cdot g_k ]

写成迭代形式:

[a_{k + 1} = a_k - H_k^{-1} cdot g_k ]

这里的 (a_k) 表示第 k 步极值. 一般 称上式的搜索方向(d_k = - g_k cdot H_k^{-1}) 为牛顿方向.

# pseudo code
a=0,
e= 1e-4 # just a example,人为给定.
for k in loops:
    calculate g_k, H_k,
    if  g_k <= e:
        break
        d_k =  - H_k^(-1).g_k 
        a_k += d_k

可见,牛顿法没有 步长因子(或 学习率,learning rate), 因此可能出现,越过极值点的情况,甚至可能使结果发散,从而得到非最优结果. 针对此问题, 可通过所谓的线性搜索(line search) 给出步长因子( 设为 (lambda_k)):

[lambda_k = arg max_{lambda in mathbb{R}} f(a_k + lambda d_k) ]

于是修上述代码:

# pseudo code
a=0,
e= 1e-4 # just a example,人为给定.
for k in loops:
    calculate g_k, H_k,
    if  g_k <= e:
        break
        d_k =  - H_k^(-1) . g_k 
        lambda_ = arg_max(f(a_k,lambda d_k))
        a_k += lambda_ . d_k 

Ps: 牛顿法中的 (d_k) 的求解, 一般不会通过求解Hessian矩阵的逆,而是通过方程组:

[H_k cdot d_k = g_k ]

求解.

拟牛顿法

牛顿法优点是收敛速度快.但计算量大( 二阶偏导),且限制较多(Hessian 矩阵需正定).

为解决此问题即出现了拟牛顿法,其基本思想: 不用二阶偏导,而是应用构造法,人为地构造出 近似Hessian 矩阵(或其逆阵)的正定对称阵. 依据不同的构造方法产生不同的拟牛顿法.

拟牛顿条件

构造近似Hessian矩阵(或其逆)的理论依据称为拟牛顿条件.

设B,D 分别表示对Hessian矩阵及其逆阵的近似:(B approx H, D approx H^{-1}).

考虑第 k+1 步:

[f(a) approx f(a_{k+1}) + abla_{a_{k+1}} fcdot(a - a_{k+1} )+ frac{1}{2} (a - a_{k+1})^Tcdot abla^2 f_{a+1}cdot (a- a_{k+1}) ]

两边同时对 a 求偏导:

[ abla_a f approx abla_{a_{k+1}} f+ (a - a_{k+1})^Tcdot abla^2 f_{a+1} ]

(a = a_k) 并整理:

[g_{k+1} - g_k approx H_{k+1} cdot(a_{k+1} - a_k) ]

再令 (y_k = g_{k+1} - g_{k}, s_k = a_{k+1} - a_k):

[y_k approx H_{k+1} cdot s_k\ s_k approx H^{-1}_{k+1} cdot y_k ]

上式即为拟牛顿条件.也即构造出的B,D 应满足如下条件:

[y_k = B_{k+1} cdot s_k\ s_k = D_{k+1} cdot y_k ]

BFGS算法

有了拟牛顿条件就可以构造近似矩阵了. 首先需明确,近似矩阵的构造采用迭代的式. 对Hessian 矩阵的逆阵做近似的算法叫做 DFP 算法,对Hessian矩阵直接构造的叫做BFGS算法, 都是分别以其开发者们的名字首字母命名的. 其中BFGS 的效果会更好,并且其也有较完善的局部收敛理论支持,因此本节介绍BFGS.

BFGS 要做的是 求得近似矩阵 (B_k) 使得: (B_k approx H_k). 设其迭代式:

[B_{k+1} = B_k +Delta B_k,qquad k= 1,2,cdots ]

其中 (D_0) 设为单位阵 (I). 这里的关键是(Delta B_k)的构造, 因为Hessian 矩阵是对称阵,很自然地,想到构造出的(Delta B_k) 也应该是对称阵, 由拟牛顿条件,其中有两个参数((s_k,y_k)), 推想(Delta B_k) 应与其二者有关, 也即需两种参数而得(Delta B_k), 因此不防构造成两个对称阵扔组合:

[Delta B_k = alpha uu^T + eta vv^T ]

其中(alpha,eta) 为系数, 而u,v 为N维向量.代入(13)式:

[egin{array}\ y_k &=& (B_k+Delta B_k)cdot s_k\ &=& (B_k + alpha uu^T + eta vv^T)cdot s_k\ &=& B_k cdot s_k + u(alpha u^T cdot s_k)+ v(eta v^Tcdot s_k)\ &=& B_k cdot s_k + (alpha u^T cdot s_k) u+ (eta v^Tcdot s_k) v\ end{array} ]

上式中$(alpha u^T cdot s_k) ,quad (eta v^Tcdot s_k) $ 均为实数,不妨令其分别为 1, -1则:

[alpha = frac{1}{u^T s_k},qquad eta = -frac{1}{v^T s_k} ]

(16)式也变成:

[y_k - B_k s_k = u - v ]

可令:

[u = y_k,qquad v = B_k s_k ]

于是:

[alpha = frac{1}{y_k^T s_k},qquad eta = -frac{1}{s^T_k B_k s_k} ]

最终:

[Delta B_k = frac{y_k y_k^T}{y_k^T s_k} - frac{B_k s_k s_k^T B_k}{s_k^T B_k s_k} ]

#pseudo code
a = 0 # 初始化
e = 1e-4 #阈值, 人为给定
B = I # 初始化
k = 0
for k in loops:
    calculate g_k
    if g_k < e:
        break
    d_k = - B_k^(-1) g_k
    lambda_ = arg_max(f(a_k,lambda d_k))
    s_k = lambda_ d_k
    a_k += s_k
    y_k = g_k -g_(k-1)
    g_(k-1) = g_k
    B_k += (y_k * y_k.T)/(y_k.T * s_k) - 
    		(B_k s_k s_k.T B_k)/(s_k.T * B_k *s_k)

上述伪码中,(B_k^{-1}) 的求解,通过对最后的迭代式应用 Sherman-Morrison公式,直接给出:

[egin{array}\ B_{k+1}^{-1} & =& (I - frac{s_k y_k^T}{y_k^T s_k} )B_k^{-1}(I - frac{y_k s_k^T}{y_k^T s_k} )+frac{s_k s_k^T}{y_k^T s_k}\ & =& B_k^{-1} (frac{1}{s_k^T y_k}+frac{y_k^TB_k^{-1}y_k}{(s_k^T y_k)^2} )s_ks_k^T - frac{1}{s_k^T y_k}(B_k^{-1}y_ks_k^T + s_ky_k^TB_k^{-1})\ end{array} ]

上式中最的等式的部分中的括号是两个数.

Ps: Sherman-Morrison 公式, 设(Ain mathbb{R}^N)为非奇异方阵, u,v 也为N 阶方阵, 若(1 + v^TA^{-1}u e 0),则:

[(A + uv^T)^{-1} = A^{-1} - frac{A^{-1}uv^T A^{-1}}{1 + v^TA^{-1}u} ]

(B_k^{-1}) 换用(D_k)表示,则:

#pseudo code
a = 0 # 初始化
e = 1e-4 #阈值, 人为给定
B = I # 初始化
k = 0
for k in loops:
    calculate g_k
    if g_k < e:
        break
    d_k = - D_k * g_k
    lambda_ = arg_max(f(a_k,lambda d_k))
    s_k = lambda_ d_k
    a_k += s_k
    y_k = g_k -g_(k-1)
    g_(k-1) = g_k
    D_k = (I - (s_k*y_k.T)/(y_k.T* s_k))*D_k *
    	(I - (y_k - s_k.T)/y_k.T * s_k) + (s_k*s_k.T)/(y_k.T* s_k)

L-BFGS算法

当待估参数很多,或待估向量维数很高,需很大存储空间. 为减少内丰开销, L-BFGS(Limited memory BFGS) 应运而生. 其是BFGS的近似,其基本思想: 不再存储完整的矩阵D_k, 而是存储计算过程中的向量序列({s_k},quad {y_k}); 而且只存储最新的 m 个(人为给定). 每次计算D_k时,只利用最新的 m 个({s_k},quad {y_k}), 经此处理,原来的O(N2)变成了O(mN).

由上一个伪码中最后一步:

[D_{k+1} = (I - frac{s_k y_k^T}{y_k^Ts_k})D_k(I - frac{y_ks_k^T}{y_k^Ts_k}) + frac{s_ks_k^T}{y_k^Ts_k} ]

( ho_k = frac{1}{y_k^Ts_k}quad V_k = I - ho_k y_k s_k^T) 则:

[D_{k+1} = V_k^TD_kV_k + ho_ks_ks_k^T ]

上面给出逻辑,下面给出计算方式:

# pseudo code to get D_k * g_k
if k <= m:
    delta = 0
    L = k
else:
    delta = k - m 
    L = m
 q_L = g_k
a_list = []
for i in range(L-1,-1,-1): # loop: L-1 to 0
    j = i + delta
    alpha = rho_j* s_j.T* q
    a_list.append(alpha)
    q -= alpha* y_i
a_list = a_list[::-1]
r = D_0 * q
for i in range(L):
    j = i+ delta
    beta = rho_j*y_j.T * r
    r +=r +(alpha_i - beta)* s_j # alpha_i = a_list[i]

参考文献

牛顿法与拟牛顿法学习笔记一 至 五, peghoty, 2014.

Ps: 本文主要参考上述文献,因主要目的是对此法做一些记录,且peghoty写的博文很清晰,故没有广泛查找文献, 虽有失严谨,但已足够.

原文地址:https://www.cnblogs.com/vpegasus/p/newton.html