邏輯迴歸原理

 雖然叫做“迴歸”,但是這個算法是用來解決分類問題的。迴歸與分類的區別在於:迴歸所預測的目標量的取值是連續的(例如房屋的價格);而分類所預測的目標變量的取值是離散的(例如判斷郵件是否爲垃圾郵件)。當然,爲了便於理解,我們從二值分類(binary classification)開始,在這類分類問題中,y只能取0或1。更好的理解問題,先舉個小例子:假如我們要製作一個垃圾郵件過濾系統,如果一封郵件是垃圾系統,y=1,否則y=0 。給定訓練樣本集,當然它們的特徵和標籤都已知,我們就是要訓練一個分類器,將它們分開。

線性迴歸的假設(hypotheses)函數爲:


爲了簡便,記,那麼


邏輯迴歸本質上是線性迴歸,只是在特徵到結果的映射中加入了一層邏輯函數g(z),即先把特徵線性求和,然後使用函數g(z)作爲假設函數來預測。g(z)可以將連續值映射到0 和1。

g(z)爲sigmoid function.



sigmoid function 的導數如下:


邏輯迴歸用來分類0/1 問題,也就是預測結果屬於0 或者1 的二值分類問題。這裏假設了二值滿足伯努利分佈,也就是


其也可以寫成如下的形式:


對於訓練數據集,特徵數據x={x1, x2, … , xm}和對應的分類標籤y={y1, y2, … , ym},假設m個樣本是相互獨立的,那麼,極大似然函數爲:


log似然爲:


如何使其最大呢?與線性迴歸類似,我們使用梯度上升的方法(求最小使用梯度下降),那麼


如果只用一個訓練樣例(x,y),採用隨機梯度上升規則,那麼隨機梯度上升更新規則爲:


2 梯度下降算法

梯度下降算法的僞代碼如下:

################################################

初始化迴歸係數爲1

重複下面步驟直到收斂{

        計算整個數據集的梯度

        使用alpha x gradient來更新迴歸係數

}

返回迴歸係數值

################################################

      注:因爲本文中是求解的Logit迴歸的代價函數是似然函數,需要最大化似然函數。所以我們要用的是梯度上升算法。但因爲其和梯度下降的原理是一樣的,只是一個是找最大值,一個是找最小值。找最大值的方向就是梯度的方向,最小值的方向就是梯度的負方向。另外,最大似然可以通過取負對數,轉化爲求最小值。

 

2.2 隨機梯度下降SGD (stochastic gradient descent)

      梯度下降算法在每次更新迴歸係數的時候都需要遍歷整個數據集(計算整個數據集的迴歸誤差),該方法對小數據集尚可。但當遇到有數十億樣本和成千上萬的特徵時,就有點力不從心了,它的計算複雜度太高。改進的方法是一次僅用一個樣本點(的迴歸誤差)來更新迴歸係數。這個方法叫隨機梯度下降算法。由於可以在新的樣本到來的時候對分類器進行增量的更新(假設我們已經在數據庫A上訓練好一個分類器h了,那新來一個樣本x。對非增量學習算法來說,我們需要把x和數據庫A混在一起,組成新的數據庫B,再重新訓練新的分類器。但對增量學習算法,我們只需要用新樣本x來更新已有分類器h的參數即可),所以它屬於在線學習算法。與在線學習相對應,一次處理整個數據集的叫“批處理”。

        隨機梯度下降算法的僞代碼如下:

###############################################

初始化迴歸係數爲1

重複下面步驟直到收斂{

        對數據集中每個樣本

               計算該樣本的梯度

                使用alpha xgradient來更新迴歸係數

 }

返回迴歸係數值

###############################################

 

2.3 改進的隨機梯度下降

  1)在每次迭代時,調整更新步長alpha的值。隨着迭代的進行,alpha越來越小,這會緩解係數的高頻波動(也就是每次迭代係數改變得太大,跳的跨度太大)。當然了,爲了避免alpha隨着迭代不斷減小到接近於0(這時候,係數幾乎沒有調整,那麼迭代也沒有意義了),我們約束alpha一定大於一個稍微大點的常數項,具體見代碼。

  2)每次迭代,改變樣本的優化順序。也就是隨機選擇樣本來更新迴歸係數。這樣做可以減少週期性的波動,因爲樣本順序的改變,使得每次迭代不再形成週期性。

 改進的隨機梯度下降算法的僞代碼如下:

################################################

初始化迴歸係數爲1

重複下面步驟直到收斂{

       對隨機遍歷的數據集中的每個樣本

              隨着迭代的逐漸進行,減小alpha的值

              計算該樣本的梯度

              使用alpha x gradient來更新迴歸係數

    }

返回迴歸係數值

2.4 批量梯度下降

其實批量的梯度下降就是一種折中的方法,他用了一些小樣本來近似全部的,其本質就是我1個指不定不太準,那我用個30個50個樣本那比隨機的要準不少了吧,而且批量的話還是非常可以反映樣本的一個分佈情況的。

#################################################

import random
# matrix_A  訓練集
matrix_A = [[1,4], [2,5], [5,1], [4,2]]
Matrix_y = [19,26,19,20]
theta = [2,4]
#學習速率
leraing_rate = 0.005
loss = 50
iters = 1
Eps = 0.0001
#隨機梯度下降
while loss>Eps and iters <1000 :
    loss = 0
    i = random.randint(0, 3)
    h = theta[0]*matrix_A[i][0] + theta[1]*matrix_A[i][1] 
    theta[0] = theta[0] + leraing_rate*(Matrix_y[i]-h)*matrix_A[i][0]
    theta[1] = theta[1] + leraing_rate*(Matrix_y[i]-h)*matrix_A[i][1]
    Error = 0
    Error = theta[0]*matrix_A[i][0] + theta[1]*matrix_A[i][1] - Matrix_y[i]
    Error = Error*Error
    loss = loss +Error
    iters = iters +1
print ('theta=',theta)
print ('iters=',iters)
"""
#梯度下降
while loss>Eps and iters <1000 :
    loss = 0
    for i in range(4):
        h = theta[0]*matrix_A[i][0] + theta[1]*matrix_A[i][1] 
        theta[0] = theta[0] + leraing_rate*(Matrix_y[i]-h)*matrix_A[i][0]
        theta[1] = theta[1] + leraing_rate*(Matrix_y[i]-h)*matrix_A[i][1]
    for i in range(4):
        Error = 0
        Error = theta[0]*matrix_A[i][0] + theta[1]*matrix_A[i][1] - Matrix_y[i]
        Error = Error*Error
        loss = loss +Error
    iters = iters +1
print ('theta=',theta)
print ('iters=',iters)
"""
"""
#批量梯度下降
while loss>Eps and iters <1000 :
    loss = 0
    sampleindex =  random.sample([0,1,2,3],2)
    for i in sampleindex :
        h = theta[0]*matrix_A[i][0] + theta[1]*matrix_A[i][1] 
        theta[0] = theta[0] + leraing_rate*(Matrix_y[i]-h)*matrix_A[i][0]
        theta[1] = theta[1] + leraing_rate*(Matrix_y[i]-h)*matrix_A[i][1]
    for i in sampleindex :
        Error = 0
        Error = theta[0]*matrix_A[i][0] + theta[1]*matrix_A[i][1] - Matrix_y[i]
        Error = Error*Error
        loss = loss +Error
    iters = iters +1
print ('theta=',theta)
print ('iters=',iters)
"""



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章