監督學習——隨機梯度下降算法(sgd)和批梯度下降算法(bgd)


線性回歸

       首先要明白什么是回歸。回歸的目的是通過幾個已知數據來預測另一個數值型數據的目標值。

      假設特征和結果滿足線性關系,即滿足一個計算公式h(x),這個公式的自變量就是已知的數據x,函數值h(x)就是要預測的目標值。這一計算公式稱為回歸方程,得到這個方程的過程就稱為回歸。

       假設房子的房屋面積和卧室數量為自變量x,用x1表示房屋面積,x2表示卧室數量;房屋的交易價格為因變量y,我們用h(x)來表示y。假設房屋面積、卧室數量與房屋的交易價格是線性關系。

image

他們滿足公式

image

上述公式中的θ為參數,也稱為權重,可以理解為x1和x2對h(x)的影響度。對這個公式稍作變化就是

image

公式中θ和x都可以看成是向量,n是特征數量。

假如我們依據這個公式來預測h(x),公式中的x是我們已知的(樣本中的特征值),然而θ的取值卻不知道,只要我們把θ的取值求解出來,我們就可以依據這個公式來做預測了。

最小均方法(Least Mean squares)

       在介紹LMS之前先了解一下什么損失函數的概念。

       我們要做的是依據我們的訓練集,選取最優的θ,在我們的訓練集中讓h(x)盡可能接近真實的值。h(x)和真實的值之間的差距,我們定義了一個函數來描述這個差距,這個函數稱為損失函數,表達式如下:

image

       這里的這個損失函數就是著名的最小二乘損失函數,這里還涉及一個概念叫最小二乘法,這里不再展開了。我們要選擇最優的θ,使得h(x)最近進真實值。這個問題就轉化為求解最優的θ,使損失函數J(θ)取最小值。(損失函數還有其它很多種類型)

那么如何解決這個轉化后的問題呢?這又牽扯到一個概念:LMS 和 梯度下降(Radient Descent)。

      LMS是求取h(x)回歸函數的理論依據,通過最小化均方誤差求最佳參數的方法。

梯度下降

       我們要求解使得J(θ)最小的θ值,梯度下降算法大概的思路是:我們首先隨便給θ一個初始化的值,然后改變θ值讓J(θ)的取值變小,不斷重復改變θ使J(θ)變小的過程直至J(θ)約等於最小值。

首先我們給θ一個初始值,然后向着讓J(θ)變化最大的方向更新θ的取值,如此迭代。公式如下:

image

公式中α稱為步長(learning rate),它控制θ每次向J(θ)變小的方向迭代時的變化幅度。J(θ)對θ的偏導表示J(θ)變化最大的方向。由於求的是極小值,因此梯度方向是偏導數的反方向。

  • α取值太小收斂速度太慢,太大則可能會Overshoot the minimum。
  • 越接近最小值時,下降速度越慢
  • 收斂: 當前后兩次迭代的差值小於某一值時,迭代結束

求解一下這個偏導,過程如下:

image

那么θ的迭代公式就變為:

image

上述表達式只針對樣本數量只有一個的時候適用,那么當有m個樣本值時該如何計算預測函數?批梯度下降算法和隨機梯度下降算法

批梯度下降算法(BGD)

有上一節中單個樣本的參數計算公式轉化為處理多個樣本就是如下表達:

image

這種新的表達式每一步計算都需要全部訓練集數據,所以稱之為批梯度下降(batch gradient descent)。

注意,梯度下降可能得到局部最優,但在優化問題里我們已經證明線性回歸只有一個最優點,因為損失函數J(θ)是一個二次的凸函數,不會產生局部最優的情況。(假設學習步長α不是特別大)

批梯度下降的算法執行過程如下圖:

image

大家仔細看批梯度下降的數學表達式,每次迭代的時候都要對所有數據集樣本計算求和,計算量就會很大,尤其是訓練數據集特別大的情況。那有沒有計算量較小,而且效果也不錯的方法呢?有!這就是:隨機梯度下降(Stochastic Gradient Descent, SGD)

隨機梯度下降算法(SGD)

隨機梯度下降在計算下降最快的方向時時隨機選一個數據進行計算,而不是掃描全部訓練數據集,這樣就加快了迭代速度。

隨機梯度下降並不是沿着J(θ)下降最快的方向收斂,而是震盪的方式趨向極小點。

隨機梯度下降表達式如下:

image

執行過程如下圖:

image

批梯度下降和隨機梯度下降在三維圖上對比如下:

微信圖片_20180220163831

基於梯度下降算法的python3實現如下:(注釋部分為BGD的實現)

  1 # -*- coding: cp936 -*-
  2 import numpy as np
  3 from scipy import stats
  4 import matplotlib.pyplot as plt
  5 
  6 
  7 # 構造訓練數據
  8 x = np.arange(0., 10., 0.2)
  9 m = len(x)                                      # 訓練數據點數目
 10 x0 = np.full(m, 1.0)
 11 input_data = np.vstack([x0, x]).T               # 將偏置b作為權向量的第一個分量
 12 target_data = 2 * x + 5 + np.random.randn(m)
 13 
 14 
 15 # 兩種終止條件
 16 loop_max = 10000   # 最大迭代次數(防止死循環)
 17 epsilon = 1e-3
 18 
 19 # 初始化權值
 20 np.random.seed(0)
 21 w = np.random.randn(2)
 22 #w = np.zeros(2)
 23 
 24 alpha = 0.001      # 步長(注意取值過大會導致振盪,過小收斂速度變慢)
 25 diff = 0.
 26 error = np.zeros(2)
 27 count = 0          # 循環次數
 28 finish = 0         # 終止標志
 29 # -------------------------------------------隨機梯度下降算法----------------------------------------------------------
 30 
 31 while count < loop_max:
 32     count += 1
 33 
 34     # 遍歷訓練數據集,不斷更新權值
 35     for i in range(m):
 36         diff = np.dot(w, input_data[i]) - target_data[i]  # 訓練集代入,計算誤差值
 37 
 38         # 采用隨機梯度下降算法,更新一次權值只使用一組訓練數據
 39         w = w - alpha * diff * input_data[i]
 40 
 41         # ------------------------------終止條件判斷-----------------------------------------
 42         # 若沒終止,則繼續讀取樣本進行處理,如果所有樣本都讀取完畢了,則循環重新從頭開始讀取樣本進行處理。
 43 
 44     # ----------------------------------終止條件判斷-----------------------------------------
 45     # 注意:有多種迭代終止條件,和判斷語句的位置。終止判斷可以放在權值向量更新一次后,也可以放在更新m次后。
 46     if np.linalg.norm(w - error) < epsilon:     # 終止條件:前后兩次計算出的權向量的絕對誤差充分小  
 47         finish = 1
 48         break
 49     else:
 50         error = w
 51 print ('loop count = %d' % count,  '\tw:[%f, %f]' % (w[0], w[1]))
 52 
 53 
 54 # -----------------------------------------------梯度下降法-----------------------------------------------------------
 55 
 56 '''
 57 while count < loop_max:
 58     count += 1
 59 
 60     # 標准梯度下降是在權值更新前對所有樣例匯總誤差,而隨機梯度下降的權值是通過考查某個訓練樣例來更新的
 61     # 在標准梯度下降中,權值更新的每一步對多個樣例求和,需要更多的計算
 62     sum_m = np.zeros(2)
 63     for i in range(m):
 64         dif = (np.dot(w, input_data[i]) - target_data[i]) * input_data[i]
 65         sum_m = sum_m + dif     # 當alpha取值過大時,sum_m會在迭代過程中會溢出
 66 
 67     w = w - alpha * sum_m       # 注意步長alpha的取值,過大會導致振盪
 68     #w = w - 0.005 * sum_m      # alpha取0.005時產生振盪,需要將alpha調小
 69 
 70     # 判斷是否已收斂
 71     if np.linalg.norm(w - error) < epsilon:
 72         finish = 1
 73         break
 74     else:
 75         error = w
 76 print ('loop count = %d' % count,  '\tw:[%f, %f]' % (w[0], w[1]))
 77 
 78 '''
 79 
 80 # check with scipy linear regression 
 81 slope, intercept, r_value, p_value, slope_std_error = stats.linregress(x, target_data)
 82 print ('intercept = %s slope = %s' %(intercept, slope))
 83 
 84 plt.plot(x, target_data, 'k+')
 85 plt.plot(x, w[1] * x + w[0], 'r')
 86 plt.show()
 87 

總結:

     開年第一篇,加油

參考:

http://mp.weixin.qq.com/s/7WlGN8JxfSmpJ8K_EyvgQA

http://m.elecfans.com/article/587673.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM