優(yōu)化算法推導&手寫Python實現(xiàn)——牛頓法和擬牛頓法1

  • 在上一篇文章《機器學習算法推導&實現(xiàn)——邏輯斯蒂回歸》中禾酱,我們分別使用了梯度下降法牛頓法來求解對數(shù)似然函數(shù)的最優(yōu)化問題微酬,從實例中我們也能發(fā)現(xiàn)牛頓法的收斂速度遠快于梯度下降法,但是在上文中颤陶,直接使用了牛頓法的結(jié)果佩伤,并沒有進行相應推導蕊温,故本文一方面是補上牛頓法的推導,另一方面是展開討論下擬牛頓法。

牛頓法推導

  • 牛頓法的推導得先從泰勒公式說起:


    0.PNG
  • 假設現(xiàn)在函數(shù)f(x)迭代了k次的值為X(k)操灿,則在X(k)上進行二階泰勒展開可近似得到以下公式:


    1.PNG
  • 我們要求得f(x)的極小值,則必要條件是f(x)在極值點處的一階導數(shù)為0盟蚣,即:


    2.PNG
  • 因為我們把每輪迭代求得的滿足目標函數(shù)極小值的x作為下一輪迭代的值刺覆,因此我們可以假設第k+1輪的值就是最優(yōu)解:


    3.PNG
  • 代入二階泰勒展開并求導可得:
    4.PNG

    令:
    5.PNG
    6.PNG

    可得最終的優(yōu)化公式為:
    7.PNG
  • 雖然根據(jù)推導,我們已經(jīng)知道了牛頓法的迭代方法姨涡,但是在實際應用過程中衩藤,我們會發(fā)現(xiàn)海塞矩陣的逆矩陣往往計算比較復雜,于是又有了擬牛頓法來簡化這一過程涛漂。

擬牛頓法的原理

  • 在擬牛頓法中赏表,我們考慮優(yōu)化出一個n階矩陣D來代替海塞矩陣的逆矩陣,首先我們得先來看看替代矩陣D要滿足什么條件:
  • 首先根據(jù)二階泰勒展開匈仗,我們令:


    8.PNG
  • 代入f(x)瓢剿,并求導,可得:


    9.PNG
  • 再令:


    5.PNG
    6.PNG
  • 最終可得矩陣D需滿足的條件:


    10.PNG
  • 另外在每次迭代中可以更新矩陣D悠轩,故可以假設以下更新條件:


    11.PNG

    由此我們可以發(fā)現(xiàn)海塞矩陣逆矩陣的近似矩陣D(x)的選擇條件比較靈活间狂,可以有多種具體的實現(xiàn)方法。

1火架、DFP算法(Davidon-Fletcher-Powell)推導

  • 在DFP算法中鉴象,我們假設:
    12.PNG

    *在這里我們知道凸函數(shù)的二階導數(shù)海塞矩陣(Hessian)是對稱矩陣,因此我們假設想要替代的D, P, Q矩陣也是對稱矩陣何鸡,即矩陣的轉(zhuǎn)置等于矩陣本身炼列。
  • 兩邊乘以\Delta{gk}可得:
    13.PNG
  • 為了滿足上式要求,我們不妨令:


    14.PNG
  • 我們先來求P矩陣音比,最簡單的就是令:
    16.PNG
  • 接著兩邊乘以\Delta{gk}可得:
    18.PNG

    求得\alpha俭尖,并代入P矩陣,可求得:
    19.PNG
  • 同樣的方法我們求解下Q矩陣
    20.PNG
  • 最終,DFP算法的迭代公式為:
    21.PNG

python實現(xiàn)DFP算法

  • 我們繼承上一篇文章邏輯回歸算法的類稽犁,并且增加擬牛頓法的優(yōu)化算法焰望。
  • 我們先看下算法的主函數(shù)部分买决,在繼承邏輯回歸類的基礎上主要有2點改動:一是把"method"參數(shù)提前齐苛,在實例化的時候就要求定位好優(yōu)化算法;二是重寫了train方法承二,衍生出其他擬牛頓算法虑椎。
from ML_LogisticRegression import LogisticRegressionSelf as logit
import numpy as np
?
class allLogitMethod(logit):
    def __init__(self, method):
        """init class"""
        super().__init__()
        self.method = method
        self.graList = []               #記錄梯度模長的列表
?
    #重寫下train方法
    def train(self, X, y, n_iters=1000, learning_rate=0.01):
        """fit model"""
        if X.ndim < 2:
            raise ValueError("X must be 2D array-like!")
        self.trainSet = X
        self.label = y
        if self.method.lower() == "gradient":
            self._LogisticRegressionSelf__train_gradient(n_iters, learning_rate)
        elif self.method.lower() == "newton":
            self._LogisticRegressionSelf__train_newton(n_iters)
        elif self.method.lower() == "dfp":
            self.__train_dfp(n_iters, learning_rate)
        else:
            raise ValueError("method value not found!")
        return  
  • 在寫算法主體前震鹉,我們先看下DFP的簡易優(yōu)化過程
  1. 初始化參數(shù)W0,初始化替代矩陣Dk0捆姜,計算初始梯度Gk0传趾,迭代次數(shù)k;
  2. While ( k < n_iters ) and ( ||Gk0|| > e ):
    1. 計算出W0需要優(yōu)化的方向Pk = Dk*Gk0
    2. 更新參數(shù)W1如下:
      for n in N:
      • 嘗試用一維搜索方法改變Pk的學習率,
      • 求得最小似然值泥技,
      • 求出W1和deltaW(W1 - W0)
    3. 更新梯度Gk1浆兰,并求deltaG(Gk1 - Gk0)
    4. 更新DK1,利用上述推導的DFP的迭代公式
    5. 重新賦值W0珊豹,Dk0簸呈,Gk0
    6. k += 1
  3. end.
  • 我們可以大致看到DFP算法的主體部分有外循環(huán)內(nèi)循環(huán)兩個部分組成,所以我們也是將內(nèi)外循環(huán)分開來寫店茶。
  • 我們先看內(nèi)循環(huán)部分蜕便。內(nèi)循環(huán)是已經(jīng)知道了參數(shù)W的優(yōu)化方向的基礎上,想要找到最合適的學習率贩幻,使得更新后的W求得的似然值最小玩裙。實際有很多方法,在這里為了簡單段直,筆者只是對學習率進行了i次方的操作。具體函數(shù)如下:
    #一維搜索法求出最優(yōu)lambdak溶诞,更新W后鸯檬,使得似然值最小
    def __updateW(self, X, Y, lambdak, W0, Pk):
        """此處對lambdak的處理僅簡單用1~i次方來逐步變小,以選取到最小似然值的lambdak"""
        min_LLvalue = np.inf
        W1 = np.zeros(W0.shape)
        for i in range(10):
            Wi = W0 - (lambdak**i)*Pk
            Ypreprob, LLvalue = self.PVandLLV(X, Y, Wi)
            if LLvalue < min_LLvalue:
                min_LLvalue = LLvalue
                W1 = np.copy(Wi)
                deltaW = - (lambdak**i)*Pk
                bestYpreprob = Ypreprob
        return W1, deltaW, min_LLvalue, bestYpreprob
  • 再看外循環(huán)部分螺垢。
    #新增擬牛頓法-DFP優(yōu)化算法
    def __train_dfp(self, n_iters, learning_rate):
        """Quasi-Newton Method DFP(Davidon-Fletcher-Powell)"""
        n_samples, n_features = self.trainSet.shape
        X = self.trainSet
        y = self.label
        #合并w和b喧务,在X尾部添加一列全是1的特征
        X2 = np.hstack((X, np.ones((n_samples, 1))))
        #將y轉(zhuǎn)置變?yōu)?n_samples,1)的矩陣
        Y = np.expand_dims(y, axis=1)
        #初始化特征系數(shù)W,初始化替代對稱矩陣
        W = np.zeros((1, n_features+1))
        Dk0 = np.eye(n_features+1)
        #計算初始的預測值枉圃、似然值功茴,并記錄似然值
        Ypreprob, LL0 = self.PVandLLV(X2, Y, W)
        self.llList.append(LL0)
        #根據(jù)初始的預測值計算初始梯度,并記錄梯度的模長
        Gk0 = self._LogisticRegressionSelf__calGradient(X2, Y, Ypreprob)
        graLength = np.linalg.norm(Gk0)
        self.graList.append(graLength)
        #初始化迭代次數(shù)
        k = 0
        while (k<n_iters) and (graLength>self.tol):
            #計算優(yōu)化方向的值Pk=Gk0.Dk0
            Pk = np.dot(Gk0, Dk0)
            #一維搜索更新參數(shù)孽亲,并保存求得的最小似然值
            W, deltaW, min_LLvalue, Ypreprob = self.__updateW(X2, Y, learning_rate, W, Pk)
            self.llList.append(min_LLvalue)
            #更新梯度Gk和deltaG坎穿,同時求得梯度的模長和更新前后的模長差值
            Gk1 = self._LogisticRegressionSelf__calGradient(X2, Y, Ypreprob)
            graLength = np.linalg.norm(Gk1)
            self.graList.append(graLength)
            deltaG = Gk1 - Gk0
            Gk0 = Gk1
            #更新替代矩陣Dk
            Dk1 = Dk0 + np.dot(deltaW.T, deltaW)/np.dot(deltaW, deltaG.T) - \
            np.dot(np.dot(np.dot(Dk0, deltaG.T), deltaG), Dk0)/np.dot(np.dot(deltaG, Dk0), deltaG.T)
            Dk0 = Dk1
            k += 1
        self.n_iters = k
        self.w = W.flatten()[:-1]
        self.b = W.flatten()[-1]
        Ypre = np.argmax(np.column_stack((1-Ypreprob,Ypreprob)), axis=1)
        self.accurancy = sum(Ypre==y)/n_samples
        print("第{}次停止迭代,梯度模長為{},似然值為{}玲昧,準確率為{}".format(self.n_iters, self.graList[-1], self.llList[-1], self.accurancy))
        print("w:{};\nb:{}".format(self.w, self.b))
        return
  • 在這里還有一點小小的提示:筆者在實測過程中栖茉,發(fā)現(xiàn)DFP算法經(jīng)常會導致求解似然值和P(y=1|X)的時候報值溢出的錯誤。主要是python的numpy.exp(wx)中的wx過大導致的孵延,比如看下圖的報錯:
    22.PNG
  • 所以在這里我們對求解似然值和P(y=1|X)的公式進行了一些調(diào)整吕漂。當wx為負數(shù)時,使用原公式尘应;當wx為正數(shù)時惶凝,使用轉(zhuǎn)換公式替換。其實質(zhì)是一致的犬钢。
    23.PNG
  • 最后我們用擬牛頓法-DFP算法牛頓法實測比較下苍鲜。
    1. 牛頓法:迭代了7次,迭代時長0.18s娜饵,似然值176.81坡贺,準確率0.94,模型參數(shù)如下圖所示:
if __name__ == "__main__":
    import matplotlib.pyplot as plt
    from sklearn.datasets import make_classification
    import time
    X, y = make_classification(n_samples=1000, n_features=4)
    #1箱舞、自編的牛頓法進行擬合
    time_nt = time.time()
    logit_nt = allLogitMethod("newton")
    logit_nt.train(X, y, n_iters=100)
    print("迭代時長:", time.time()-time_nt)
    plt.plot(range(logit_nt.n_iters+1), logit_nt.llList)
    plt.show()

24.PNG

2. 擬牛頓法-DFP算法:迭代了18次遍坟,迭代時長0.038s,似然值176.81晴股,準確率0.94愿伴,模型參數(shù)如下圖所示:

    #3、自編的擬牛頓法-DFP算法進行擬合
    time_dfp = time.time()
    logit_dfp = allLogitMethod("DFP")
    logit_dfp.train(X, y, n_iters=20, learning_rate=0.5)
    print("迭代時長:", time.time()-time_dfp)
    fig = plt.figure(figsize=(10,6)) 
    ax1 = fig.add_subplot(1,2,1)
    ax1.plot(range(logit_dfp.n_iters+1), logit_dfp.llList)
    ax2 = fig.add_subplot(1,2,2)
    ax2.plot(range(logit_dfp.n_iters+1), logit_dfp.graList)
    plt.show()
25.PNG
  • 經(jīng)過兩種方法的對比电湘,我們發(fā)現(xiàn)兩者最終訓練出來的模型參數(shù)基本一致隔节,似然值也下降到同一水平DFP雖然迭代18次比牛頓法多寂呛,但是訓練總時間只有0.038s怎诫,遠小于牛頓法的訓練總時間。
  • 可見贷痪,DFP算法中的Dk矩陣完全可以逼近于牛頓法中的海塞矩陣的逆矩陣幻妓,而且DFP算法中的Dk矩陣的訓練也比二階導數(shù)矩陣的訓練來得方便與快速。

以上就是本次的全部內(nèi)容劫拢,謝謝閱讀肉津。(今天先寫到這,寫的好累舱沧,擬牛頓法的其他算法我們下次再接著推導與實現(xiàn)妹沙。)

全部代碼可前往以下地址下載:
https://github.com/shoucangjia1qu/ML_gzh/tree/master/LogisticRegression

?往期回顧:
機器學習算法推導&實現(xiàn)——邏輯斯蒂回歸
機器學習算法推導&實現(xiàn)——線性回歸

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市熟吏,隨后出現(xiàn)的幾起案子距糖,更是在濱河造成了極大的恐慌玄窝,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,651評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件肾筐,死亡現(xiàn)場離奇詭異哆料,居然都是意外死亡,警方通過查閱死者的電腦和手機吗铐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評論 3 392
  • 文/潘曉璐 我一進店門东亦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人唬渗,你說我怎么就攤上這事典阵。” “怎么了镊逝?”我有些...
    開封第一講書人閱讀 162,931評論 0 353
  • 文/不壞的土叔 我叫張陵壮啊,是天一觀的道長。 經(jīng)常有香客問我撑蒜,道長歹啼,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,218評論 1 292
  • 正文 為了忘掉前任座菠,我火速辦了婚禮狸眼,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘浴滴。我一直安慰自己拓萌,他們只是感情好,可當我...
    茶點故事閱讀 67,234評論 6 388
  • 文/花漫 我一把揭開白布升略。 她就那樣靜靜地躺著微王,像睡著了一般。 火紅的嫁衣襯著肌膚如雪品嚣。 梳的紋絲不亂的頭發(fā)上炕倘,一...
    開封第一講書人閱讀 51,198評論 1 299
  • 那天,我揣著相機與錄音翰撑,去河邊找鬼罩旋。 笑死,一個胖子當著我的面吹牛额嘿,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播劣挫,決...
    沈念sama閱讀 40,084評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼册养,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了压固?” 一聲冷哼從身側(cè)響起球拦,我...
    開封第一講書人閱讀 38,926評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后坎炼,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體愧膀,經(jīng)...
    沈念sama閱讀 45,341評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,563評論 2 333
  • 正文 我和宋清朗相戀三年谣光,在試婚紗的時候發(fā)現(xiàn)自己被綠了檩淋。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,731評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡萄金,死狀恐怖蟀悦,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情氧敢,我是刑警寧澤日戈,帶...
    沈念sama閱讀 35,430評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站孙乖,受9級特大地震影響浙炼,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜唯袄,卻給世界環(huán)境...
    茶點故事閱讀 41,036評論 3 326
  • 文/蒙蒙 一弯屈、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧越妈,春花似錦季俩、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,676評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至阎抒,卻和暖如春酪我,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背且叁。 一陣腳步聲響...
    開封第一講書人閱讀 32,829評論 1 269
  • 我被黑心中介騙來泰國打工都哭, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人逞带。 一個月前我還...
    沈念sama閱讀 47,743評論 2 368
  • 正文 我出身青樓欺矫,卻偏偏與公主長得像,于是被迫代替她去往敵國和親展氓。 傳聞我的和親對象是個殘疾皇子穆趴,可洞房花燭夜當晚...
    茶點故事閱讀 44,629評論 2 354

推薦閱讀更多精彩內(nèi)容

  • @[toc] 1. 牛頓法 1.1 求解f' = 0的點,牛頓法推導 Newton method NR法是尋找函數(shù)...
    fly_dragon閱讀 2,023評論 0 0
  • 概率論與數(shù)理統(tǒng)計 無窮小階數(shù) 無窮小量表述:線性逼近 相當于利用切線和斜率來理解誤差和逼近遇汞。 泰勒級數(shù):線性逼近 ...
    Babus閱讀 809評論 0 1
  • 機器學習就是需要找到模型的鞍點未妹,也就是最優(yōu)點簿废。因為模型很多時候并不是完全的凸函數(shù),所以如果沒有好的優(yōu)化方法可能會跑...
    冒綠光的盒子閱讀 1,059評論 0 3
  • 之前络它,我發(fā)過一篇文章族檬,通俗地解釋了梯度下降算法的數(shù)學原理和推導過程,推薦一看化戳。鏈接如下: 簡單的梯度下降算法单料,你真...
    紅色石頭Will閱讀 1,697評論 1 10
  • 你還是每天都在刷抖音嗎? 你是否還在被抖音統(tǒng)治折迂烁? 一滑一上午看尼, 一滑滑到半夜? 抖音占據(jù)了我們太多時間盟步, 很多可...
    梓梓梓寒閱讀 163評論 0 1