深度學習(2)--梯度下降算法

      最近,訓練過程中遇到了一些問題,所有回頭看了一些原理性的內容,學習過程做了簡單記錄,如果有不準確的點,歡迎大家指正。

梯度下降(gradient descent)  

       梯度下降法的基本思想可以類比爲一個下山的過程。假設這樣一個場景:一個人被困在山上,需要從山上下來(i.e. 找到山的最低點,也就是山谷)。但此時山上的濃霧很大,導致可視度很低。因此,下山的路徑就無法確定,他必須利用自己周圍的信息去找到下山的路徑。這個時候,他就可以利用梯度下降算法來幫助自己下山。具體來說就是,以他當前的所處的位置爲基準,尋找這個位置最陡峭的地方,然後朝着山的高度下降的地方走,同理,如果我們的目標是上山,也就是爬到山頂,那麼此時應該是朝着最陡峭的方向往上走。然後每走一段距離,都反覆採用同一個方法,最後就能成功的抵達山谷。

      

Cost function (loss function, objective function): 目標函數

  

  • C: cost
  • w: weight 權重
  • b: bias 偏向
  • n: 訓練數據集實例個數
  • x: 輸入值
  • a: 輸出值 (當x是輸入時)
  • ||v||:  向量的length function

C(w,b) 越小越好,輸出的預測值和真實值差別越小,因此我們在訓練過程的目標是最小化C(w,b)

      最小化問題可以用梯度下降解決(gradient descent),假設目標函數C有兩個參數v1和v2,通常可以用微積分解決,如果v包含的變量過多,無法用微積分解決.

               

      對於一個變量,我們可以抽象成一個小球在曲面上的某一點,滾動到最低點,假設y在mininum的右側,每點的導數{y}'>0 ,假設每次移動f(x)=y-\eta {y}' ,結果仍然>0 ,其中\eta代表學習率(每次我們移動的步長),當y在mininum左側f(x)=y-\eta {y}' 結果仍然大於0,仍然向下移動。

                         

 

梯度下降的特點

1、可能會陷入局部最優  2、前提是目標函數要是凸函數convex  3、learning rate自動會減小

對於多個變量,每個變量的更新方法如下

         

   推導過程:

1,總的cost方程變化量和各個變量偏導方向的變化和大概相同

            

2,我們假設 

3,多個對於單個變量 梯度指這個變量的導數,對於多個變量 梯度只多個變量組成向量的轉置如下

            

可以推出    

4,由前面的單變量,我們假設  

  可以推出:  <=0

所以對於變量,可以使目標函數逐漸降低。

5,對於平均cost函數 可以推出

        == >

        ==>  

 

隨機梯度下降算法(stochastic gradient descent)

     對於一個訓練過程,一般實例都有幾萬或者幾十萬,對於人臉項目都有數百萬的訓練集,如果等都訓練一遍在更新不太現實。

基本思想:從所有訓練實例中隨機取一個採樣(sample):X1,X2,...,Xm (mini-batch),來估計▽T▽T,大大提高學習效率。

       可以推斷出

                                   

                       

    w和b的更新方程如下:

                         

     然後重新選擇下一個mini_batch 進行訓練。

代碼實現如下:

    def SGD(self,train_data,epoches,mini_size,eta,test_data):
        if test_data: n_test = len(test_data)
        n = len(train_data) #表示 訓練樣本數量
        for epoch in range(epoches):
            random.shuffle(train_data)

            mini_batches = [train_data[k:k+mini_size] for k in xrange(0,n,mini_size)] #xrange 返回的是生成器
            for mini_batch in mini_batches:
                self.update_minibatch(mini_batch,eta)
            if test_data:
                print "epoches {0} acc {1}/{2} ".format(epoch,self.cal_acc(test_data),n_test)
            else:
                print "no test data"

    # mini_batch 代表mini_size 個元組(x,y) 其中x是輸入的維度 ,輸出是class的種類
    def update_minibatch(self,mini_batch,eta):

        nabla_b = [np.zeros(b.shape) for b in self.biases] #隨機梯度下降算法,用於存儲我們指定的minibatch中的數據的bias的總和
        nabla_w = [np.zeros(w.shape) for w in self.weights]

        for x,y in mini_batch:
            new_nabla_b ,new_nabla_w = self.back(x,y)

            nabla_w = [nw+w for nw,w in zip(new_nabla_w,nabla_w)]
            nabla_b = [nb+b for nb,b in zip(new_nabla_b,nabla_b)]

        self.weights = [w-((eta/len(mini_batch))*nabla_w) for w,nabla_w in zip(self.weights,nabla_w)]
        self.biases = [b-((eta/len(mini_batch))*nabla_b) for b,nabla_b in zip(self.biases,nabla_b)]

 

 

 

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