梯度才是神经网络最美的样子

picture.image

关于梯度下降,本文主要讲三个问题:

一、什么是梯度

二、什么是梯度下降

三、三种常见的梯度下降算法实现

什么是梯度

梯度是一个与函数相切的向量,指向此函数最大增量的方向。 函数在局部最大值或最小值处梯度为零。 在数学中,梯度被定义为函数的偏导数。 例如,我们有一个函数:

picture.image

函数图形如下图所示,我们可以看到函数的最小值点在(0,0)。

picture.image

即该函数的梯度为对x的偏导数与对y的偏导数,可表示为:

picture.image

如果我们想要在点(1,2)处的梯度,只需要将(1,2)代入上面的公式即可得到梯度为:

picture.image

什么是梯度下降

由于梯度是指向函数最大增量的向量,因此负梯度是指向函数最大减量的向量。 因此,梯度下降就是通过在负梯度方向上迭代来最小化损失函数。

在迭代的过程中,先定义一个起点:

picture.image

然后得到迭代过程为

picture.image

上面公式中参数alpha称为学习率,一般设置为一个较小的常量。还是用上面的例子来说,我们已经知道函数的梯度为:

picture.image

因此,梯度下降的迭代过程就可以写成:

picture.image

picture.image

化简得:

picture.image

picture.image

如果我们假设alpha小于1,那么我们可以得到:

picture.image

结论与我们在上图中观察到的结果相同。 另一种解释梯度下降的直观方法是在下山的过程中,每一步都走下降最陡的地方即可最快到达山脚。

picture.image

同样,在机器学习中我们更关注目标函数和参数之间的关系,机器学习模型使用梯度下降的核心思想就是迭代调整参数以便最小化成本函数。

picture.image

在某些情况下,我们可以通过方程直接计算最适合模型到训练集的参数。 例如,要最小化线性回归的MSE,参数可以写为:

picture.image

Gradient Descent中的一个重要参数是学习率,它决定了每次下降的步长。当学习速度太大时,梯度下降可能错过最优解。 当学习速率太小时,算法需要很长时间才能收敛。 因此,初始化适当的学习率是非常重要的。

picture.image

归一化对梯度下降同样重要。 如果特征未归一化,大量的特征参数将会大大增加算法的复杂度。 在对所有特征进行归一化后可以加速梯度下降算法下降到最低。下图可以直接了解归一化对于梯度下降的作用。

picture.image

三种常见的梯度下降算法实现

常用的梯度下降算法包括批量梯度下降,小批量梯度下降和随机梯度下降。下面我们将用Python来实现这三种算法。

picture.image

批量梯度下降: 批量梯度下降在每一步迭代时使用整个训练集。

它计算每条数据的误差,并取平均值来确定梯度。

批量梯度下降的优点是该算法计算效率更高,并且它产生稳定的学习路径,因此更容易收敛。

但是,当训练集很大时,批量梯度下降需要更长的时间。


                        
 # Function for batch gradient decent   
  def Batch\_GD (Learning\_Rate,num\_iterations,X,y):   
    #Step 1: Initial Parameter   
    N=len(X)   
    w=np.zeros((X.shape[1],1))   
    b=0   
    costs=[]   
    # Starting Loop   
    for i in range(num_iterations):   
    #Step 2: Apply Sigmoid Function and get y prediction   
      Z=np.dot(wT,XT)+b   
      y_pred=1/(1+1/np.exp(Z))   
  
    #Step 3: Calculate Loss Function   
      cost=-(1/N)*np.sum(y*np.log(y_pred)+(1-y)*np.log(1-y_pred))   
  
    #Step 4: Calculate Gradient   
      dw=1/N*np.dot(XT,(y_pred-y).T)   
      db=1/N*np.sum(y_pred-y)   
  
    #Step 5: Update w & b   
      w = w - Learning_Rate * dw   
      b = b - Learning_Rate * db   
  
    # Records cost   
    if i % 1000 == 0:   
      costs.append(cost)   
    #print(cost)   
    return(w,b,costs)   
  # Run a function   
  Result_BatchGD=Batch_GD(Learning_Rate=0.01,num_iterations=100000,X=X,y=y)   

                    

随机梯度下降: 随机梯度下降只是从每个迭代的训练集中选择一个误差,并且仅基于该单个记录更新梯度。

随机梯度下降的优点是算法在每次迭代时速度较快。

与批量梯度下降相比,该算法在迭代的过程中 成本函数不会平滑地减少,而是会上下跳动。

经过几轮迭代后,算法可能会找到一个好的参数,但最终结果不一定是全局最优的。


                        
 # Function for Stochastic Gradient Descent   
  def Stochastic\_GD (Learning\_Rate,num\_iterations,X,y):   
  # Step 1: Initial Parameter   
    N=len(X)   
    w=np.zeros((X.shape[1],1))   
    b=0   
    costs=[]   
  # Starting two layer of loops   
    for i in range(num_iterations):   
      for j in range(N):   
  # Choose 1 record   
        XX=X[j,:]   
        yy=y[j]   
  # Step 2: Apply Sigmoid Function and get y prediction   
        Z=np.dot(wT,XX.T)+b   
        y_pred=1/(1+1/np.exp(Z))   
  #Step 3: Calculate Loss Function   
        cost=-(yy*np.log(y_pred)+(1-yy)*np.log(1-y_pred))   
  #Step 4: Calculate Gradient   
        dw=np.multiply(XX,(y_pred-yy)).reshape((2,1))   
        db=y_pred-yy   
  #Step 5: Update w & b   
        w = w - Learning_Rate * dw   
        b = b - Learning_Rate * db   
  
  #Step 6: Calculate Loss Function   
        Z_full=np.dot(wT,XT)+b   
        y_pred_full=1/(1+1/np.exp(Z_full))   
        cost=-(1/N)*np.sum(y*np.log(y_pred_full)+(1-y)*np.log(1-y_pred_full))   
  #Records cost   
     if i % 100 == 0:   
        costs.append(cost)   
  #print(cost)   
  
    return(w,b,costs)   
  # Run a function   
  Result_Stoc_GD=Stochastic_GD(Learning_Rate=0.01,num_iterations=2000,X=X,y=y)   

                    

小批量梯度下降:小批量梯度下降 结合了Batch和随机梯度下降的概念。算法每次迭代 是基于训练集的子集而不是完整数据集。小批量梯度下降 的优点是该算法在计算过程中利用矩阵运算,并且损失函数可以比随机梯度下降更平稳和稳定地降低。


                        
# Function for mini batch Gradient Descent   
  def Minibatch\_GD (Learning\_Rate,num\_iterations,X,y,Minibatch):   
  # Part 1: Mini Batch   
    np.random.seed(1000)   
    N=len(X)   
    mini_batches=[]   
  
  #Step 1: Shuffle (X,y)   
    permutation=list(np.random.permutation(N))   
    shuffled_X=X[permutation,:]   
    shuffled_y=y[permutation]   
  
  #Step 2: Partition   
    num_complete_minibatches=int(np.floor(N/Minibatch))   
  
  for i in range(num_complete_minibatches):   
    mini_batch_X=shuffled_X[i*Minibatch:(i+1)*Minibatch,:]   
    mini_batch_y=shuffled_y[i*Minibatch:(i+1)*Minibatch]   
  
    mini_batch = (mini_batch_X, mini_batch_y)   
    mini_batches.append(mini_batch)   
  
  if N % Minibatch !=0:   
  mini_batch_X=shuffled_X[N-Minibatch:N,:]   
  mini_batch_y=shuffled_y[N-Minibatch:N]   
  
  mini_batch = (mini_batch_X, mini_batch_y)   
  mini_batches.append(mini_batch)   
  
  # Part 2: Gradient Descent   
  w=np.zeros((X.shape[1],1))   
  b=0   
  costs=[]   
  
  for i in range(num_iterations):   
  for j in range(num_complete_minibatches+1):   
  #Select Minibatch   
  XX=mini_batches[j][0]   
  yy=mini_batches[j][1]   
  #Step 2: Apply Sigmoid Function and get y prediction   
  Z=np.dot(wT,XX.T)+b   
  y_pred=1/(1+1/np.exp(Z))   
  
  #Step 3: Calculate Gradient   
  dw=1/Minibatch*np.dot(XX.T,(y_pred-yy).T)   
  db=1/Minibatch*np.sum(y_pred-yy)   
  #Step 4: Update w & b   
  w = w - Learning_Rate * dw   
  b = b - Learning_Rate * db   
  
  #Step 5: Calculate Loss Function   
  Z_full=np.dot(wT,XT)+b   
  y_pred_full=1/(1+1/np.exp(Z_full))   
  cost=-(1/N)*np.sum(y*np.log(y_pred_full)+(1-y)*np.log(1-y_pred_full))   
  
  if i % 1000 ==0:   
    costs.append(cost)   
  #print(cost)   
  
    return(w,b,costs)   
  # Run a function   
  Result_MiniGD=Minibatch_GD(Learning_Rate=0.01,num_iterations=100000,X=X,y=y,Minibatch=50)   

                    

参考

https://towardsdatascience.com/an-introduction-to-gradient-descent-c9cca5739307

picture.image

0
0
0
0
评论
未登录
暂无评论