隨機梯度下降實現


隨機梯度下降:

   我們用X1,X2..Xn 去描述feature里面的分量,比如x1=房間的面積,x2=房間的朝向,等等,我們可以做出一個估計函數:

image

    θ在這兒稱為參數,在這兒的意思是調整feature中每個分量的影響力,就是到底是房屋的面積更重要還是房屋的地段更重要。為了如果我們令X0 = 1,就可以用向量的方式來表示了:

image

    我們程序也需要一個機制去評估我們θ是否比較好,所以說需要對我們做出的h函數進行評估,一般這個函數稱為損失函數(loss function)或者錯誤函數(error function),描述h函數不好的程度,在下面,我們稱這個函數為J函數

    在這兒我們可以做出下面的一個錯誤函數:

image 

    這個錯誤估計函數是去對x(i)的估計值與真實值y(i)差的平方和作為錯誤估計函數,前面乘上的1/2是為了在求導的時候,這個系數就不見了。

    如何調整θ以使得J(θ)取得最小值有很多方法,其中有最小二乘法(min square),是一種完全是數學描述的方法,在stanford機器學習開放課最后的部分會推導最小二乘法的公式的來源,這個來很多的機器學習和數學書上都可以找到,這里就不提最小二乘法,而談談梯度下降法。

    梯度下降法是按下面的流程進行的:

    1)首先對θ賦值,這個值可以是隨機的,也可以讓θ是一個全零的向量。

    2)改變θ的值,使得J(θ)按梯度下降的方向進行減少。

    為了更清楚,給出下面的圖:

image    這是一個表示參數θ與誤差函數J(θ)的關系圖,紅色的部分是表示J(θ)有着比較高的取值,我們需要的是,能夠讓J(θ)的值盡量的低。也就是深藍色的部分。θ0,θ1表示θ向量的兩個維度。

    在上面提到梯度下降法的第一步是給θ給一個初值,假設隨機給的初值是在圖上的十字點。

    然后我們將θ按照梯度下降的方向進行調整,就會使得J(θ)往更低的方向進行變化,如圖所示,算法的結束將是在θ下降到無法繼續下降為止。

image     當然,可能梯度下降的最終點並非是全局最小點,可能是一個局部最小點,可能是下面的情況:

image

   上面這張圖就是描述的一個局部最小點,這是我們重新選擇了一個初始點得到的,看來我們這個算法將會在很大的程度上被初始點的選擇影響而陷入局部最小點  

   下面我將用一個例子描述一下梯度減少的過程,對於我們的函數J(θ)求偏導J:(求導的過程如果不明白,可以溫習一下微積分)

  image

    下面是更新的過程,也就是θi會向着梯度最小的方向進行減少。θi表示更新之前的值,-后面的部分表示按梯度方向減少的量,α表示步長,也就是每次按照梯度減少的方向變化多少。

image     一個很重要的地方值得注意的是,梯度是有方向的,對於一個向量θ,每一維分量θi都可以求出一個梯度的方向,我們就可以找到一個整體的方向,在變化的時候,我們就朝着下降最多的方向進行變化就可以達到一個最小點,不管它是局部的還是全局的。

    用更簡單的數學語言進行描述步驟2)是這樣的:

  image    倒三角形表示梯度,按這種方式來表示,θi就不見了,看看用好向量和矩陣,真的會大大的簡化數學的描述啊。

 

#舉個隨機梯度下降應用在神經網絡的例子

 

 

'''
目標:

輸入1 經過神經元 輸出0

like:
x=0 ==> sigmode(w*x+b)==>0 需要機器學習w,b的優值
'''
weight=0
bias=0
import math



def sigmode(z):
    return 1/(1+math.exp(-z))

#定義損失函數
'''
是用來估量你模型的預測值f(x)與真實值Y的不一致程度,它是一個非負實值函數.
'''

def quadratic_cost(a):
    '''
    二次損傷函數:J(θ))=損傷函數=1/2(預測值-真實值)^2
    (備注:1/2沒有意思方便計算,如果損失函數越小那么預測值就越准)
    
    如何調整θ以使得J(θ)取得最小值?
    
    梯度下降法是按下面的流程進行的:
    1)首先對θ賦值,這個值可以是隨機的,也可以讓θ是一個全零的向量。
    2)改變θ的值,使得J(θ)按梯度下降的方向進行減少。
    
    設立a=sigmode(z),z=wx+b
    實際值為0呀,0就是那個理想值  [經過神經元 輸出0]
    那么:J(θ)=1/2(a-0)^2=a^2/2
    '''
    return a*a/2

def quadratic_derivative(a):
    '''
    這個地方的導數要知道:
    sigmode的倒數為
    
    f(sigmode)=sigmode*(1-sigmode)
    
    a=sigmode
    
    sigmode*sigmode=sigmode*導sigmode+導sigmode*sigmode=a*a(1-a)+a(1-a)*a=2a*a*(1-a)
    
    最后再除以2 得到
    '''
    return a*a*(1-a)

def outputValue(weight,bias):
    '''
    神經元輸出
    
    神經元輸入為1
    '''
    return sigmode(weight*1+bias);

def gradient_descent():
    '''
    梯度下降
    '''
    #學習次數
    umFrames = 300;
    weight = 0.6
    bias = 0.9
    count=0
    
    #學習步長
    eta=0.15
    while True:
        a = outputValue(weight, bias)
        delta = quadratic_derivative(a)
        weight += -eta*delta
        bias += -eta*delta
        count += 1
        if count > umFrames:
            print "w = ",weight
            print "b = ",bias
            print "sigmoid:",a
            break;

gradient_descent()    

 
         

w =  -1.28433217279

 
         

b =  -0.984332172794

 
         

sigmoid: 0.0939556948636

圖解:

  ==》》

ref:http://neuralnetworksanddeeplearning.com/chap3.html#the_cross-entropy_cost_function

 

#這兒模擬了使用梯度下降來實現神經元的自主學習 


免責聲明!

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



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