數據、特征和數值優化算法是機器學習的核心,而牛頓法及其改良(擬牛頓法)是機器最常用的一類數字優化算法,今天就從牛頓法開始,介紹幾個擬牛頓法算法。本博文只介紹算法的思想,具體的數學推導過程不做介紹。
1. 牛頓法
牛頓法的核心思想是”利用函數在當前點的一階導數,以及二階導數,尋找搜尋方向“(回想一下更簡單的梯度下降法,她只用了當前點一階導數信息決定搜索方向)。
牛頓法的迭代公式是(稍微有修改,最原始的牛頓法\(\gamma=1\):
\[{{\bf{x}}_{n + 1}} = {{\bf{x}}_n} - \gamma {[Hf({{\bf{x}}_n})]^{ - 1}}\nabla f({{\bf{x}}_n})\]
其中,\({[Hf({{\bf{x}}_n})]^{ - 1}}\nabla f({{\bf{x}}_n})\)是線搜索方向。這個方向的含義是什么呢。有兩種物理解釋:
1. 一階導數\(\nabla f({\bf{x}}){\mkern 1mu} \)當前搜尋點 與 \(\nabla f({\bf{x}}){\mkern 1mu} = 0\)連線的方向。
2. 當前點泰勒展開(舍棄二階以上項)函數中 當前搜尋點 與 泰勒展開函數極小值連線方向。
2. 擬牛頓算法
上述的牛頓法需要計算Hessian矩陣的逆矩陣,運算復雜度太高。在動輒百億、千億量級特征的大數據時代,模型訓練耗時太久。因此,很多牛頓算法的變形出現了,這類變形統稱擬牛頓算法。擬牛頓算法的核心思想用一個近似矩陣\(B\)替代逆Hessian矩陣\({H^{ - 1}}\)。不同算法的矩陣\(B\)的計算有差異,但大多算法都是采用迭代更新的思想在tranning的沒一輪更新矩陣\(B\)。
下面介紹兩種最常用的擬牛頓算法:
- BFGS
BFGS(Broyden–Fletcher–Goldfarb–Shanno)的算法流程如下:
1. 初始化:初始點\({x_0}\)以及近似逆Hessian矩陣\(B_0^{ - 1}\)。通常,\({B_0} = I\),既為單位矩陣。
2. 計算線搜索方向:\({{\bf{p}}_k} = - B_k^{ - 1}\nabla f({{\bf{x}}_k})\)
3. 用”Backtracking line search“算法沿搜索方向找到下一個迭代點:\({{\bf{x}}_{k + 1}} = {{\bf{x}}_k} + {\alpha _k}{{\bf{p}}_k}\)
4. 根據Armijo–Goldstein 准則,判斷是否停止。
5. 計算\({{\bf{x}}_{k + 1}} = {{\bf{x}}_k} + {\alpha _k}{{\bf{p}}_k}\); 以及 \({{\bf{y}}_k} = \nabla f({{\bf{x}}_{k + 1}}) - \nabla f({{\bf{x}}_k})\)
6. 迭代近似逆Hessian矩陣:
\[B_{k + 1}^{ - 1} = \left( {I - \frac{{{s_k}y_k^T}}{{y_k^T{s_k}}}} \right)B_k^{ - 1}\left( {I - \frac{{{y_k}s_k^T}}{{y_k^T{s_k}}}} \right) + \frac{{{s_k}s_k^T}}{{y_k^T{\mkern 1mu} {s_k}}}\]
上式5中的推到方法比較復雜,有興趣的可以搜一下相關文獻。
- L-BFGS
BFGS算法需要存儲近似逆Hessian矩陣\(B_0^{ - 1}\)。對於很多應用來說(比如百度的CTR預估),千億量級的feature數需要\({10^{16}}\)p存儲。顯然,目前的計算機技術還很難滿足這樣的空間需求。因此,內存受限的BFGS算法(Limited-memory BFGS)就誕生了。
L-BFGS算法不存儲近似逆Hessian矩陣\(B_0^{ - 1}\), 而是直接通過迭代算法獲取本輪的搜索方向\({{\bf{p}}_k} = - B_k^{ - 1}\nabla f({{\bf{x}}_k})\)。
雖然L-BFGS算法不需要保存\(B_0^{ - 1}\)矩陣,但要保存每次迭代的中間信息,不過都是一維數組,而迭代次數有不會很多(100次以內),所以存儲要求大大降低。
L-BFGS算法的流程如下:
定義:
\[{s_k} = {x_{k + 1}} - {x_k}{\mkern 1mu} \]
\[{y_k} = {g_{k + 1}} - {g_k}{\mkern 1mu} \]
以上兩個一維數組需要保存每次迭代的結果。
再定義:
\[{\rho _k} = \frac{1}{{y_k^{\rm{T}}{s_k}}}\]
\[{g_k} \equiv \nabla f({x_k})\]
L-BFGS算法如下:
1. 初始化:初始點\({x_0}\)以及近似逆Hessian矩陣\(B_0^{ - 1}\)。通常,\({B_0} = I\),既為單位矩陣。
2. 用”Backtracking line search“算法沿搜索方向找到下一個迭代點:\({{\bf{x}}_{k + 1}} = {{\bf{x}}_k} + {\alpha _k}{{\bf{p}}_k}\)。
3. 根據Armijo–Goldstein 准則,判斷是否停止。
4. 更新搜索方向 \({{\bf{p}}_k}\); 用下面的”two loop recursion"算法。
two loop recursion算法:
\[\begin{array}{l}
q = {g_k}{\mkern 1mu} \\
For(i = k - 1,k - 2, \ldots ,k - m):\\
{\alpha _i} = {\rho _i}s_i^{\rm{T}}q{\mkern 1mu} \\
q = q - {\alpha _i}{y_i}{\mkern 1mu} \\
{H_k} = y_{k - 1}^{\rm{T}}{s_{k - 1}}/y_{k - 1}^{\rm{T}}{y_{k - 1}}\\
z = {H_k}q\\
done\\
For{\rm{(}}i = k - m,k - m + 1, \ldots ,k - 1):\\
{\beta _i} = {\rho _i}y_i^{\rm{T}}z{\mkern 1mu} \\
z = z + {s_i}({\alpha _i} - {\beta _i}){\mkern 1mu} \\
done\\
{{\bf{p}}_k} = B_k^{ - 1}{g_k} = z
\end{array}\]
-
OWL-QN
OWL-QN算法的全稱是Orthant-Wise Limited-memory Quasi-Newton。從全稱可以看出,該算法是單象限的L-BFGS算法,也就是說,OWL-QN算法每次迭代都不會超出當前象限。
為什么要加象限限制呢?L-BFGS算法需要計算函數的導數,這就要求優化函數需要處處可導。對於\(l2 - norm\)正則項,這個要求是滿足的,但對\(l1 - norm\)正則項,這函數並非處處可導:
\[f\left( x \right) = \ell \left( x \right) + c\sum\limits_i {\left| {{x_i}} \right|} - - - (1)\]
\(l1 - norm\)正則項具有特征選擇的效果,是很多大規模機器學習算法的選擇。為了牛頓法思想可以應用於\(l1 - norm\)正則項的機器學習算法,學者提出了OWL-QN算法。
觀察式(1),正則項在任意一個象限里都是線性的,一階導數為常數,二階導數為0。OWL-QN算法的核心思想就是將參數每次迭代更新都限制在一個象限內,即每次迭代都不改變參數的正負性。
但是,優化過程中,很多參數的正負肯定是需要改變的。OWL-QN算法通過在下次迭代中選擇合適的象限來改變參數的正負。比如,一個參數在當前點是正相權重,在線搜索時,按照標准的線搜索算法,該參數會變成負。OWL-QN算法限制了符號變換,對於需要變換符號的參數,將其置為0。待下一次迭代時,再根據情況決定該維度的搜索方向。
與L-BFGS算法相比,OWL-QN算法做了以下幾點調整:
1. 采用偽梯度(pseudo-gradient)\(\diamondsuit {\rm{ }}f({x^k})\)替代BFGS里的梯度
2. 線搜索是,如果某一維度變量需要跨越象限(正負號改變),則該維度值置為0
其中,1中的偽梯度是這么算的,不為0的參數,其偏微分即為其正負號(線性),若某一位為0,其梯度也置為0。
總結OWL-QN算法如下[4]:
參考文獻:
1. http://en.wikipedia.org/wiki/Broyden%E2%80%93Fletcher%E2%80%93Goldfarb%E2%80%93Shanno_algorithm
2. http://en.wikipedia.org/wiki/Limited-memory_BFGS
3. http://aria42.com/blog/2014/12/understanding-lbfgs/
4. Andrew, Galen, and Jianfeng Gao. "Scalable training of L 1-regularized log-linear models." Proceedings of the 24th international conference on Machine learning. ACM, 2007.