0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

【连载】深度学习笔记6:神经网络优化算法之从SGD到Adam

人工智能实训营 2018-08-20 12:47 次阅读

从前面的学习中,带大家一起学会了如何手动搭建神经网络,以及神经网络的正则化等实用层面的内容。这些都使得我们能够更深入的理解神经网络的机制,而并不是初次接触深度学习就上手框架,虽然对外宣称神经网络是个黑箱机制,但是作为学习者我们极度有必要搞清楚算法在每个环节到底都干了些什么。

今天讲的是深度学习的一个大的主题——优化算法。采用何种方式对损失函数进行迭代优化,这是机器学习的一大主题之一,当一个机器学习问题有了具体的模型和评估策略,所有的机器学习问题都可以形式化为一个最优化问题。这也是为什么我们说优化理论和凸优化算法等学科是机器学习一大支柱的原因所在。从纯数学的角度来看,所有的数学模型尽管形式不一,各有头面,但到最后几乎到可以归约为最优化问题。所以,有志于奋战在机器学习和深度学习领域的各位,学好最优化,责无旁贷啊。

要说机器学习和深度学习的优化算法,梯度下降必然是核心所在。神经网络发展至今,优化算法层出不穷,但大底是出不了梯度下降的框框架架。这一篇笔记,笔者就和大家一起学习和回顾深度学习中常用的优化算法。在前面手动搭建神经网络的代码实践中,我们对于损失函数的优化采用了一般的梯度下降法,所以本篇总结就从梯度下降法开始。

梯度下降法 Gradient Descent


640?wx_fmt=png

想必大家对于梯度下降是很熟悉了,选择负梯度方向进行参数更新算是常规操作了。话不多说,对于多层神经网络如何执行梯度下降:

defupdate_parameters_with_gd(parameters,grads,learning_rate):
"""
Updateparametersusingonestepofgradientdescent

Arguments:
parameters--pythondictionarycontainingyourparameterstobeupdated:
parameters['W'+str(l)]=Wl
parameters['b'+str(l)]=bl
grads--pythondictionarycontainingyourgradientstoupdateeachparameters:
grads['dW'+str(l)]=dWl
grads['db'+str(l)]=dbl
learning_rate--thelearningrate,scalar.
Returns:
parameters--pythondictionarycontainingyourupdatedparameters
"""
L=len(parameters)//2#numberoflayersintheneuralnetworks
#Updateruleforeachparameter
forlinrange(L):
parameters['W'+str(l+1)]=parameters['W'+str(l+1)]-learning_rate*grads['dW'+str(l+1)]
parameters['b'+str(l+1)]=parameters['b'+str(l+1)]-learning_rate*grads['db'+str(l+1)]
returnparameters

在上述代码中,我们传入含有权值和偏置的字典、梯度字段和更新的学习率作为参数,按照开头的公式编写权值更新代码,一个简单的多层网络的梯度下降算法就写出来了。

小批量梯度下降法 mini-batch Gradient Descent

工业数据环境下,直接对大数据执行梯度下降法训练往往处理速度缓慢,这时候将训练集分割成小一点的子集进行训练就非常重要了。这个被分割成的小的子集就叫做 mini-batch,意为小批量。对每一个小批量同时执行梯度下降会大大提高训练效率。在实际利用代码实现的时候,小批量梯度下降算法通常包括两个步骤:充分打乱数据(shuffle)和分组组合数据(partition)。如下图所示。

640?wx_fmt=png
shuffle
640?wx_fmt=png
partition

具体代码实现为:

def random_mini_batches(X, Y, mini_batch_size = 64, seed = 0):
  """
  Creates a list of random minibatches from (X, Y)

  Arguments:
  X -- input data, of shape (input size, number of examples)
  Y -- true "label" vector (1 for blue dot / 0 for red dot), of shape (1, number of examples)
  mini_batch_size -- size of the mini-batches, integer

  Returns:
  mini_batches -- list of synchronous (mini_batch_X, mini_batch_Y)
  """

  np.random.seed(seed)    
  m = X.shape[1]         
  mini_batches = []  # Step 1: Shuffle (X, Y)
  permutation = list(np.random.permutation(m))
  shuffled_X = X[:, permutation]
  shuffled_Y = Y[:, permutation].reshape((1,m))  # Step 2: Partition (shuffled_X, shuffled_Y). Minus the end case.
  num_complete_minibatches = math.floor(m/mini_batch_size) 
  for k in range(0, num_complete_minibatches):
    mini_batch_X = shuffled_X[:, 0:mini_batch_size]
    mini_batch_Y = shuffled_Y[:, 0:mini_batch_size]

    mini_batch = (mini_batch_X, mini_batch_Y)
    mini_batches.append(mini_batch)  # Handling the end case (last mini-batch < mini_batch_size)
  if m % mini_batch_size != 0:
    mini_batch_X = shuffled_X[:, 0: m-mini_batch_size*math.floor(m/mini_batch_size)]
    mini_batch_Y = shuffled_Y[:, 0: m-mini_batch_size*math.floor(m/mini_batch_size)]

    mini_batch = (mini_batch_X, mini_batch_Y)
    mini_batches.append(mini_batch)  
return mini_batches

小批量梯度下降的实现思路非常清晰,先打乱数据在分组数据,需要注意的细节在于最后一个小批量所含的训练样本数,通常而言最后一个小批量会少于前面批量所含样本数。

随机梯度下降 Stochastic Gradient Descent

当小批量所含的训练样本数为 1 的时候,小批量梯度下降法就变成了随机梯度下降法(SGD)。SGD虽然以单个样本为训练单元训练速度会很快,但牺牲了向量化运算所带来的便利性,在较大数据集上效率并不高。
我们可以看一下梯度下降和随机梯度下降在实现上的差异:

# GD
X = data_input Y = labels parameters = initialize_parameters(layers_dims)
for i in range(0, num_iterations): # Forward propagation a, caches = forward_propagation(X, parameters) # Compute cost. cost = compute_cost(a, Y) # Backward propagation. grads = backward_propagation(a, caches, parameters) # Update parameters. parameters = update_parameters(parameters, grads)

# SGDX = data_input Y = labels parameters = initialize_parameters(layers_dims)
for i in range(0, num_iterations):
for j in range(0, m): # Forward propagation a, caches = forward_propagation(X[:,j], parameters) # Compute cost cost = compute_cost(a, Y[:,j]) # Backward propagation grads = backward_propagation(a, caches, parameters) # Update parameters. parameters = update_parameters(parameters, grads)

所以,从本质上看,梯度下降法、小批量梯度下降法和随机梯度下降法,并没有区别。唯一的区别就在于它们执行一次训练过程所需要用到的训练样本数。梯度下降法用到的是全集训练数据,随机梯度下降则是单个样本数据,而小批量则是介于二者之间。

带动量的梯度下降法(momentum)


正如上图中看到的一样,我们假设梯度下降的横向为参数 W 的下降方向,而偏置 b 的下降方向为纵轴,我们总是希望在纵轴上的震荡幅度小一点,学习速度慢一点,而在横轴上学习速度快一点,无论是小批量梯度下降还是随机梯度下降,好像都不能避免这个问题。为了解决这个问题,带动量的梯度下降法来了。带动量的梯度下降考虑历史梯度的加权平均值作为速率进行优化。执行公式如下:

640?wx_fmt=png
根据上述公式编写带动量的梯度下降法实现代码:

defupdate_parameters_with_momentum(parameters,grads,v,beta,learning_rate):
"""
UpdateparametersusingMomentum

Arguments:
parameters--pythondictionarycontainingyourparameters:
parameters['W'+str(l)]=Wl
parameters['b'+str(l)]=bl
grads--pythondictionarycontainingyourgradientsforeachparameters:
grads['dW'+str(l)]=dWl
grads['db'+str(l)]=dbl
v--pythondictionarycontainingthecurrentvelocity:
v['dW'+str(l)]=...
v['db'+str(l)]=...
beta--themomentumhyperparameter,scalar
learning_rate--thelearningrate,scalar

Returns:
parameters--pythondictionarycontainingyourupdatedparameters
v--pythondictionarycontainingyourupdatedvelocities
"""

L=len(parameters)//2#numberoflayersintheneuralnetworks

#Momentumupdateforeachparameter
forlinrange(L):#computevelocities
v['dW'+str(l+1)]=beta*v['dW'+str(l+1)]+(1-beta)*grads['dW'+str(l+1)]
v['db'+str(l+1)]=beta*v['db'+str(l+1)]+(1-beta)*grads['db'+str(l+1)]#updateparameters
parameters['W'+str(l+1)]=parameters['W'+str(l+1)]-learning_rate*v['dW'+str(l+1)]
parameters['b'+str(l+1)]=parameters['b'+str(l+1)]-learning_rate*v['db'+str(l+1)]
returnparameters,v

实现带动量的梯度下降的关键点有两个:一是动量是考虑历史梯度进行梯度下降的,二是这里的需要指定的超参数变成了两个:一个是学习率 learning_rate,一个是梯度加权参数beta

Adam算法

Adam 全称为 Adaptive Moment Estimation,是在带动量的梯度下降法的基础上融合了一种称为 RMSprop(加速梯度下降)的算法而成的。相较于带动量的梯度下降法,无论是RMSprop 还是 Adam,其中的改进思路都在于如何让横轴上的学习更快以及让纵轴上的学习更慢。RMSprop 和 Adam 在带动量的梯度下降法的基础上,引入了平方梯度,并对速率进行了偏差纠正。具体计算公式如下:

640?wx_fmt=png

实现代码如下:

def update_parameters_with_adam(parameters, grads, v, s, t, learning_rate = 0.01,
                beta1 = 0.9, beta2 = 0.999, epsilon = 1e-8):
  """
  Update parameters using Adam

  Arguments:
  parameters -- python dictionary containing your parameters:
          parameters['W' + str(l)] = Wl
          parameters['b' + str(l)] = bl
  grads -- python dictionary containing your gradients for each parameters:
          grads['dW' + str(l)] = dWl
          grads['db' + str(l)] = dbl
  v -- Adam variable, moving average of the first gradient, python dictionary
  s -- Adam variable, moving average of the squared gradient, python dictionary
  learning_rate -- the learning rate, scalar.
  beta1 -- Exponential decay hyperparameter for the first moment estimates 
  beta2 -- Exponential decay hyperparameter for the second moment estimates 
  epsilon -- hyperparameter preventing division by zero in Adam updates

  Returns:
  parameters -- python dictionary containing your updated parameters 
  v -- Adam variable, moving average of the first gradient, python dictionary
  s -- Adam variable, moving average of the squared gradient, python dictionary
  """

  L = len(parameters) // 2         
  v_corrected = {}            
  s_corrected = {}             

  # Perform Adam update on all parameters
  for l in range(L):
    v["dW" + str(l+1)] = beta1 * v["dW" + str(l+1)] + (1 - beta1) * grads['dW'+str(l+1)]
    v["db" + str(l+1)] = beta1 * v["db" + str(l+1)] + (1 - beta1) * grads['db'+str(l+1)]    # Compute bias-corrected first moment estimate. Inputs: "v, beta1, t". Output: "v_corrected".  
    v_corrected["dW" + str(l+1)] = v["dW" + str(l+1)] / (1 - beta1**t)
    v_corrected["db" + str(l+1)] = v["db" + str(l+1)] / (1 - beta1**t)    # Moving average of the squared gradients. Inputs: "s, grads, beta2". Output: "s".
    s["dW" + str(l+1)] = beta2 * s["dW" + str(l+1)] + (1 - beta2) * (grads["dW" + str(l+1)])**2
    s["db" + str(l+1)] = beta2 * s["db" + str(l+1)] + (1 - beta2) * (grads["db" + str(l+1)])**2


    # Compute bias-corrected second raw moment estimate. Inputs: "s, beta2, t". Output: "s_corrected".
    s_corrected["dW" + str(l+1)] = s["dW" + str(l+1)] / (1 - beta2**t)
    s_corrected["db" + str(l+1)] = s["db" + str(l+1)] / (1 - beta2**t)    # Update parameters. Inputs: "parameters, learning_rate, v_corrected, s_corrected, epsilon". Output: "parameters".

    parameters["W" + str(l+1)] = parameters["W" + str(l+1)] - learning_rate * v_corrected["dW" + str(l+1)] / (np.sqrt(s_corrected["dW" + str(l+1)]) + epsilon)
    parameters["b" + str(l+1)] = parameters["b" + str(l+1)] - learning_rate * v_corrected["db" + str(l+1)] / (np.sqrt(s_corrected["db" + str(l+1)]) + epsilon)  
return parameters, v, s

除了以上这些算法,还有一些像 Adadelta 之类的算法我们没有提到,有需要了解的同学可以自行查找相关资料。最后用一个图来展示各种优化算法的效果:




本文来自《自兴动脑人工智能》项目部:凯文




声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
收藏 人收藏

    评论

    相关推荐

    神经网络优化器有哪些

    神经网络优化器是深度学习中用于调整网络参数以最小化损失函数的重要工具。这些优化器通过不同的策略来
    的头像 发表于 07-11 16:33 442次阅读

    BP神经网络学习机制

    BP神经网络(Backpropagation Neural Network),即反向传播神经网络,是一种基于梯度下降算法的多层前馈神经网络,其学习
    的头像 发表于 07-10 15:49 351次阅读

    深度神经网络与基本神经网络的区别

    在探讨深度神经网络(Deep Neural Networks, DNNs)与基本神经网络(通常指传统神经网络或前向神经网络)的区别时,我们需
    的头像 发表于 07-04 13:20 545次阅读

    深度神经网络的设计方法

    结构的构建,还包括激活函数的选择、优化算法的应用、正则化技术的引入等多个方面。本文将从网络结构设计、关键组件选择、优化与正则化策略、以及未来发展趋势四个方面详细探讨
    的头像 发表于 07-04 13:13 361次阅读

    神经网络优化算法有哪些

    神经网络优化算法深度学习领域中的核心技术之一,旨在通过调整网络中的参数(如权重和偏差)来最小化
    的头像 发表于 07-03 16:01 390次阅读

    神经网络反向传播算法的优缺点有哪些

    神经网络反向传播算法(Backpropagation Algorithm)是一种广泛应用于深度学习和机器学习领域的
    的头像 发表于 07-03 11:24 577次阅读

    神经网络反向传播算法的作用是什么

    神经网络反向传播算法(Backpropagation)是一种用于训练人工神经网络算法,它通过计算损失函数关于网络参数的梯度来更新
    的头像 发表于 07-03 11:17 962次阅读

    神经网络反向传播算法的原理、数学推导及实现步骤

    传播算法的原理、数学推导、实现步骤以及在深度学习中的应用。 神经网络概述 神经网络是一种受人脑启发的计算模型,由大量的
    的头像 发表于 07-03 11:16 608次阅读

    神经网络算法的结构有哪些类型

    神经网络算法深度学习的基础,它们在许多领域都有广泛的应用,如图像识别、自然语言处理、语音识别等。神经网络的结构有很多种类型,每种类型都有其
    的头像 发表于 07-03 09:50 362次阅读

    神经网络算法的优缺点有哪些

    的优点 自学习能力:神经网络算法具有强大的自学习能力,能够大量数据中自动提取特征,无需人工干预。这使得
    的头像 发表于 07-03 09:47 943次阅读

    深度学习与卷积神经网络的应用

    随着人工智能技术的飞速发展,深度学习和卷积神经网络(Convolutional Neural Network, CNN)作为其中的重要分支,已经在多个领域取得了显著的应用成果。图像识
    的头像 发表于 07-02 18:19 726次阅读

    基于神经网络算法的模型构建方法

    神经网络是一种强大的机器学习算法,广泛应用于各种领域,如图像识别、自然语言处理、语音识别等。本文详细介绍了基于神经网络算法的模型构建方法,包
    的头像 发表于 07-02 11:21 404次阅读

    深度神经网络模型有哪些

    、Sigmoid或Tanh。 卷积神经网络(Convolutional Neural Networks,CNN): 卷积神经网络深度学习中最重
    的头像 发表于 07-02 10:00 1022次阅读

    如何训练和优化神经网络

    神经网络是人工智能领域的重要分支,广泛应用于图像识别、自然语言处理、语音识别等多个领域。然而,要使神经网络在实际应用中取得良好效果,必须进行有效的训练和优化。本文将从神经网络的训练过程
    的头像 发表于 07-01 14:14 369次阅读

    详解深度学习神经网络与卷积神经网络的应用

    处理技术也可以通过深度学习来获得更优异的效果,比如去噪、超分辨率和跟踪算法等。为了跟上时代的步伐,必须对深度学习
    的头像 发表于 01-11 10:51 1820次阅读
    详解<b class='flag-5'>深度</b><b class='flag-5'>学习</b>、<b class='flag-5'>神经网络</b>与卷积<b class='flag-5'>神经网络</b>的应用