如何从零开始构建深度学习项目?这里有一份详细的教程(从零开始学程序)

在学习了关于深度学习的理论课程后,很多人会有兴趣尝试建立一个属于自己的项目。本文将从第一步开始,告诉你如何解决项目开发中遇到的各种问题。
本文由六个部分组成,涵盖了深度学习项目的整个过程。我们将用一个自动卡通上色项目来说明深度学习的设计、程序调试和参数调整过程。
这篇文章的题目是“如何开始一个深度学习项目?”,分为以下六个部分:
第1部分:启动深度学习项目。
第二部分:创建深度学习数据集。
第三部分:设计深度模型。
第四部分:可视化深度网络模型及度量指标。
第五部分:深度学习网络中的调试。
第六部分:提高深度学习模型的性能和网络调优。
第1部分:启动深度学习项目。
应该选择什么样的项目?
很多人工智能项目其实没那么严重,做起来很好玩。2017年初,我开始了一个给日本漫画上色的项目,作为我对生成对抗网络(GAN)研究的一部分。这个问题很难解决,但是很吸引人,尤其是对于我这种不会画画的人!找项目的时候,不要局限于增量改进。做出一个适销对路的产品或者创造一个学习速度更快质量更高的新模式。
调试深度网络(DN)非常棘手。
训练深度学习模型需要数百万次迭代,所以发现bug的过程非常困难,容易崩溃。所以要从简单的地方入手,循序渐进。比如模型的优化(比如正则化)总是可以在代码调试完成之后进行。此外,我们还需要经常可视化预测结果和模型度量,需要让模型先运行,这样才有可以回归的基线。我们最好不要拘泥于一个大的模型,尽量把所有的模块都做对。
测量和学习
宏大的项目计划可能会导致悲剧性的失败。大部分个人项目的第一个版本会持续两到四个月,时间很短,因为研究、调试、实验都需要大量的时间。一般情况下,我们会安排这些复杂的实验通宵运行,到第二天早上,我们希望获得足够的信息来采取下一步行动。在早期,这些实验不应该超过12小时,这是一个很好的经验法则。为了做到这一点,我们将卡通着色项目的范围缩小到单个动画角色的着色。此外,我们需要设计许多测试,这样我们就可以在实验中使用它们来分析模型的缺点。一般来说,这些测试不应该计划得太远。我们需要快速测量和学习,并为下一个设计提供足够的反馈。
研究和产品
当我们在2017年春天开始讨论漫画着色项目时,凯文弗兰斯(Kevin Frans)有一个Deepcolor项目,与甘(GAN)一起为漫画添加颜色提示。
在确定目标的时候,你会努力保证项目完成后依然有意义。GAN模型相当复杂,2017年初还没有达到嵌入式产品所需的质量水平。但是,如果把应用范围缩小到产品可以熟练处理的程度,就可以把质量提高到商业水平。所以,无论你启动什么样的DL项目,都要在模型泛化、容量和精度之间保持良好的平衡。
费用
你必须使用GPU来训练实际模型。比CPU快20到100倍。价格最低的亚马逊GPU p2.xlarge site实例价格为7.50美元/天,而8核GPU的价格高达75美元/天。在我们的卡通着色项目中,一些实验需要两天以上的时间,因此平均每周的成本至少为150美元。至于更快的AWS实例,它的成本可能高达1500美元/周。我们可以买单机,不用云计算。2018年2月,搭载英伟达GeForce GTX 1080 Ti的台式机售价约为2200美元。在训练微调后的VGG模型时,它比P2的例子快5倍左右。
时线
我们把开发分为四个阶段,后三个阶段是多次迭代进行的。
项目研究
模型设计
和调试。
实验和参数调整
项目研究
我们将首先研究现有的产品,探索它们的弱点。许多GAN类型的解决方案使用空间颜色线索,图案有点不清楚,有时会出现混色。我们为我们的项目设定了两个月的时间框架,其中有两个优先事项:在没有提示的情况下生成颜色和提高颜色保真度。我们的目标是:
给单个动画角色上的灰色卡通上色,不要使用空间颜色提示。
站在巨人的肩膀上
接下来,我们需要了解相关的研究和开源项目。很多人在开始实践之前,至少要阅读几十篇论文和项目。比如我们在深入研究GAN的时候,发现有十几种新的GAN模型,比如3360Dragan,cGAN,LSGAN等。读研究论文可能很痛苦,但很有意义。
深度学习(DL)代码简洁,但很难检查缺陷,很多研究论文经常遗漏实现细节。很多项目都是从开源实现开始的,解决了类似的问题,所以我们可以搜索更多的开源项目。所以我们在GitHub上查看了不同GAN变种的代码实现,测试了几次。
第二部分:创建深度学习数据集。
深度学习项目的成功取决于数据集的质量。在本文的第二部分,我们将讨论创建高质量训练数据集的核心问题。
开放学术数据集
对于研究项目,您可以搜索已建立的公共数据集。这些数据集可以提供更整洁的样本和基线模型性能。如果您有多个公开可用的数据集,请选择与您的问题最相关且质量最好的样本。
自定义数据集
对于实际问题,我们需要来自问题领域的样本。首先尝试找到公共数据集。关于创建高质量定制数据集的研究仍然缺乏。如果没有可用数据,请搜索可以抓取数据的位置。这个位置通常有很多参考,但数据质量通常较低,需要投入大量精力进行排序。在获取样本之前,花时间评估所有选项,并选择最相关的选项。
高质量的数据集应包括以下特征:
类别平衡
充足的数据
并且高质量信息包含在数据标记中。
并且数据标记误差非常小。
和你的问题有关。
不要一次抓取所有数据。我们经常借助标签和分类抓取网站样本,从而获取与我们问题相关的数据。最好的爬取方法是在你的模型中训练测试少量样本,根据经验教训改进爬取方法。
清理抓取的数据非常重要,否则再好的模型设计也无法达到媲美人类水平的性能。Danbooru和Safebooru是两个非常受欢迎的动漫角色来源,但一些深度学习应用更喜欢Getchu来获得更高质量的图纸。我们可以使用一组标签从Safebooru下载图像,并直观地检查样本和运行测试来分析错误(表现不佳的样本)。
模型训练和视觉评估都提供了进一步的信息,以完善我们的标签选择。随着迭代的继续,我们会了解更多,并逐渐积累样本。我们还需要使用分类器进一步过滤与问题无关的样本,比如去掉所有字符过小的图像。相对于学术数据集,小项目收集的样本很少,适当的时候可以应用迁移学习。
下图左图由PaintsChainer提供,右图由最终模型上色:
我们决定使用一些训练样本来测试算法。结果并不意外,颜色少了,款式也不对。
经过一段时间的模型训练,我们知道什么样的画图表现不好。不出所料,复杂的图画更难上色。
由此可见,选择一个好的样本是非常重要的。作为一个产品,PaintsChainer非常明智的专注于自己擅长的线条类型。这次用的是从网上挑选的干净线稿,结果又一次让人惊喜。
以下是一些教训:数据没有好坏之分,只是有些数据不能满足你的需求。另外,随着样本类别的增加,训练和保持输出质量会变得更加困难,删除无关数据可以得到更好的模型。
在开发初期,我们意识到有些图纸有太多错综复杂的结构。在没有显著增加模型容量的情况下,这些图纸在训练中的价值不大,最好不要使用,否则只会影响训练效率。
焦点评论
尽可能使用公共数据集;
寻找能获得高质量多样样本的最佳网站;
分析错误,过滤掉与实际问题无关的样本;
迭代地创建你的样本;
平衡每个类别的样本数量;
培训前组织样本;
收集足够的样本。如果没有足够的样本,应用迁移学习。
第三部分:深度学习设计。
第三部分介绍了一些高级的深度学习策略。接下来,我们将详细介绍最常见的设计选择,这可能需要一些基本的DL背景。
简单灵活
最初的设计应该简单小巧。在学习阶段,人的脑子里会充斥着很多很酷的想法。我们倾向于一次编码所有的细节。但这是不现实的,一开始就想超越顶尖成绩也是不现实的。先少做网络层和定制,再做一些必要的超参数微调方案。这些都需要验证损失函数一直在递减,不要一开始就在更大的模型上浪费时间。
经过短暂的调试,我们的模型在5000次迭代后产生了简单的结果。但至少模特身上的颜色是限定在固定区域的,肤色也有些暴露。
上面的结果给了我们关于模型是否开始着色的有价值的反馈。所以不要从一个大的模型开始,否则你会花很多时间去调试和训练模型。
优先级和增量设计
首先,为了创建一个简单的设计,我们需要选择优先级。把复杂的问题分解成小问题,逐步解决。深度学习的正确策略是快速实现所学。在跳到无提示模型之前,让我们使用带有空间颜色提示的模型。不要一步跳到“无建议”的模型设计。例如,如果我们首先删除建议中的空间信息,颜色质量将急剧下降,因此我们改变我们的优先级,并在做下一步之前细化我们的模型。在设计模型的过程中,我们会遇到很多惊喜。与其制定一个需要不断变化的长期计划,不如制定一个优先级驱动的计划。使用更短和更小的设计迭代来确保项目的可管理性。
避免随意改进。
首先,分析自己模型的弱点,而不是随意改进,比如使用双向LSTM或PReLU。我们需要根据视觉模型误差(性能差的场景)和性能参数来确定模型问题。随意改进会适得其反,会成比例地增加培训成本,收效甚微。
限制
我们对网络设计施加限制,以确保更有效的培训。构建深度学习不是简单的把网络层堆在一起。添加好的约束可以使学习更有效或更智能。比如关注机制的应用,可以让网络知道关注哪里。在变分自编码器中,我们训练隐藏因子服从正态分布。在设计中,我们应用去噪方法,通过置零去除大量空间颜色所隐含的分数。具有讽刺意味的是,这使得模型更容易学习和推广。
设计细则
文章的下一部分将讨论深度学习项目中会遇到的一些常见的设计选择。
深度学习软件框架
自2015年11月Google发布TensorFlow以来,短短6个月的时间,它已经成为最受欢迎的深度学习框架。虽然短期内似乎很难有竞争对手,但一年后脸书发布了PyTorch,引起了研究界的极大关注。到2018年,已经有大量深度学习平台可供选择,包括TensorFlow、PyTorch、Caffe、Caffe2、MXNet、CNTK等。
一些研究人员转向PyTorch的一个主要原因是:PyTorch的设计关注最终用户,API简单直观。错误可以直观的理解,API文档非常完整。PyTorch中的预训练模型、数据预处理和加载公共数据集等功能非常受欢迎。
TensorFlow也很棒,但是到目前为止它采用了自底向上的方法,这使得它变得极其复杂。TensorFlow的API比较冗长,Debug不一样。构建深度网络的API模型大概有十几个。
截至2018年2月,TensorFlow依然独占鳌头。开发者社区仍然是最大的。这是一个非常重要的因素。如果你想用多台机器训练模型或者在手机上部署推理引擎,TensorFlow是唯一的选择。但是,如果其他平台变得更加专注于最终用户,我们可以预见,将有更多的小项目到中间项目。
随着TensorFlow的发展,有很多API可供选择来构建深度网络。最高级别的API是提供隐式集成的评估器,而TensorBoard提供性能评估。最底层的API非常冗长,在很多模块中都有。现在用wrapper API合并成tf.layers、tf.metrics、tf.losses模块,这样更容易建立深度网络层。
对于想要更直观的API的研究人员,还有Keras、TFLearn、TF-Slim等。可供选择,可以直接在TensorFlow上使用。我的建议是选择一个具有所需预训练模型和工具(下载数据集)的框架。除此之外,学术界使用Keras API进行原型设计也是相当流行的。
移动
不要做重复性的工作。很多深度学习软件平台都有预训练模型,比如VGG19,ResNet,Inception v3。从零开始训练需要很多时间。正如2014年VGG论文所说,“VGG模型是用4个NVIDIA Titan Black GPU训练的,按照架构训练一个网络需要2-3周。」
很多预训练模型可以用来解决深度学习问题。例如,我们使用预先训练的VGG模型来提取图像特征,并将这些特征反馈给LSTM模型来生成描述。许多预训练模型都是用ImageNet数据集训练的。如果您的目标数据与ImageNet相差不大,我们将修复大部分模型参数,只重新训练最后几个完全连接的层。否则,我们将使用训练数据集对整个网络进行端到端的重新训练。但是,在这两种情况下,由于模型已经过预训练,重新训练所需的迭代次数将大大减少。由于训练时间短,即使训练数据集不够大,也能避免过拟合。这种迁移学习在所有学科中都是有效的,比如用预先训练好的英文模型训练中文模型。
但这种迁移学习只适用于需要复杂模型提取特征的问题。在我们的项目中,我们的例子不同于ImageNet,我们需要端到端地重新训练模型。但是,当我们只需要一个相对简单的潜在因子(颜色)时,来自VGG19的训练复杂度太高。因此,我们决定建立一个新的更简单的CNN特征提取模型。
价值函数
不是所有的代价函数都是等价的,而且会影响模型的训练难度。有些成本函数相当标准,但有些问题领域需要仔细考虑。
分类:交叉熵,折叠损失函数(SVM)
回归:均方差(MSE)
对象检测或分割:交集比率(IoU)
优化:KL发散
单词嵌入:噪声对比度估计(NCE)
词:余弦相似度
理论分析上看起来很好的代价函数,在实际中可能并不奏效。比如GAN中鉴频器网络的代价函数,就采用了一种更实际、更实验的方法,而不是一种理论分析上看起来很好的方法。在一些问题领域中,成本函数可以是猜测的一部分和实验的一部分,或者是几个成本函数的组合。我们的项目从标准的GAN成本函数开始。此外,我们还添加了使用MSE和其他正则化成本的重建成本。然而,如何找到一个更好的成本函数是我们项目中尚未解决的问题之一,我们相信它将对颜色保真度产生重大影响。
组件
好的度量有助于更好地比较和调整模型。特殊问题请查看Kaggle平台,该平台组织了很多DL比赛,并提供了详细的指标。不幸的是,在我们的项目中,你很难定义一个精确的公式来衡量艺术渲染的准确性。
正规化
L1正则化和L2正则化是常见的,但L2正则化在深度学习中更受欢迎。
L1正则化有什么优势?L1正则化可以产生更稀疏的参数,这有助于求解底层表示。因为每一个非零参数都会增加一个代价,所以L1更喜欢零参数而不是L2正则化,也就是说,它更喜欢零参数而不是L2正则化中的许多微小参数。L1正则化使得滤波器更干净,更容易解释,因此对于特征选择是一个很好的选择。对L1异常值的脆弱性也很低。如果数据不是太干净,运行效果会更好。然而,L2正则化仍然更受欢迎,因为解决方案可能更稳定。
梯度下降
始终密切监视梯度是否消失或爆炸。梯度下降的可能原因有很多,很难确认。不要跳到学习率调整或者让模型设计变化太快。小梯度可能仅由编程错误引起,例如输入数据的不正确缩放或所有权重初始化为零。
如果排除了其他可能的原因,当梯度爆炸时,将应用梯度截断(特别是对于NLP)。跳跃是缓解梯度下降问题的常用技术。在ResNet中,残差模块允许输入绕过当前层到达下一层,有效地增加了网络的深度。
嗡嗡声
缩放要素。通常我们以零为平均值将特征缩放到一定范围,比如[-1,1]。特征的不适当缩放是梯度爆炸或减小的最常见原因之一。有时,我们会计算训练数据的均值和方差,以使数据更接近正态分布。如果验证或测试数据被缩放,则应再次使用训练数据的平均值和方差。
批量标准化和层标准化
各层激活函数前节点输出的不平衡是梯度问题的另一个主要来源,因此有必要对CNN应用批量归一化(BN)。如果对输入数据进行适当的标准化(缩放),DN会学习得更快更好。在BN中,我们从每批训练数据中计算每个空间位置的均值和方差。比如批量是16,特征图的空间维度是10 X10。我们计算100个平均值和100个方差(每个位置一个)。每个位置的平均值是16个样本的相应位置平均值。我们使用平均值和方差来归一化每个位置的节点输出。BN提高了精度,缩短了训练时间。
然而,BN对RNN无效,因此我们需要使用图层归一化。在RNN,BN的均值和方差不适合重新归一化RNN单元的输出,这可能是由于RNN和共享参数的循环性质。在层归一化中,由当前样本的层输出计算的平均值和方差被输出以再次归一化。具有100个元素的图层仅使用当前输入的一个平均方差来重新归一化该图层。
拒绝传统社会的人
可以对图层应用Dropout以规范化模型。2015年批次常态化兴起后,退学热度下降。归一化使用平均值和标准差批量缩放节点输出。就像噪声一样,它会迫使图层更稳健地学习输入中的变量。批量归一化也有助于解决梯度下降的问题,所以逐渐取代了辍学。
结合辍学和L2正则化的好处是特定领域。通常,我们可以在调优过程中测试dropout,并收集经验数据来证明它的好处。
激活功能
ReLU是DL中最常用的非线性激活函数。如果学习率太高,许多节点的激活值可能为零。如果改变学习率没有帮助,我们可以尝试leaky ReLU或PReLU。在leaky ReLU中,当x ^ 0时,不输出0,而是有一个预定义的小的向下斜率(如0.01或由一个超级参数设置)。参数ReLU(PReLU)向前推一步。每个节点将有一个可训练的斜率。
分割数据集
为了测试实际性能,我们把数据分成三部分: 70%用于训练,20%用于验证,10%用于测试。确保每个数据集和每批训练样本中的样本被完全打乱。在训练过程中,我们使用训练数据集建立具有不同超级参数的模型。我们使用验证数据集来运行这些模型,并选择精确度最高的模型。但是为了安全起见,我们使用10%的测试数据进行最后的混淆检查。如果您的测试结果与验证结果大相径庭,您应该更充分地扰乱数据或收集更多数据。
基础
设置基线有助于我们比较模型和调试。例如,我们可以使用VGG19模型作为问题分类的基线。或者,我们可以先扩展一些已经建立的简单模型来解决我们的问题。这有助于我们更好地理解问题,并建立用于比较的性能基线。在我们的项目中,我们修改了已建立的GAN实施方案,并重新设计了发电网络作为基线。
检查点
我们定期保存模型的输出和测量结果,以供比较。有时,我们希望重现模型的结果或重新加载模型以进一步训练它。检查点允许我们保存模型,以便以后重新加载。但是,如果模型设计已经更改,则所有旧的检查点都无法加载。我们还使用Git标签来跟踪多个模型,并为特定的检查点重新加载正确的模型。我们的设计每个检查点占用4gb的空间。在云环境中工作时,应该相应地配置足够的存储。我们经常启动和终止亚马逊云实例,因此我们将所有文件存储在亚马逊EBS中,以便于重新连接。
自定义层
深度学习软件包中的内置层经过了更好的测试和优化。然而,如果您想要自定义图层,您需要:
具有非随机数据的前向和后向传播码的模测试:
将反向传播结果与简单梯度测试进行比较;
在分母上加少量或使用对数计算来避免NaN值。
使标准化
深度学习的挑战之一是可重复性。在调试过程中,如果初始模型参数在会话之间不断变化,则很难调试。因此,我们显式初始化了所有随机生成器的种子。我们在项目中初始化了python、NumPy和TensorFlow的种子。在微调过程中,我们关闭了种子初始化,以便为每次运行生成不同的模型。为了重现模型的结果,我们稍后将检查点并重新加载它。
【计算机】优化程序
Adam optimizer是深度学习中最受欢迎的优化器之一。它适用于许多类型的问题,包括具有稀疏或噪声梯度的模型。其简单的微调使得快速获得好的结果成为可能。事实上,默认的参数配置通常运行良好。Adam optimizer结合了AdaGrad和RMSProp的优点。Adam对每个参数使用相同的学习速率,并随着学习的进展独立地适应。Adam是一种基于动量的算法,利用了梯度的历史信息。因此,梯度下降可以更加平滑地运行,并且抑制了大梯度和大学习率导致的参数振荡问题。
Adam优化器调整
Adam有四个可配置的参数:
学习率(默认0.001);
:第一时刻估计的指数衰减率(默认为0.9);
:二阶矩估计的指数衰减率(默认为0.999),在稀疏梯度问题中应设置为接近1;
(默认值1e-8)是一个小值,用于避免被零除。
(动量)通过累积梯度的历史信息来平滑梯度下降。通常,对于早期阶段,默认设置已经很好了。否则,最有可能改变的参数应该是学习率。
摘要
以下是深度学习项目主要步骤的简要总结:
定义任务(对象检测、艺术线条着色)收集数据集(MS Coco,公共网站)搜索学术数据集和基线构建您自己的数据集(从Twitter、新闻、网站等)定义指标搜索已建立的指标清理和预处理数据选择特征并转换数据一键矢量、词汇包、光谱图等.分桶、对数标度、频谱图移除噪声或异常值移除无效和重复的数据缩放或白化数据分割数据集用于培训、验证和测试可视化数据验证数据集建立基线计算基线的指标分析改进区域的错误选择网络结构CNN、LSTM……实施深度网络代码调试和验证参数初始化计算损耗和指标 验证和总结结果分析错误添加层和节点优化超参数微调尝试我们的模型变体第4部分:可视化深度神经网络模型和指标
在对深度神经网络进行故障排除时,人们总是过快过早地得出结论。在我们知道如何排除故障之前,我们应该首先考虑要查找什么,然后花几个小时追踪故障。在这一部分,我们将讨论如何可视化深度学习模型和性能指标。
张量板
跟踪每一个动作,检查每一步的结果,这是非常重要的。借助TensorBoard等预置包,视觉模型和性能指标变得简单,奖励几乎同步。
数据可视化(输入、输出)
验证模型的输入和输出。在将数据输入模型之前,保存一些训练和验证样本以进行可视化验证。取消数据预处理。将像素值调整回[0,255]。检查多个批次,以确保我们没有重复同一批次的数据。下图是一些训练样本,右下是验证样本。
有时候,验证输入数据的直方图是很棒的。理想情况下,应该以0为中心,间隔在-1和1之间。如果特征处于不同的尺度,那么梯度将下降或爆炸(取决于学习速率)。
定期保存相应模型的输出,用于验证和误差分析。例如,验证输出中的颜色是否稍亮。
指数(损失准确度)
除了定期记录损失和准确性,我们还可以记录和绘制它们,以分析它们的长期趋势。下图是TensorBoard上显示的精度和交叉熵损失。
画一张损失图可以帮助我们调整学习速度。任何损失的长期增加都说明学习率过高。如果学习率低,学习速度就会变慢。
下面是另一个学习率过高的真实样本。我们可以看到损失函数突然上升(可能是梯度突然上升造成的)。
我们使用精确度图表来调整正则化因子。如果验证和训练的精度差距较大,则模型过拟合。为了减轻过拟合,我们需要增加正则化因子。
总结
体重偏差:我们密切监控体重和偏差。下图显示了不同训练迭代中第1层的权重和偏移。出现大(正/负)权重是不正常的。正态分布的权重表示训练过程顺利(但不一定)。
激活:为使梯度下降达到最佳性能,激活函数前节点的输出应呈正态分布。如果不是,那么我们可以对卷积层应用批量归一化,或者对RNN层应用归一化。我们还在激活该功能后监控无效节点(0激活)的数量。
梯度:我们监控每一层的梯度,以确定最严重的深度学习问题:梯度消失或爆炸。如果渐变从最右边的层到最左边的层快速下降,渐变就会消失。
这可能不是很常见:我们可视化了CNN过滤器。它识别由模型提取的特征的类型。如下图所示,前两个卷积图层正在检测边界和颜色。
对于CNN,我们可以看到特征图在学习什么。下图捕捉了特定图片中激活功能最高的9张图片(右侧)。它还使用去卷积网络从特征图(左)重建空间图像。
可视化和理解卷积网络,马修D泽勒等。
这种图像重建很少做。但是在世代模型中,我们经常改变一个潜在因素,而保持其他因素不变。它验证模型是否在智能学习。
胶囊之间的动态路由
第五部分:深度学习网络的调试。
深度学习的问题解决步骤
在早期的开发中,我们会同时遇到几个问题。如前所述,深度学习训练由数百万次迭代组成。很难发现bug,容易死机。从简单开始,逐渐改变。诸如正则化之类的模型优化可以在代码调试之后进行。以功能优先的方式检查模型:
将正则化因子设置为0;
无其他转正(包括退学);
使用默认设置的Adam优化器;
使用ReLU
没有数据增强;
不太深的网络层;
扩展输入数据,但不要做不必要的预处理;
不要在长时间的训练迭代或大批量上浪费时间。
用少量的训练数据对模型进行过度拟合,是在debug中进行深度学习的最好方法。如果损失值在数千次迭代中没有减少,则进一步调试代码。如果准确度超过了猜测的概念,你将获得第一个里程碑。然后对模型进行后续修改:添加网络层和定制;用完整的训练数据开始训练;正则化通过监控训练和验证数据集之间的精度差异来控制过拟合。
如果卡住了,就把所有的东西都扔掉,从一个更小的问题开始。
初始化超参数
很多超级参数更多的是和模型优化有关。关闭超参数或使用默认值。使用Adam优化器,快速高效,有很好的默认学习率。早期的问题主要来自于bug,而不是模型设计和微调。在进行微调之前,请仔细阅读以下清单。这些问题比较常见,容易查。如果损失没有减少,调整学习率。如果损失下降太慢,学习率会增加10。如果损失值上升或梯度爆炸,学习率减少10。重复此过程,直到损耗值逐渐减小。典型的学习率在1到1e-7之间。
核对表
数据:
并目视检查输入数据(在数据预处理之后,在馈入模型之前);
检查输入标签的准确性(数据扰动后);
不要一遍又一遍的喂同一批数据;
适当缩放的输入数据(通常可缩放到区间(-1,1)并且具有零平均值);
检查输出的范围(例如,在区间(-1,1)之间);
始终使用训练集的均值/方差来重新调整验证/测试集;
模型的所有输入数据具有相同的维度;
获得数据集的整体质量(是否有太多的离群值或坏样本)。
型号:
准确初始化模型参数,不要把所有权重都设置为0;
调试活动或渐变消失/爆炸网络层(从最右边到最左边);
调试;权重为0或过大的网络层;
并检验损失函数;
对于预训练模型,输入数据范围应与模型中使用的范围相匹配;
推理和测试中的退出应该总是被关闭。
重量初始化
将所有权重初始化为0是最常见的错误,深网学不到东西。根据高斯分布初始化权重重要性:
缩放和标准化
人们对缩放和规范化已经有了很好的理解,但这仍然是最被忽视的问题之一。如果输入特征和节点输出都被标准化,则训练模型将会更容易。如果做的不准确,损失值不会随着学习率下降。我们应该监控每层节点的输入特征和输出的直方图。适当放大。对于节点的输出,最完美的形态是零均值,数值不要太大(正或负)。如果不是,且该层存在梯度问题,则对卷积层进行批量归一化,对RNN单元进行层归一化。
损失函数
并检查损失函数的准确性。模型的损失值必须低于随机猜测值。例如,在10类分类问题中,随机猜测的交叉熵损失为-ln(1/10)。
分析误差
检查不良性能(错误)并加以改进,并将错误可视化。在我们的项目中,对于具有高度纠缠结构的图像,模型性能不好。例如,使用更小的过滤器添加更多的卷积图层来解决小要素。如有必要,增强数据或收集更多类似的样本,以更好地训练模型。在某些情况下,您可能希望删除这些示例,并将它们限制在更集中的模型中。
正则化微调
关闭正则化(使模型过度拟合),直到做出合理的预测。
一旦模型代码可以工作,下一个要调整的参数就是正则化因子。我们需要增加训练数据量,然后增加正则化来缩小训练和验证精度的差距。不要过度,因为我们想稍微过度拟合模型。密切监控数据和调整成本。在较长的时间尺度内,正则化损失不应该控制数据损失。如果大规模的正则化不能缩小两个准确率的差距,那么degug先正则化代码或者方法。
类似于学习率,我们以对数比例改变测试值,例如,在开始时改变1/10。请注意,每个正则化因子可能具有完全不同的数量级,我们可以重复调整这些参数。
多重损失函数
在第一种实现中,避免了多个数据丢失函数。每个损失函数的权重可能有不同的数量级,也需要一定的努力来调整。如果我们只有一个损失函数,我们只能关心学习率。
固定变量
当我们使用预训练模型时,我们可以固定特定层的模型参数,从而加快计算速度。一定要再次检查是否有固定变量的错误。
单元测试
正如很少提到的,我们应该对核心模块进行单元测试,这样当代码改变时,实现仍然是健壮的。如果它的参数是由随机函数初始化的,就不容易检查网络层的输出。此外,我们可以模拟输入数据并检查输出。对于每个模块(层),我们可以检查:
和训练输出的形状;
可训练变量的数量(不是参数的数量)。
尺寸不匹配
跟踪张量(矩阵)的形状,并将其存档在代码中。对于形状为[N,channel,W,H]的张量,如果W(宽度)和H(高度)的维数相同,那么它们交换代码时就不会有误差。因此,我们应该使用非对称形状进行代码单元测试。比如我们用[4,3]张量代替[4,4]进行测试。
第六部分:提高深度学习模型的性能和网络调优。
提高模型容量
为了提高模型的容量,我们可以逐步向深度网络(DN)添加层和节点。更深的层将输出更复杂的模型。我们还可以减小过滤器的尺寸。较小的滤波器(33或55)的性能通常比较大的滤波器好。
调优的过程强调实践而不是理论。我们逐渐添加层和节点,这可能会过度适应模型,因为我们可以将其正则化,然后将其降低。重复这个迭代过程,直到精度不再提高,不再值得训练,计算性能降低。
但是,GPU的内存是有限的。截至2018年初,高端显卡NVIDIA GeForce GTX 1080 TI的内存为11GB。两个仿射层之间隐藏节点的最大数量受内存大小的限制。
对于非常深的网络,梯度消失的问题非常严重。我们可以添加一个跳转连接(类似于ResNet中的剩余连接)来缓解这个问题。
模型数据集的设计变更
以下是提高性能的清单:
分析验证数据集中的错误(较差的预测结果);
激活监控功能。当激活函数不以零或非正态分布为中心时,考虑批量归一化或分层归一化;
监控无效节点的比例;
使用梯度截断(特别是在NLP任务中)控制梯度爆炸问题;
混洗数据集(手动或通过程序);
平衡数据集(每个类别有相似数量的样本)。
在激活该功能之前,我们应该密切监视激活直方图。如果它们的尺度相差很大,那么梯度下降将是无效的。使用规范化。如果深度网络有大量无效节点,那么我们应该进一步跟踪问题。可能是bug,权重初始化或者渐变消失造成的。如果没有,试试一些高级的ReLU函数,比如漏ReLU。
数据集的收集和清理
如果你想建立自己的数据集,那么最好的建议是仔细研究如何收集样本。找到最优质的资源,过滤掉所有与你的问题无关的数据,分析错误。在我们的项目中,具有高度纠缠结构的图像的性能很差。我们可以添加卷积层和小过滤器来改变模型。但是模型很难训练。我们可以添加更多的纠缠样本进行进一步的训练,但是已经有很多了……另一种方式:可以细化项目范围,缩小样本范围。
数据增强
收集标记数据是一项昂贵的工作。对于图片,我们可以使用旋转、随机裁剪、移位等数据增强方法来修改已有的数据,生成更多的数据。色彩失真包括色调、饱和度和曝光偏移。
半监督学习
我们也可以用未标记的数据来补充训练数据。使用模型对数据进行分类。将具有高置信度预测的样本添加到具有相应标签预测的训练数据集中。
调整
学习率调整
让我们简单回顾一下如何调整学习率。在早期开发阶段,我们关闭任何非关键的超参数或将其设置为0,包括正则化。使用Adam optimizer,默认的学习率通常表现良好。如果我们对自己的代码很有信心,但损失并没有减少,我们需要调整学习率。典型的学习率在1到1e-7之间。每次降低10%的学习率,短迭代测试,严密监控损失。如果一直涨,那就是学习率太高了。如果不降,学习率太低。提高学习率,直到亏损提前变平。
下面是一个真实的样本,说明学习率过高,导致成本骤增:
在一个不常见的实践中,人们监控W比率的更新:
如果比率1e-3,考虑降低学习率;
如果比例为1E-3,考虑提高学习率。
超参数调整
模型设计稳定后,我们可以进一步调整模型。最常调整的超参数有:
小批量;
学习率;
正则化因子;
特定图层的超参数(如dropout)。
小批量
典型的批量大小为8、16、32或64。如果批量太小,梯度下降就不平滑,模型的学习速度就慢,损失可能会有波动。如果批量太大,完成一次训练迭代(一次更新)的时间太长,返回的结果也会很小。在我们的项目中,我们减少了批量大小,因为每次训练迭代花费的时间太长。我们密切监控整个学习速度和损失。如果损失波动剧烈,就知道批量减少太大了。批量大小会影响正则化因子等超级参数。一旦我们确定了批量大小,我们通常会锁定值。
学习率正则化因子
我们可以使用上述方法来进一步调整学习率和正则化因子。我们通过监控损失来控制学习率与验证和训练精度之间的差距,从而调整正则化因子。我们没有降低10%的学习率,而是降低了3%(在微调中可能更低)。
调谐不是一个线性过程。超参数是相关的,我们会反复调整。学习率与正则化因子高度相关,有时需要一起调整。不要过早进行微调,可能会浪费时间。如果设计改了,这些努力就白费了。
拒绝传统社会的人
辍学率通常在20%到50%之间。先从20%开始吧。如果模型过度拟合,请增加该值。
其他调整
稀少
激活功能
参数的稀疏性可以使计算优化变得简单,降低能耗(这对移动设备非常重要)。如果有必要,我们可以用L1正则化代替L2正则化。ReLU是最流行的激活函数。对于一些深度学习竞赛,人们使用更高级的ReLU变体来提高准确率。在某些场景下,它还可以减少无效节点。
高级参数调整
一些高级微调方法:
学习率衰减调度
动量(动量)
早点停下来
我们不使用固定的学习率,而是定期降低学习率。超参数包括学习率下降的频率和幅度。例如,每100,000次迭代可以减少0.95个学习率。为了调整这些参数,我们需要监控成本,以确保参数下降得更快,而不是过早。
高级优化器使用动量使梯度下降过程平滑。Adam optimizer中有两种动量设置,分别控制一阶(默认0.9)和二阶(默认0.999)动量。对于坡度较陡的问题区域,比如NLP,我们可以稍微提高动量值。
当验证误差不断上升时,可以通过停止训练来缓解过拟合。
然而,这只是概念的可视化。实时误差可能暂时上升,然后再次下降。我们可以定期检查模型,并记录相应的验证误差。以后再选型号吧。
网格搜索
一些超参数是高度相关的。我们应该使用对数标度上的可能性网格来一起调整它们。例如:对于两个超参数和,我们从对应的初始值开始,每步减少10倍:
(e-1、e-2、……和e-8);
(e-3,e-4,…和e-6).
相应的网格将是[(E-1,E-3),(E-1,E-4),……,(e-8,E-5)和(E-8,e-6)]。
我们没有使用明确的交叉点,而是稍微随机地移动这些点。这种随机性可能会帮助我们发现一些隐藏的属性。如果最佳点在网格的边界(蓝点),我们将在边界区域重新测试。
网格搜索需要大量的计算。对于较小的项目,它们将被零星地使用。我们开始用更少的迭代来调整粗粒度参数。在后期的微调阶段,我们将使用更长的迭代,并将值调整为3(或更低)。
模型
在机器学习中,我们可以从决策树中投票进行预测。这种方法非常有效,因为误判通常是局部的:两个模型出现相同错误的概率非常小。在深度学习中,我们可以从随机猜测(提交一个没有明确设定的随机种子)开始训练,优化模型不是唯一的。我们可以多次使用验证数据集测试来选择性能最好的模型,也可以让多个模型内部投票,最后输出预测结果。这种方法需要多个会话,肯定会消耗系统资源。我们也可以一次训练,检查多个模型,然后选择过程中表现最好的模型。通过设定的模型,我们可以根据这些做出准确的预测:
每个模型预测的“投票”;
基于预测置信度的加权投票。
该模型在提高某些问题的预测精度方面非常有效,在深度学习数据竞赛中经常被团队采用。
模型提升
除了微调模型,我们还可以尝试使用模型的不同变体来提高性能。例如,我们可以考虑使用彩色发生器来部分或完全取代标准LSTM。这个概念并不陌生:我们可以一步一步的画图。
直观地说,将时间序列方法引入图像生成任务是有利的,这一点在Draw 3360a递归神经网络用于图像生成中已经得到了证明。
微调和模型提升
性能显著提升的背后,往往是车型设计的改变。然而,有时微调模型也可以提高机器学习的性能。最终的判断可能取决于你相应任务的基准测试结果。
卡格尔
在开发过程中,你可能会有一些简单的问题,比如:我需要使用Leak ReLU吗?有时候问题很简单,但是你在任何地方都找不到答案。在一些论文中,你会看到Leak ReLU的优越性,但是其他项目的体验表明,并没有性能上的提升。太多的项目,太多的变量,缺乏衡量多种可能性的验证结果。Kaggle是一个开放的数据科学竞赛平台,深度学习是其中非常重要的一部分。通过观察一些优秀选手的方法,或许可以找到最常见的表现指标。而且有些数据竞赛团队会把自己的代码(叫内核)上传到开源。只要你关注探索,Kaggle会是一个很棒的信息源。
实验框架
深度学习和开发需要依赖大量的经验,调整超参数是一件非常枯燥的工作。创建一个实验框架可以加速这一过程。例如,有些人会开发代码,将模型定义外化为字符串进行调整。但是,这些努力通常不能给小团队带来收益。以我的经验来看,代码简单性和可追溯性的损失会远大于收益,这意味着很难对代码进行简单的修改。易读的代码必须简洁灵活。相反,很多AI云产品已经开始提供自动调整超级参数的功能。虽然这项技术还处于初级阶段,但人们不需要自己编写框架应该是大势所趋。请关注这一趋势。
结论
现在,您有了调整后的模型,您可以正式部署它了。希望这一系列教程对你有所帮助。深度学习可以帮助我们解决很多问题,它的应用范围超乎你的想象。想用深度学习代替前端设计?可以试试pix2code!
原始链接:
https://medium . com/@ Jonathan _ hui/how-to-start-a-deep-learning-project-d 9 E1 db 90 fa 72
https://medium . com/@ Jonathan _ hui/build-a-deep-learning-dataset-part-2-a 6837 FFA 2d 9 e
https://medium . com/@ Jonathan _ hui/deep-learning-designs-part-3-e 0 b 15 ef 09 CCC
https://medium . com/@ Jonathan _ hui/visualize-deep-network-models-and-metrics-part-4-9500 Fe 06 e3d 0
https://medium . com/@ Jonathan _ hui/debug-a-deep-learning-network-part-5-1123 C20 f 960d
https://medium . com/@ Jonathan _ hui/improve-深度学习-模型-性能-网络-调优-part-6-29bf90df6d2d

其他教程

吉他初学者怎样去调弦(吉他如何调音)

2022-9-5 22:10:25

其他教程

5部让你燃到不行的动漫免费观看(很燃的动漫电影)

2022-9-5 22:12:31

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索