揪出bug!解析调试神经网络的技巧

来源:互联网 发布:php 查找字符串位置 编辑:程序博客网 时间:2024/05/18 17:02

原文链接:Introduction to debugging neural networks 
译者:刘翔宇 审校:刘帝伟 
责编:周建丁(机器学习原创/翻译投稿请联系zhoujd@csdn.net)

以下建议是针对神经网络初学者的,这些建议都来自于我在行业应用和斯坦福大学里为神经网络初学者提供建议所获得的经验。本质上讲,神经网络要比大多数程序难以调试,因为大多数神经网络bug不会导致类型错误或运行时错误。只会导致不良的收敛。特别是你刚入门,碰到这些问题会非常令人沮丧!但经验丰富的神经网络训练者能够系统地克服这些困难,尽管有许多看似模棱两可的错误信息:

性能错误:你的神经网络没有训练好(Performance Error: your neural net did not train well.)。

对于门外汉来说,这条错误信息令人畏惧。但是对经验丰富的人来说,这是一个巨大的错误。它意味着样板代码不能正常工作,是时候深入代码调试了!

如何处理NaN

到目前为止,我的学生提出的最常见的一个问题就是,“我为什么会得到NaN错误。”有时,这问题有复杂的原因。但多数情况下,NaN错误在前100次迭代中出现,原因很简单:你的学习率过高了。当学习率非常高的时候,就会在前100次迭代的时候出现NaN错误。用因子为3来降低学习率,直到前100次迭代不再出现NaN错误。这么做一旦有效,你就有了一个非常好的学习率作为开端。根据我的经验,最好的学习率是你得到NaN错误的范围的一到十分之一。

如果你在100次迭代之后碰到了NaN错误,又有两种常见原因。

  1. 如果你使用的是RNN,确保你使用了梯度下降,并对梯度使用L2正则化。RNN似乎在训练早期会产生梯度,10%或更少的批次有学习峰值,此时的梯度幅值是相当高的。没有对梯度削减,这些峰值会产生NaN。
  2. 如果写的是自定义的网络层,那么很有可能因为除以0而引发NaN。另一个众所周知会产生Nan错误的层是Softmax层。Softmax计算包括分子分母的exp(x)操作,它可以用无穷大除以无穷大,会产生NaN。确保你使用了稳定的Softmax实现。

神经网络学习不到任何东西怎么办

一旦你没有了NaN错误,那么你的神经网络就可以在上千次迭代中平稳运行,而且不会在前几百次迭代后减少训练损失。当你第一次构建代码库的时候,最好别使用2000次迭代。这并不是因为所有的网络可以从低于2000次迭代开始学习。相反,从开头开始编码网络很可能出现bug,在达到高迭代次数之前,你会想要过早进行调试。现在的目的是一次又一次地缩小问题范围,直到你得到了一个在2000次迭代以下训练出来的网络。幸运地是,有两种方式来降低复杂性。

  1. 将训练集大小减小到10个实例。在几百次的迭代中,在这10个实例上,神经网络通常会出现过度拟合的情况。许多编码错误不会导致过拟合的出现。如果你的网络在10个实例的训练集上没有出现过度拟合,那么确保你使用的数据挂上了正确的标签。将批次大小减小到1来检查批次计算错误。在代码中添加打印语句确保输出与你期望的一致。通常情况下,你可以通过上面介绍的纯粹蛮力来找出错误。一旦网络可以在10个实例上训练,你可以试着让它在100个实例上训练。如果这种方式运行正常,但效果不是很好,你可以试试下面的方法。

  2. 解决你感兴趣的最简单的问题。如果你想翻译句子,首先可以建立一个针对特定语言的语言模型。如果你完成了,那么试着在给出3个词语的情况下预测翻译出来的第一个词。如果你想检测图像中的物体,那么在训练回归网络之前,你可以对图像中物体数目进行分类。在网络能够解决的棘手问题和使用最少的时间让代码得到合适的数据之间需要权衡。这个时候就要发挥你的创造能力了。

将神经网络运用于其他新场景的技巧是合理使用上面介绍的两个步骤。这是一种协调机制,并且效果不错。首先,你表明这个神经网络至少可以记住几个例子。然后这个神经网络可以泛化到更简单问题的验证集中。你慢慢在取得稳步进展时提升难度。这并没有高手第一次使用的Karpathy风格那么有趣,但至少它起作用。有时候你会碰到棘手的问题,你会发现它在2000次迭代中不会继续学习了。那很棒!但它的迭代次数很少会是这个问题之前复杂度下迭代次数的10倍。如果你发现是这种情况,尝试搜索中等水平的复杂度。

调整超参数

现在你的网络可以学习东西了,你可能会得意忘形。你还可能发现你训练的网络并不能够解决大多数复杂的问题。超参数调整就是解决问题的关键。有些人直接下载一个CNN的包然后在他们的数据集上运行,然后告诉你说使用超参数调整并没有带来什么不同。这是因为它们使用已经存在的架构来解决已经存在的问题。如果你要解决的问题需要新的架构呢,通过超参数调整来得到良好的设置就是必须的了。你最好确保针对你要解决的问题阅读了超参数教程,不过我还是会在下面列出一些基本思想。

  • 可视化是关键。不要怕在训练过程中花时间编写自定义可视化工具。如果你的可视化方法效果不行,那么考虑换另一种方法。
  • 权重初始化很重要。一般情况下,较大的初始化权重是个不错的选择,但是太大又会导致NaN。因此权重的初始化需要与学习率一同调整。
  • 确保权重看起来“健康”。要了解这是什么意思,我建议在IPython的notebook中查看现有网络的权重值。花些时间来观察在诸如ImageNet或Penn Tree Bank这些标准的数据集上训练的成熟的网络中成分的权重的直方图应该是什么样的。
  • 神经网络的w.r.t.输入不是不变的,特别是在使用SGD而不是其他方法训练的时候,因为SGD不是尺度不变的方法。花时间用与扩展其他方面的方式来扩展输入数据和输出标签。
  • 在训练过程中降低学习速率几乎总会给你带来提升。最好的衰减策略通常是:在k次迭代后,每n次迭代就用学习率除以1.5,k>n。
  • 使用超参数配置文件,虽然把超参数放到代码中也行,但是如果你想试试不同的值那么会比较麻烦。我把参数放在一个JSON文件中,使用一条命令导入,参见https://github.com/Russell91/tensorbox,确切的格式不重要。不要轻易重构代码,因为重新加载超参数比较麻烦!重构会引入bug,它们将会延长训练周期,并且可以在你得到一个你喜欢的网络前避免。
  • 如果你负担得起,随机化你的超参数搜索。随机搜索能生成你意想不到的超参数组合,并且一旦你了解某个超参数会产生的影响,随机搜索减少你许多工作。

结论

调试神经网络比传统的程序更费劲,因为大部分错误发生在整个网络的单一维度上。然而,二分查找仍然是你的朋友。通过改变问题的难度使用少量的训练样例的交替,你能快速解决最初的bug。超参数调整和长时间耐心等待可以解决余下的问题。


(以下内容来源于http://m.blog.csdn.net/article/details?id=50999918)

调参是个头疼的事情,Yann LeCun、Yoshua Bengio和Geoffrey Hinton这些大牛为什么能够跳出各种牛逼的网络?
下面一些推荐的书和文章:调参资料总结

Neural Network: Trick of the Trade Neural Networks: Tricks of the Trade

Practical Recommendations for Gradient-based Training of Deep Architectures arxiv.org/abs/1206.5533

神经网络训练中的Tricks之高效BP(反向传播算法)翻译文章。神经网络训练中的Tricks之高效BP(反向传播算法),来自与于《Neural Networks: Tricks of the Trade》一书第二版中的第一章 Efficient BackProp 的部分小节。

Deep Learning for Vision: Tricks of the TradeMarc’Aurelio Ranzato 在 CVPR 上 的 presentation slides/talk(Youtube 等地方可以搜到)。caffe 作者之一贾扬清推荐。涉及到了许多 DL 的调参技巧(在 slides 比较靠后的地方)

Optimizing RNN performance百度 Silicon Valley AI Lab 的分享,现在主要是 GEMM 的性能优化,以后还会有并行 GPU,GRU 和 LSTM 的实现技巧等……

Must Know Tips/Tricks in Deep Neural Networks来自 NJU LAMDA 实验室的 Xiu-Shen Wei 的总结,主要集中于 CNN,包括各种数据处理上可能带来的性能和表现的差异。图表丰富,有理有据。

训练深度神经网络的时候需要注意的一些小技巧这篇是综合翻译,没给出都从哪节选的。我收集的英文版在下面:

Training Tricks from Deeplearning4jdeeplearning4j 的 googlegroups 也很推荐。这篇其实干货不多,但是也有一些了。包括对于训练的理解,并不全是干货般的总结。

Suggestions for DL from Llya SutskeveHinton 亲传弟子介绍深度学习的实际 tricks,包括data, preprocessing, minibatches, gradient normalization, learning rate, weight initialization, data augmentation, dropout和ensemble。

Efficient Training Strategies for Deep Neural Network Language Models讨论了如何设置 batch-size, initial learning rate, network initialization,但最有趣的结论应该是:普通的 deep feed-forward architecture比recurrent NN 在 model long distance dependency 效果和效率都更好。

Neural Networks Best PracticeUber 的 data scientist 写的。比如: Rectifier is becoming popular as an activation function. However, I find its theory dubious and my experiments have not shown that it is always better. That said, I’m experimenting with new activation functions. (Little trivia: I’m borrowing many ideas from my graduate work in computational wave propagation.)

How transferable are features in deep neural networks?也是争议比较大的一篇文章,finetuning 有一定帮助,但是不够细致。

Dark Knowledge from Hinton有心人整理的 Hinton 提到的 Dark Knowledge 的一些资源。

Stochastic Gradient Descent TricksL eon Bottou 写的 Stochastic Gradient Descent Tricks 挺好,做工程也要做的漂亮。

Advice for applying Machine Learning主要集中在如何观察数据来选择方法。

How to Debug Learning Algorithm for Regression Model主要都是讲回归中遇到的各种“预期不符”的结果。配合 ESL 第二章和第三章内容看效果加成。

Large-scale L-BFGS using MapReduceNIPS’14 的论文,简单并行化 LBFGS里面的双循环(最耗时,计算量巨大)。

特征工程选择系列特征工程系列文章:Part1.单变量选取 Part2.线性模型和正则化 Part3.随机森林 Part4.稳定性选择法、递归特征排除法(RFE)及综合比较。有 Python 代码。

机器学习代码心得之有监督学习的模块 机器学习代码心得之迭代器和流水处理新一代大神微博@陈天奇怪 的系列文章,有兴趣的直接顺着看吧。

STOCHASTIC GRADIENT BOOSTING: CHOOSING THE BEST NUMBER OF ITERATIONSKaggle 达人 YANIR SEROUSSI 告诉你如何选择 Stochastic Gradient Boosting 的训练最佳 iteration 超参数。不过我比较存疑,因为如果条件允许,当然迭代的越多越好……

Large-Scale High-Precision Topic Modeling on TwitterTwitter 高级研究员的 KDD’14论文。有不少实用技巧,比如短文本特征,LR结果概率化修正,正样本抽样,PU学习后负样本选取。

0 0