一位ML工程师构建深度神经网络的实用技巧

简介:

通用技巧

有些技巧对你来说可能就是明摆着的事,但在某些时候可能却并非如此,也可能存在不适用的情况,甚至对你的特定任务来说,可能不是一个好的技巧,所以使用时需要务必要谨慎!

使用 ADAM 优化器

确实很有效。与更传统的优化器相比,如 Vanilla 梯度下降法,我们更喜欢用ADAM优化器。用 TensorFlow 时要注意:如果保存和恢复模型权重,请记住在设置完AdamOptimizer 后设置 Saver,因为 ADAM 也有需要恢复的状态(即每个权重的学习率)。

ReLU 是最好的非线性(激活函数)

就好比 Sublime 是最好的文本编辑器一样。ReLU 快速、简单,而且,令人惊讶的是,它们工作时,不会发生梯度递减的情况。虽然 sigmoid 是常见的激活函数之一,但它并不能很好地在 DNN 进行传播梯度。

不要在输出层使用激活函数

这应该是显而易见的道理,但如果使用共享函数构建每个层,那就很容易犯这样的错误:所以请确保在输出层不要使用激活函数。

请在每一个层添加一个偏差

这是 ML 的入门知识了:偏差本质上就是将平面转换到最佳拟合位置。在 y=mx+b 中,b 是偏差,允许曲线上下移动到“最佳拟合”位置。

使用方差缩放(variance-scaled)初始化

在 Tensorflow 中,这看起来像tf.reemaner.variance_scaling_initializer()。根据我们的经验,这比常规的高斯函数、截尾正态分布(truncated normal)和 Xavier 能更好地泛化/缩放。

粗略地说,方差缩放初始化器根据每层的输入或输出数量(TensorFlow中的默认值是输入数量)调整初始随机权重的方差,从而有助于信号更深入地传播到网络中,而无须额外的裁剪或批量归一化(batch normalization)。Xavier 与此相似,只是各层的方差几乎相同;但是不同层形状变化很大的网络(在卷积网络中很常见)可能不能很好地处理每层中的相同方差。

归一化输入数据

对于训练,减去数据集的均值,然后除以它的标准差。在每个方向的权重越少,你的网络就越容易学习。保持输入数据以均值为中心且方差恒定有助于实现这一点。你还必须对每个测试输入执行相同的规范化,因此请确保你的训练集与真实数据相似。

以合理保留其动态范围的方式缩放输入数据。这与归一化有关,但应该在归一化之前就进行。例如,真实世界范围为 [0,140000000] 的数据 x 通常可以用 tanh(x) 或 tanh(x/C) 来控制,其中 C 是一些常数,它可以拉伸曲线,以适应 tanh 函数缓坡部分的动态范围内的更多输入范围。特别是在输入数据在一端或两端可能不受限制的情况下,神经网络将在(0,1)之间学习得更好。

一般不用学习率衰减

学习率衰减在 SGD 中更为常见,但 ADAM 很自然地处理了这个问题。如果你真的想把每一分表现都挤出去:在训练结束时短时间内降低学习率;你可能会看到突然的、非常小的误差下降,然后它会再次变平。

如果你的卷积层有 64 或 128 个过滤器,那就足够了。特别是一个对于深度网络而言。比如,128 个真的就已经很多了。如果你已经有了大量的过滤器,那么再添加更多的过滤器未必会进一步提高性能。

池化用于平移不变性

池化本质上就是让网络学习图像“那部分”的“总体思路”。例如,最大池化可以帮助卷积网络对图像中的特征的平移、旋转和缩放变得更加健壮。

调试神经网络

如果你的网络没能很好地进行学习(指在训练过程中损失/准确率没有收敛,或者没有得到预期的结果),那么可以试试以下的技巧:

过拟合

如果你的网络没有学习,那么首先要做的第一件事就是对训练点进行过拟合。准确率基本上应为 100% 或 99.99%,或误差接近 0。如果你的神经网络不能对单个数据点进行过拟合,那么体系架构就可能有严重的问题,但这可能是微妙的。如果你可以对一个数据点进行过拟合,但是对较大的集合进行训练仍然无法收敛,请尝试以下建议:

降低学习率

你的网络学习就会变得更慢一些,但是它可能会找到以前无法进入的最小化的方式,因为它的步长太大了。

提高学习率

这样做将会加快训练,有助于收紧反馈,这意味着无论你的网络是否正常工作,你都会很快地知道你的网络是否有效。虽然网络应该更快地收敛,但其结果可能不会很好,而且“收敛”实际上可能会跳来跳去。(对于 ADAM 优化器,我们发现在很多经历中,学习率大约为 0.001 时,表现很不错。)

减少批量处理规模

将批处理大小减小到 1,可以为你提供与权重更新相关的更细粒度的反馈,你应该使用TensorBoard(或其他一些调试/可视化工具)展示出来。

删除批归一化层

随着批处理大小减少到 1,这样做会暴露出梯度消失或梯度爆炸的问题。我们曾有过一个网络,在好几周都没有收敛,当我们删除了批归一化层之后,我们才意识到第二次迭代时输出都是 NaN。就像是创可贴上的吸水垫,它也有它可以发挥效果的地方,但前提是你知道网络没有 Bug。

增加批量处理的规模

一个更大的批处理规模,如果可以的话,整个训练集减少梯度更新中的方差,使每个迭代更准确。换句话说,权重更新将朝着正确的方向发展。但是!它的可用性和物理内存限制都有一个有效的上限。通常,我们发现这个建议不如上述两个建议有用,可以将批处理规模减少到1并删除批归一化层。

检查你的重构

大幅度的矩阵重构(如改变图像的X、Y 维度)会破坏空间局部性,使网络更难学习,因为它也必须学会重塑。(自然特征变得支离破碎。事实上,自然特征在空间上呈局部性,也是为什么卷积神经网络能如此有效的原因!)如果使用多个图像/通道进行重塑,请特别小心;使用 numpi.stack()进行适当的对齐操作。

仔细检查你的损失函数

如果使用一个复杂的函数,请尝试将其简化为 L1 或 L2。我们发现L1对异常值不那么敏感,在发出噪声的批或训练点时,不会做出太大的调整。

如果可以的话,仔细检查你的可视化。你的可视化库(matplotlib、OpenCV等)是调整值的比例呢,还是它们进行裁剪?可考虑使用一种视觉上均匀的配色方案。

实战分析

为了使上面所描述的过程更容易让读者理解,我们这儿有一些用于描述我们构建的卷积神经网络的真实回归实验的损失图(通过TesnorBoard)。

起初,这个网络根本没有学习:

c8fa26792f0500fd25b98b3bf5313f36ab0b8e6e

我们试图裁剪这些值,以防止它们超出界限:

5dc764303178282301e8d13fb33d4063c29e4802

嗯。看看不平滑的值有多疯狂啊!学习率是不是太高了?我们试着在一个输入数据上降低学习率并进行训练:

7c95144bbc81b4b8c1277ae55eb5a81ad3e84971

你可以看到学习率的前几个变化发生的位置(大约在 300 步和 3000 步)。显然,我们衰减得太快了。所以,给它更多的衰减时间,它表现得会更好:

680412e1e2f59b53fbd4abb09daf80f445778180

你可以看到我们在 2000 步和 5000 步的时候衰减了。这样更好一些了,但还不够好,因为它没有趋于 0。

然后我们禁用了 LR 衰减,并尝试将值移动到更窄的范围内,而不是通过 tanh 输入。虽然这显然使误差值小于 1,但我们仍然不能对训练集进行过拟合:

fee354e43cce2cb0970039bb4e913aaf0f7fee44

这里我们发现,通过删除批归一化层,网络在一到两次迭代之后迅速输出 NaN。我们禁用了批归一化,并将初始化更改为方差缩放。这些改变了一切!我们能够对只有一两个输入的测试集进行过拟合了。当底部的图标裁剪Y轴时,初始误差值远高于 5,表明误差减少了近 4 个数量级:

5fc57d2101aa2c811e77e8ecd98488a9927cb1bf

上面的图表是非常平滑的,但是你可以看到它非常快地拟合了测试输入,随着时间的推移,整个训练集的损失降低到了 0.01 以下。这没有降低学习速度。然后我们将学习速率降低一个数量级后继续训练,得到更好的结果:

8f180510910d0ffccf82dbd30cd530b991ab2dbf

这些结果好得多了!但是,如果我们以几何方式降低学习率,而不是将训练分成两部分,会发生什么样的结果呢?

通过在每一步将学习率乘以 0.9995,结果就不那么好了:

827f753b241cc36e74b4598a90bdc2085b8f2027

大概是因为学习率衰减太快了吧。乘数为 0.999995 会表现的更好,但结果几乎相当于完全没有衰减。我们从这个特定的实验序列中得出结论,批归一化隐藏了由槽糕的初始化引起的爆炸梯度,并且 ADAM 优化器对学习率的衰减并没有什么特别的帮助,与批归一化一样,裁剪值只是掩盖了真正的问题。我们还通过 tanh 来控制高方差输入值。

我们希望,本文提到的这些基本技巧能够在你构建深度神经网络时有所帮助。通常,正式因为简单的事情才改变了这一切。


原文发布时间为:2018-09-19

本文来自云栖社区合作伙伴“CDA数据分析师”,了解相关信息可以关注“DA数据分析师”。

相关文章
|
7月前
|
前端开发 JavaScript 开发者
JavaScript:构建动态网络的引擎
JavaScript:构建动态网络的引擎
|
9月前
|
机器学习/深度学习 算法 量子技术
GQNN框架:让Python开发者轻松构建量子神经网络
为降低量子神经网络的研发门槛并提升其实用性,本文介绍一个名为GQNN(Generalized Quantum Neural Network)的Python开发框架。
227 4
GQNN框架:让Python开发者轻松构建量子神经网络
|
边缘计算 安全 算法
阿里云CDN:构建全球化智能加速网络的数字高速公路
阿里云CDN构建全球化智能加速网络,拥有2800多个边缘节点覆盖67个国家,实现毫秒级网络延迟。其三级节点拓扑结构与智能路由系统,结合流量预测模型,确保高命中率。全栈式加速技术包括QUIC协议优化和Brotli压缩算法,保障安全与性能。五层防御机制有效抵御攻击,行业解决方案涵盖视频、物联网及游戏等领域,支持新兴AR/VR与元宇宙需求,持续推动数字内容分发技术边界。
811 13
|
7月前
|
人工智能 监控 数据可视化
如何破解AI推理延迟难题:构建敏捷多云算力网络
本文探讨了AI企业在突破算力瓶颈后,如何构建高效、稳定的网络架构以支撑AI产品化落地。文章分析了典型AI IT架构的四个层次——流量接入层、调度决策层、推理服务层和训练算力层,并深入解析了AI架构对网络提出的三大核心挑战:跨云互联、逻辑隔离与业务识别、网络可视化与QoS控制。最终提出了一站式网络解决方案,助力AI企业实现多云调度、业务融合承载与精细化流量管理,推动AI服务高效、稳定交付。
|
7月前
|
机器学习/深度学习 算法 搜索推荐
从零开始构建图注意力网络:GAT算法原理与数值实现详解
本文详细解析了图注意力网络(GAT)的算法原理和实现过程。GAT通过引入注意力机制解决了图卷积网络(GCN)中所有邻居节点贡献相等的局限性,让模型能够自动学习不同邻居的重要性权重。
1369 0
从零开始构建图注意力网络:GAT算法原理与数值实现详解
|
6月前
|
机器学习/深度学习 分布式计算 Java
Java与图神经网络:构建企业级知识图谱与智能推理系统
图神经网络(GNN)作为处理非欧几里得数据的前沿技术,正成为企业知识管理和智能推理的核心引擎。本文深入探讨如何在Java生态中构建基于GNN的知识图谱系统,涵盖从图数据建模、GNN模型集成、分布式图计算到实时推理的全流程。通过具体的代码实现和架构设计,展示如何将先进的图神经网络技术融入传统Java企业应用,为构建下一代智能决策系统提供完整解决方案。
594 0
|
9月前
|
监控 安全 Go
使用Go语言构建网络IP层安全防护
在Go语言中构建网络IP层安全防护是一项需求明确的任务,考虑到高性能、并发和跨平台的优势,Go是构建此类安全系统的合适选择。通过紧密遵循上述步骤并结合最佳实践,可以构建一个强大的网络防护系统,以保障数字环境的安全完整。
202 12
|
10月前
|
JSON 编解码 API
Go语言网络编程:使用 net/http 构建 RESTful API
本章介绍如何使用 Go 语言的 `net/http` 标准库构建 RESTful API。内容涵盖 RESTful API 的基本概念及规范,包括 GET、POST、PUT 和 DELETE 方法的实现。通过定义用户数据结构和模拟数据库,逐步实现获取用户列表、创建用户、更新用户、删除用户的 HTTP 路由处理函数。同时提供辅助函数用于路径参数解析,并展示如何设置路由器启动服务。最后通过 curl 或 Postman 测试接口功能。章节总结了路由分发、JSON 编解码、方法区分、并发安全管理和路径参数解析等关键点,为更复杂需求推荐第三方框架如 Gin、Echo 和 Chi。
|
人工智能 供应链 安全
2025 年网络法律论坛 | 应对安全风险,构建韧性举措
2025年查尔斯顿网络法律论坛汇聚法律、网络安全与保险行业专家,探讨全球威胁态势、人工智能应用及监管变化等议题。主旨演讲揭示非对称威胁与供应链漏洞,强调透明度和协作的重要性。小组讨论聚焦AI合理使用、监管热点及网络保险现状,提出主动防御与数据共享策略。论坛呼吁跨领域合作,应对快速演变的网络安全挑战,构建更具韧性的防御体系。
300 1
2025 年网络法律论坛 | 应对安全风险,构建韧性举措
|
安全 自动驾驶 物联网
新四化驱动,如何构建智能汽车的“全场景”可进化互联网络?
在智能化、电动化、网联化、共享化的时代浪潮中,汽车正从单纯的 “机械产品” 进化为先进的 “移动智能终端”。在软件定义汽车(SDV)的崭新时代,每一次 OTA 升级的顺利完成、每一秒自动驾驶的精准决策、每一帧车载娱乐交互的流畅呈现,都离不开一张实时响应、全域覆盖、安全可靠的广域网络。

热门文章

最新文章

下一篇
开通oss服务