深度学习(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)]

 

 

 

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