天天看點

⚡機器學習⚡中的優化器(Optimizers)方法Adam

⚡終于!!!

⚡終于又有時間學習Deep Learning了⚡!

30天ML計劃,一起加油!!!

https://blog.csdn.net/weixin_44333889/category_11271153.html

《專欄》

在訓練NN的時候,有哪些Optimizers可以優化更快的找到global Minima?

下面我們來看下有哪些方法可以優化求解。

Background

在訓練神經網路的時候,最開始我們是用的Gradient Descent(梯度下降法,GD)來求解,但是會出現很多問題,面臨大量的資料的時候,GD會出現local Minima,而且求解速度會下降。

關于GD+Momentum,可以看這個介紹簡單易懂。

整個技術的發展路線如下:

SGD 【Cauchy,1847】

SGD with momentum 【Rumelhart,et al.,Nature’1986】

上面兩個是遠古時期的優化求解方法,其實放到現在來看,依舊還是很有效果。

如下面這些就是SGDM訓練出來的,

⚡機器學習⚡中的優化器(Optimizers)方法Adam
⚡機器學習⚡中的優化器(Optimizers)方法Adam

目前比較常用的是下面三個Optimizers:

Adagrad 【Duchi,et al. JMLR’11 2011】

RMSProp 【Hinton,et al. Lecture slides, 2013】

Adam 【kingma,et al. ICLR’15 2014】

借用一下李老師(台大,李宏毅)的PPT。

SGD,stochastic gradient descent。也就是最普通的方法,如下圖所示

⚡機器學習⚡中的優化器(Optimizers)方法Adam
⚡機器學習⚡中的優化器(Optimizers)方法Adam
⚡機器學習⚡中的優化器(Optimizers)方法Adam

Adagrad

Adagrad(自适應梯度算法)。其基本思想是,對每個參數theta自适應的調節它的學習率,自适應的方法就是對每個參數乘以不同的系數,并且這個系數是通過之前累積的梯度大小的平方和決定的,也就是說,對于之前更新很多的,相對就可以慢一點,而對那些沒怎麼更新過的,就可以給一個大一些的學習率。

Adagrad算法:

⚡機器學習⚡中的優化器(Optimizers)方法Adam

以上就為Adagrad算法的内容。

Python實作代碼:

import numpy as np

class Adagrad:
    def __init__(self, learning_rate=0.01):
        self.learning_rate = learning_rate    # 學習率設定為0.01
        self.fg = None  
        self.delta = 1e-07                   # 設定1e-07微小值避免分母為0
        
    def update(self, params, grads):     # 更新操作
        if self.fg is None:
            self.fg = {}               # 設為空清單
            for key, value in params.items():
                self.fg[key] = np.zeros_like(value)   # 構造一個矩陣

        for key in params.keys():        # 循環疊代
            self.fg[key] += grads[key] * grads[key]     
            params[key] -= self.learning_rate * grads[key] / (np.sqrt(self.fg[key]) + self.delta) 
      

RMSProp

RMSProp算法實則為對Adagrad的一個改進,也就是把Adagrad對曆史梯度加和變成了對曆史梯度求均值,再利用這個均值代替Adagrad累加的梯度和對目前梯度進行權重,并用來update更新。

用均值代替求和是為了解決Adagrad的學習率逐漸消失的問題。

⚡機器學習⚡中的優化器(Optimizers)方法Adam
⚡機器學習⚡中的優化器(Optimizers)方法Adam

圖檔源自網絡)

有位大佬的解釋更加清晰,可跳轉

此處

def RMSprop(x, y, step=0.01, iter_count=500, batch_size=4, alpha=0.9, beta=0.9):
    length, features = x.shape
    data = np.column_stack((x, np.ones((length, 1))))
    w = np.zeros((features + 1, 1))
    Sdw, v, eta = 0, 0, 10e-7
    start, end = 0, batch_size
    
    # 開始疊代
    for i in range(iter_count):
        # 計算臨時更新參數
        w_temp = w - step * v
        
        # 計算梯度
        dw = np.sum((np.dot(data[start:end], w_temp) - y[start:end]) * data[start:end], axis=0).reshape((features + 1, 1)) / length        
        
        # 計算累積梯度平方
        Sdw = beta * Sdw + (1 - beta) * np.dot(dw.T, dw)
        
        # 計算速度更新量、
        v = alpha * v + (1 - alpha) * dw
        
        # 更新參數
        w = w - (step / np.sqrt(eta + Sdw)) * v
        start = (start + batch_size) % length
        if start > length:
            start -= length
        end = (end + batch_size) % length
        if end > length:
            end -= length
    return w
      

Adam

最後講講Adam(自适應矩估計 Adaptive moment estimation),因為目前是比較強的,下面這些都是由Adam訓練出來的,

⚡機器學習⚡中的優化器(Optimizers)方法Adam

看一下Adam和SGDM的準确率對比(源自論文)

⚡機器學習⚡中的優化器(Optimizers)方法Adam

由于Adam的提出的地方有一些突兀,并非在論文或會議,能找到的最原始的出處也隻有下面了,看一下他的更新方式吧,相當于一個優化參數的更新子產品。

⚡機器學習⚡中的優化器(Optimizers)方法Adam
⚡機器學習⚡中的優化器(Optimizers)方法Adam

Adam 的Python代碼有大佬已經開源了:

https://github.com/yzy1996/Python-Code/blob/master/Algorithm/Optimization-Algorithm/Adam.py https://github.com/sagarvegad/Adam-optimizer/blob/master/Adam.py

如果不想轉連結,這裡直接附上了:

import math

alpha = 0.01
beta_1 = 0.9
beta_2 = 0.999                      # 初始化參數的值
epsilon = 1e-8
def func(x):
    return x*x -4*x + 4
def grad_func(x):                   # 計算梯度
    return 2*x - 4
theta_0 = 0                     # 初始化向量
m_t = 0 
v_t = 0 
t = 0

while (1):                  # 循環直到它收斂
    t+=1
    g_t = grad_func(theta_0)        # 計算随機函數的梯度
    m_t = beta_1*m_t + (1-beta_1)*g_t   # 更新梯度的移動平均線
    v_t = beta_2*v_t + (1-beta_2)*(g_t*g_t) # 更新平方梯度的移動平均線
    m_cap = m_t/(1-(beta_1**t))     # 計算偏差校正後的估計
    v_cap = v_t/(1-(beta_2**t))     # 計算偏差校正後的估計
    theta_0_prev = theta_0                              
    theta_0 = theta_0 - (alpha*m_cap)/(math.sqrt(v_cap)+epsilon)    # 更新參數
    if(theta_0 == theta_0_prev):        # 檢查是否收斂
        break      

總而言之,這個優化器目前是處于機器學習中最強的優化地位。

其實,對于不同的資料集或許會有所偏差,在不同的優化時間段,前中後期,各個優化器的準确率會有所波動,如下(源自論文)準确率測試圖:

⚡機器學習⚡中的優化器(Optimizers)方法Adam

是以,不經感歎道,搞優化求解,真的是一門玄學啊,老的方法不一定在現在沒有用,新的方法不一定适用于是以場景,找到最适合的方法才是真的有效的。相信在科技如此發達的現在及以後,會有更多的優化求解算法,推進人類進步,而不僅僅是從硬體上提升運算速度。