如何训练你的神经网络?

  深度学习领域中有一些不错的做法,以便有效地训练深层神经网络。 在这篇文章中,将介绍一些最常用的实践,从训练数据的重要性,超参数的选择到更快的DNNs原型的更一般的方法.大多数这些做法都经过学术界和行业的研究验证,并在诸如Efficient BackProp(Yann LeCun et al.)and Practical Recommendations for Deep Architectures(Yoshua Bengio).等研究论文中提供了数学和实验证明。在这篇文章中没有提到任何数学证明。而是更多地概括了训练DNN的最佳实践方法。 同时,为了更深入的了解,你可以浏览上面提到的研究论文和参考文献。因此,这篇文章更多的是导向性的作用。


1.训练数据

  许多初学者都习惯直接把原始数据扔进DNN中去训练,尽管有些时候会得到不错的结果。但记住一句话“给定正确的数据类型,一个相当简单的模型将提供比复杂DNN更好更快的结果“(尽管这可能有例外)。所以,无论你是在处理CV,NLP,或者语音识别,都应该尽可能的对训练数据进行预处理,当然这不仅仅是符合程序输入的预处理。下面是常见的几点:

  • (1) .可能扩大你的数据集

  • (2).删除任何具有损坏数据的训练样本(短文本,高度失真的图像,杂散输出标签,具有大量空值的特征等)

  • (3).数据增强 - 创建新示例(比如在图像的情况下 - 重新缩放,旋转平移,添加噪点等

  • (4)对输入数据归一化。那么具体为什么需要归一化呢?归一化后有什么好处呢?原因在于神经网络学习过程本质就是为了学习数据分布,一旦训练数据与测试数据的分布不同,那么网络的泛化能力也大大降低;另外一方面,一旦每批训练数据的分布各不相同(batch 梯度下降),那么网络就要在每次迭代都去学习适应不同的分布,这样将会大大降低网络的训练速度,这也正是为什么我们需要对数据都要做一个归一化预处理的原因.

  另外,在卷积神经网处理图像问题的时候,图像数据有3种常见的预处理可能会用到,如下。我们假定数据表示成矩阵为X,其中我们假定X是[N*D]维矩阵(N是样本数据量,D为单张图片的数据向量长度).需要特别说明的一点是,下述的预处理操作,一定都是在训练集上先预算的,然后应用在交叉验证/测试集上的。举个例子,有些同学会先把所有的图片放一起,求均值,然后减掉均值,再把这份数据分作训练集和测试集,这是不对的

  • (1).去均值,这是最常见的图片数据预处理,简单说来,它做的事情就是,对待训练的每一张图片的特征,都减去全部训练集图片的特征均值,这么做的直观意义就是,我们把输入数据各个维度的数据都中心化到0了。使用python的numpy工具包,这一步可以用X -= np.mean(X, axis = 0)轻松实现。当然,其实这里也有不同的做法:简单一点,我们可以直接求出所有像素的均值,然后每个像素点都减掉这个相同的值;稍微优化一下,我们可以在RGB三个颜色通道分别做这件事。

  • (2).归一化,归一化的直观理解含义是,我们做一些工作去保证所有的维度上数据都在一个变化幅度上。通常我们有两种方法来实现归一化。一个是在数据都去均值之后,每个维度上的数据都除以这个维度上数据的标准差(X /= np.std(X, axis = 0))。另外一种方式是我们除以数据绝对值最大值,以保证所有的数据归一化后都在-1到1之间。多说一句,其实在任何你觉得各维度幅度变化非常大的数据集上,你都可以考虑归一化处理。不过对于图像而言,其实这一步反倒可做可不做,因为大家都知道,像素的值变化区间都在[0,255]之间,所以其实图像输入数据天生幅度就是一致的。

  • (3).PCA和白化/whitening,这是另外一种形式的数据预处理。在经过去均值操作之后,我们可以计算数据的协方差矩阵,从而可以知道数据各个维度之间的相关性


2.选择合适的激活函数

  激活函数是神经网络的重要部分。需要知道的是,激活函数并不是说真的激活了什么,而是为模型添加非线性元素,增加模型复杂度。以前sigmoid往往是首选,但它有俩个明显的缺点:由于sigmoid函数的性质,一是在纵坐标接近0和1的那些位置(也就是输入信号的幅度很大的时候),斜率都趋于0,因此在梯度下降的过程中容易饱合和梯度消失;二是sigmoid函数的输出没有0中心化,这是一个比较闹心的事情,因为每一层的输出都要作为下一层的输入,而未0中心化会直接影响梯度下降。tanh也许是更好的选择,尽管tanh只是一个重新缩放的Sigmoid,tanh(x)= 2 * sigmoid(x)-1,也存在梯度消失的问题,但它的输出是0中心化的的,因此收敛效果会更好。

  你可以进一步探索其他的激活函数u,如ReLU,SoftSign等,具体取决于具体的任务,这的确可以改善其中的一些问题。其中,relu或者relu6在CNN的卷积层的应用是非常广泛的。最近新出的selu,据说可以完美解决梯度消失和梯度爆炸的问题,毕竟花了将近百页的论文证明得到俩个参数,不过实际的泛华性能可能还有待大量训练的检验


3.隐藏层的层数

  保持比最佳数量更多的隐藏层单元,通常是一个可行的办法。 既然,任何正规化方法至少在某种程度上都会照顾到多余的单位。 另一方面,在保持较小数量的隐藏单位(优于最佳数量)的同时,更有可能配合模型。此外,在采用无监督的预训练表示(在后面的部分中描述)时,隐藏单元的最佳数量通常保持更大。 由于预处理的代表可能在这些表示中包含大量不相关的信息(对于特定的监督任务)。 通过增加隐藏单元的数量,模型将具有所需的灵活性,以过滤掉这些预先训练的表示中的最合适的信息。择最佳层数比较简单。 正如 Yoshua-Bengio在Quora上提到的 - “你只是继续添加图层,直到测试错误不再改进”。


4.权重初始化

  需要记住的一点是“始终使用小随机数初始化权重,以打破不同神经元之间的对称性”。但是,多小是合适的呢?建议的上限是多少呢?用什么概率分布生产随机数比较合适呢?若我们使用sigmoid函数 ,随机数太大会导致sigmoid饱和,从而神经元坏死;随机数太小则梯度会变得很小。因此,选择合适范围大小的初始值也很重要幸运的是,许多大牛们对于初始权重的适当值已经进行了大量的研究,这对于有效地融合是非常重要的。 为了初始化均匀分布的权重,均匀分布可能是最佳选择之一。此外,拥有较多输入的神经元单元应该拥有相对较小的权重。更令人兴奋的是,有一个公式,我们可以直接用于初始化权重; 即 直接利用〜uniform(-r,r)分布,其中r = sqrt(6 /(fan_in + fan_out))用于tanh激活,r = 4 *(sqrt(6 / fan_in + fan_out))用于sigmoid激活,其中 fan_in是上一层的大小,fan_out是下一层的大小.

   而另外一篇比较新的论文[Delving Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet Classification]则指出尤其对于ReLU神经元,我们初始化方差应该为2.0/n,也就是w = np.random.randn(n) * sqrt(2.0/n),目前的神经网络中使用了很多ReLU单元,因此这个设定其实在实际应用中使用最多。


5.学习率

  这可能是最重要的一个超参了,它影响着学习的过程。我们都知道,学习率太小,Loss 将很难收敛或者容易先入局部最优值;学习率过大,则在最初的训练中有可能无法收敛,Loss会变得很大很大。一般而言,将lr设置成0.01是比较安全的,尽管这不是绝对的,需要视具体的任务而定。

   与设置一个固定的学习率不同的是,在每次迭代或训练了几千 个数据之后,降低学习率是另外一种方法,虽然这可能有助于更快的训练,但需要另外手动决定新的学习率。 一般来说,学习速率可以在每轮迭代之后减半 , 这些策略在几年前相当普遍的。幸运的是,现在我们有更好的基于动量的方法来改变学习率,这是基于误差函数的曲率。 这也可能有助于为模型中的各个参数设置不同的学习率; 因为某些参数可能以相对较慢或更快的速度学习

  慢慢的,越来越多的好的优化方法可供选择,从Momentum Method 到 Adagrad, Adam, RMSProp 等。像Adagrad或Adam这样的方法,有效地挽救了我们手动选择初始学习率,并给出正确的时间,模型将开始趋于顺利(当然,仍然选择一个良好的初始速率将进一步的帮助)。像Adagrad或Adam这样的方法,可以让我们不用手动设置初始学习率,并给出正确的时间,模型也收敛的更加平滑。(当然,仍然选择一个良好的初始速率也是更好的)。


6.将参数的维度大小保持在2的指数幂

   即使在使用最新硬件资源处理最先进的深度学习模型时,内存管理仍然在字节级别完成; 所以,将参数的大小保持为64,128,512,1024(所有功率为2)总是好的。 这可能有助于分割矩阵,权重等,导致学习效率略有提升。 这在处理GPU时变得更加显着。


  网格搜索在古典机器学习中已经普遍存在。 但是,网格搜索在找到DNN的最佳超参数方面效率并不高。 主要是因为DNN在尝试不同的超参数组合时所花费的时间。 随着超参数的不断增加,网格搜索所需的计算也呈指数增长。 有两种方法:1.根据你以前的经验,您可以手动调整一些常见的超参数,如学习率,层数等。2.代替网格搜索,使用随机搜索/随机抽样选择最优超参数。 通常从所需范围内的均匀分布中选择超参数的组合。 还可以添加一些先前的知识来进一步减少搜索空间(如学习率不应该太大或太小)。 总之,与Grid Search相比,随机搜索的效率更高。


8.Mini-Batch vs. Stochastic Learning

  训练模型的主要目标是学习适当的参数,从而将输入结果转换成输出的最佳映射。无论你决定使用批次,小批量还是随机学习,模型都会对每个训练样本进行调整。在采用随机学习方法的过程中,训练每个样本之后调整权重梯度,将噪声引入梯度(因此称为“随机”)。这是非常理想的效果;即 - 在训练期间引入噪音,因此该模型不太容易过拟合。 然而,通过随机学习方法可能效率相对较低,因为单个单个训练耗时耗力。渐渐的,机器具有更强大的计算能力,随机学习可能有效地浪费了大部分的学习。送一如果我们能够计算矩阵矩阵乘法,那么我们为什么要限制自己,来迭代单个向量对的乘法呢?因此,为了提高吞吐量/加快学习速度,建议使用小批次而不是随机学习。

  但是,选择合适的批量同样重要;使得我们仍然可以保持一些噪音(不使用大批量),同时更有效地使用机器的计算能力。通常,一批16到128个例子是一个很好的选择(指数为2)。通常,一旦您已经找到更重要的超参数(通过手动搜索或随机搜索),则会选择批量大小。尽管如此,当模型将训练数据作为流(在线学习)时,还有一些场景,然后采用随机学习是一个很好的选择。.


9.打乱训练数据

  这来自信息论 - “Learning that an unlikely event has occurred is more informative than learning that a likely event has occurred”。 类似地,随机化训练样本的顺序(在不同的迭代轮数或批量中)将导致更快的收敛。 当我们没有输入相同顺序的数据时,模型的性能总是会有轻微的提升。


10.dropout正则化

   考虑到要学习很多个参数,正则化成为防止DNN过拟合的必要条件。 你也可以继续使用L1 / L2正则化,但是Dropout(简单理解就是在前向训练过程随机断开一定比例的神经元以防止网络过度依赖某一特征或神经元)更容易检查DNN有没有过拟合。 dropout实现很简单,但通常会加速学习的过程,加速收敛。 默认值为0.5是一个不错的选择,尽管这取决于具体的任务。 如果模型不太复杂,那么0.2的dropout也足够了。在测试过程中不能使用dropout,此外,权重还需进行一定的缩放。 一个使用了Dropout正则化的模型,在合理的 时间内,它的错误率是一定会下降的。


11.BN层

   深度网络层次太多后,信号和梯度越来越小,深层难以训练。被称作梯度弥散。也有可能越来越大,又被称作梯度爆炸。但是,我们知道网络一旦train起来,那么参数就要发生更新,除了输入层的数据外(因为输入层数据,我们已经人为的为每个样本归一化),后面网络每一层的输入数据分布是一直在发生变化的,因为在训练的时候,前面层训练参数的更新将导致后面层输入数据分布的变化,因此,所谓可学习的,有参数的BN(Batch Normalization)层,其本质就是在网络的每一层输入的时候,又插入了一个归一化层,也就是先做一个归一化处理,然后再进入网络的下一层,结果就是可以加速模型的训练,收敛,获得更好的性能。


12.Number of Epochs/Training Iterations

  “Training a Deep Learning Model for multiple epochs will result in a better model“,但是我们如何量化这个许多呢?事实证明,这是一个简单的策略,那就是在固定的样本数或者迭代次数下,保持你的训练,可以是2000个样本或者是一轮迭代。在每一组这些例子中,将测试误差与列车误差进行比较,如果差距在减小,则继续训练。 除此之外,在每个这样的集合之后,保存模型参数的副本(以便你可以在训练后从多个模型中选择更好的那一个)。


13.可视化

   深度学习模式的训练出现错误的原因有很多, 当我们的程序训练了好几个小时或几天,或是训练完成后,我们才意识到出了问题。 在这种情况下(这可能是非常有道理的),我们 总是应该记得将训练过程可视化。 你可以采取的最直接的方法就是打印/保存损失值的日志,训练或测试误差等。 除此之外,另一个好的做法是使用可视化库在少量训练示例之后或在迭代轮次之间绘制权重的直方图。,这都可能有助于跟踪深度学习模型中的一些常见问题,如“梯度消失”,”梯度爆炸”等。

参考资料
<1>.How to train your Deep Neural Network
<2>.CS231n Convolutional Neural Networks for Visual Recognition

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值