分享

自学构建深度学习项目:需要思考的问题及如何实现1

问题导读

1.如何选择一个深度学习项目?
2.深度学习需要什么硬件准备?
3.高质量数据集应该包括哪些特征?







导读:在学习了有关深度学习的理论之后,很多人都会有兴趣尝试构建一个属于自己的项目。本文将会从第一步开始,告诉你如何解决项目开发中会遇到的各类问题。

本文由六大部分组成,涵盖深度学习 ( DL ) 项目的整个过程。我们将使用一个自动漫画着色项目来说明深度学习的设计、程序调试和参数调整过程。
本文主题为「如何启动一个深度学习项目?」,分为以下六个部分:

  • 第一部分:启动一个深度学习项目
  • 第二部分:创建一个深度学习数据集
  • 第三部分:设计深度模型
  • 第四部分:可视化深度网络模型及度量指标
  • 第五部分:深度学习网络中的调试
  • 第六部分:改善深度学习模型性能及网络调参


01 启动一个深度学习项目


1. 应该选择什么样的项目?
很多人工智能项目其实并没有那么严肃,做起来还很有趣。2017 年初,我着手启动了一个为日本漫画上色的项目,并作为我对生成对抗网络 ( GAN ) 研究的一部分。这个问题很难解决,但却很吸引人,尤其是对于我这种不会画画的人来说!在寻找项目时,不要局限于增量性改进,去做一款适销对路的产品,或者创建一种学习速度更快、质量更高的新模型。

2. 调试深度网络(DN)非常棘手
训练深度学习模型需要数百万次的迭代,因此查找 bug 的过程非常艰难,而且容易崩坏。因此我们要从简单的地方着手,循序渐进,例如模型的优化(如正则化)始终可以在代码调试完成后进行。此外,我们还需要经常可视化预测结果和模型度量标准,并且我们首先需要令模型跑起来,这样就有一个可以后退的基线。我们最好不要陷在一个很大的模型,并尝试将所有的模块都弄好。

3. 度量和学习
宏伟的项目计划可能带惨烈的失败。多数个人项目的第一个版本会持续两到四个月,这个时间非常短暂,因为研究、调试和实验都需要花费大量的时间。一般我们安排这些复杂的实验,使其通宵运行,到第二天清晨时,我们希望得到足够的信息来采取下一步行动。在早期阶段,这些实验不应超过 12 小时,这是一条良好的经验法则。为了做到这一点,我们将漫画上色项目范围缩小到单个动画人物的上色。此外,我们需要设计很多测试,因此借助它们分析模型在实验中的不足之处。一般这些测试不要计划得太远,我们需要快速度量、学习,并为下一步设计提供足够的反馈。

4. 研究与产品
当我们在 2017 年春季开始讨论漫画上色项目时,Kevin Frans 有一个 Deepcolor 项目,用 GAN 为漫画添加色彩提示。

p.png

在确定目标时,你会花很大力气来确保项目完成后仍然具有意义。GAN 模型相当复杂,2017 年初还没达到嵌入产品所需的质量水准。然而,如果你把应用范围缩小到产品可以巧妙处理的程度,你就可以把质量提高到商用水准。为此,无论着手启动何种 DL 项目,都要把握好模型泛化、容量和准确性之间的平衡。

5. 成本
必须使用 GPU 来训练实际模型。它比 CPU 快 20 到 100 倍。价格最低的亚马逊 GPU p2.xlarge 站点实例要价 7.5 美元/天,而 8 核 GPU 的价格则高达 75 美元/天。在我们的漫画上色项目中,一些实验花费的时间就超过两天,因此平均每周花费至少需要 150 美元。至于更快的 AWS 实例,花费可能高达 1500 美元/周。我们可以购买独立计算机,而不是使用云计算。2018 年 2 月,搭载 Nvidia GeForce GTX 1080 Ti 的台式机售价约为 2200 美元。在训练精调的 VGG 模型时,它比 P2 实例大约要快 5 倍。

6. 时间线
我们将开发分为四个阶段,最后三个阶段在多次迭代中进行。

  • 项目研究
  • 模型设计
  • 实现及调试
  • 实验及调参


项目研究
我们会先对现有产品进行研究,以探索它们的弱点。许多 GAN 类型的解决方案使用空间颜色提示,图案有点不清晰,有时还会出现颜色混杂。我们为自己的项目设定了两个月的时间框架,其中有两个优先事项:生成不带提示的颜色及提高颜色保真度。我们的目标是:
在单个动画角色上为灰度漫画着色,且不使用空间颜色提示。

站在巨人的肩膀上
接下来,我们需要了解相关的研究和开源项目,许多人在开始实践之前至少要看几十篇论文和项目。例如,当我们深入研究 GAN 时,发现有十几个新的 GAN 模型: DRAGAN、cGAN、LSGAN 等,阅读研究论文可能会很痛苦,但非常有意义。
深度学习 ( DL ) 代码简练,但很难排查缺陷,且很多研究论文常常遗漏了实现细节。许多项目始于开源实现,解决的问题也很相似,因此我们可以多多搜索开源项目。因此我们在 GitHub 上查看了不同 GAN 变体的代码实现,并对它们进行若干次测试。



02 创建一个深度学习数据集


深度学习项目的成功取决于数据集的质量。在本文的第 2 部分中,我们将探讨创建优质训练数据集的核心问题。

p.png



1. 公开及学术数据集

对于研究项目,可以搜索已建立的公开数据集。这些数据集可以提供更整齐的样本和基线模型性能。如果你有多个可用的公开数据集,请选择与你的问题最相关且质量最好的样本。

2. 自定义数据集

对于实际问题,我们需要来自问题领域的样本。首先尝试查找公共数据集。关于创建高质量自定义数据集的研究还有所欠缺。如果没有可用的资料,请搜寻你可以抓取数据的位置。该位置通常有很多参考,但数据质量通常较低,还需要投入大量精力进行整理。在抓取样本之前,要专门抽出时间评估所有选项并选择最相关的选项。

高质量数据集应该包括以下特征:

  • 类别均衡
  • 数据充足
  • 数据和标记中有高质量信息
  • 数据和标记错误非常小
  • 与你的问题相关


不要一次爬取所有数据。我们经常借助标签和分类来抓取网站样本,从而获取与我们的问题相关的数据。最好的爬取方法是在你的模型中训练、测试少量样本,并根据得到的经验教训改善抓取方法。

清理你抓取的数据非常重要,否则,即使最好的模型设计也达不到与人类水平相当的表现。Danbooru 和 Safebooru 是两个非常受欢迎的动漫人物来源,但是一些深入学习的应用程序偏爱 Getchu,以获得更高质量的绘图。我们可以使用一组标签从 Safebooru 下载图像,并直观地检查样本并运行测试来分析错误(表现不佳的样本)。

模型训练和视觉评估都提供了进一步的信息来细化我们的标签选择。随着迭代的继续,我们将学到更多,并逐渐进行样本积累。我们还需要使用分类器进一步过滤与问题无关的样本,如清除所有人物过小的图像等。与学术数据集相比,小型项目收集的样本很少,在适当情况下可以应用迁移学习。

下面的左图由 PaintsChainer 提供,右图由最终的模型上色:

p.png


我们决定用一些训练样本来对算法进行测试。结果并没有给人惊喜,应用的颜色较少,样式也不正确。

p.png
p.png

由于对模型进行了一段时间的训练,我们知道什么样的绘图表现欠佳。正如预期的那样,结构错综复杂的绘图更难上色。

p.png

这说明好好选择样本非常重要。作为一款产品,PaintsChainer 专注于它们擅长的线条类型,这点非常明智。这次我使用了从互联网上挑选的干净线条艺术,结果再次给人惊喜。

p.png

这里有一些经验教训:数据没有好坏之分,只是有些数据不能满足你的需求。此外,随着样本类别的增加,训练和保持输出质量会变得更加困难,删除不相关的数据可以得到一个更好的模型。

在开发早期,我们认识到一些绘图有太多错综复杂的结构。在不显著增加模型容量的情况下,这些绘图在训练中产生的价值很小,因此最好不要使用,否则只会影响训练效率。

3. 重点回顾
  • 尽可能使用公共数据集;
  • 寻找可以获取高质量、多样化样本的最佳网站;
  • 分析错误并过滤掉与实际问题无关的样本;
  • 迭代地创建你的样本;
  • 平衡每个类别的样本数;
  • 训练之前先整理样本;
  • 收集足够的样本。如果样本不够,应用迁移学习。


03 深度学习设计

第三部分介绍了一些高层次的深度学习策略,接下来我们将详细介绍最常见的设计选择,这可能需要一些基本的 DL 背景。

1. 简单灵活

设计初始要简单、小巧。在学习阶段,人们脑海中会充斥大量很酷的观念。我们倾向于一次性把所有细节都编码进来。但这是不现实的,最开始就想要超越顶尖的结果并不实际。从较少网络层和自定义开始设计,后面再做一些必要的超参数精调方案。这些都需要查证损失函数一直在降低,不要一开始就在较大的模型上浪费时间。

在简短的 Debug 之后,我们的模型经过 5000 次迭代产生了简单的结果。但至少该模型所上的颜色开始限制在固定区域内,且肤色也有些显露出来。

p.png

在模型是否开始上色上,以上结果给了我们有价值的反馈。所以不要从大模型开始,不然你会花费大量时间 Debug 和训练模型。

2. 优先性以及增量设计

首先为了创造简单的设计,我们需要选出优先项。把复杂问题分解成小问题,一步一步解决。做深度学习的正确策略是快速的执行学到的东西。在跳到使用无暗示(no hints)模型之前,我们先使用带有空间颜色暗示的模型。不要一步跳到「无暗示」模型设计,例如我们首先去掉暗示中的空间信息,颜色质量会急剧下降,所以我们转变优先性,在做下一步前先精炼我们的模型。在设计模型的过程中,我们会遇到许多惊喜。相比于做个要不断改变的长期计划,还不如以优先性驱动的计划。使用更短、更小的设计迭代,从而保证项目可管理性。

3. 避免随机改进

首先分析自己模型的弱点,而不是随意地改进,例如用双向 LSTM 或者 PReLU。我们需要根据可视化模型误差(表现极差的场景)以及性能参数来确定模型问题。随意做改进反而适得其反,会成比例的增加训练成本,而回报极小。


4. 限制

我们把限制应用到网络设计,从而保证训练更高效。建立深度学习并不是简单的把网络层堆在一起。增加好的限制(constraints)能使得学习更为有效,或者更智能。例如,应用注意机制,能让网络知道注意哪里,在变分自编码器中,我们训练隐藏因子使其服从正态分布。在设计中,我们应用去噪方法通过归零除去空间颜色暗示的大量分数。啼笑皆非的是,这使得模型能更好地学习、泛化。

5. 设计细节

文章接下来的部分,将讨论深度学习项目中会遇到的一些常见的设计选择。

深度学习软件框架

自谷歌 2015 年 11 月发布 TensorFlow 以来,短短 6 个月就成为了最流行的深度学习框架。虽然短期看起来难有竞争对手,但一年后 Facebook 就发布了 PyTorch,且极大的受研究社区的关注。到 2018 年,已经有大量的深度学习平台可供选择,包括 TensorFlow、PyTorch、Caffe、Caffe2、MXNet、CNTK 等。

一些研究员之所以转向 PyTorch 有一主要因素:PyTorch 设计上注重端用户(end-user),API 简单且直观。错误信息可以直观地理解,API 文档也非常完整。PyTorch 中的特征,例如预训练模型、数据预处理、载入常用数据集都非常受欢迎。

TensorFlow 也非常棒,但目前为止它还是采用自下而上的方式,使其变得极为复杂。TensorFlow 的 API 很冗长,Debug 也不一样,它大概有十几种建立深度网络的 API 模型。

截止到 2018 年 2 月,TensorFlow 依然独占鳌头。开发者社区依然是是最大的。这是非常重要的因素。如果你想要用多个机器训练模型,或者把推理引擎部署到移动手机上,TensorFlow 是唯一的选择。然而,如果其他平台变得更加专注端用户,我们可以预见将会有更多从小项目转向中级项目。

随着 TensorFlow 的发展,有很多 API 可供选择来建立深度网络。最高层的 API 是提供隐式积分的评估器,而 TensorBoard 提供了性能评估。最低层的 API 非常冗长,在许多模块中都有。现在,它用封装器 API 合并到了 tf.layers、tf.metrics 和 tf.losses 模块,从而更容易地建立深度网络层。

对想要更直观 API 的研究者来说,还有 Keras、TFLearn、TF-Slim 等可以选择,这些都可直接在 TensorFlow 上使用。我建议是选择带有所需要的预训练模型与工具(来下载数据集)的框架,此外在学术界,用 Keras API 做原型设计相当流行。

迁移学习

不要做重复的工作。许多深度学习软件平台都有 VGG19、ResNet、Inception v3 这样的预训练模型。从头开始训练非常耗费时间。就像 2014 年 VGG 论文中所说的,「VGG 模型是用 4 块英伟达 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 正则化可以产生更加稀疏的参数,这有助于解开底层表示。由于每个非零参数会往成本上添加惩罚,与 L2 正则化相比,L1 更加青睐零参数,即与 L2 正则化中的许多微小参数相比,它更喜欢零参数。L1 正则化使过滤器更干净、更易于解释,因此是特征选择的良好选择。L1 对异常值的脆弱性也较低,如果数据不太干净,运行效果会更好。然而,L2 正则化仍然更受欢迎,因为解可能更稳定。

梯度下降

始终密切监视梯度是否消失或爆炸,梯度下降问题有许多可能的原因,这些原因难以证实。不要跳至学习速率调整或使模型设计改变太快,小梯度可能仅仅由编程 Bug 引起,如输入数据未正确缩放或权重全部初始化为零。

如果消除了其他可能的原因,则在梯度爆炸时应用梯度截断(特别是对于 NLP)。跳过连接是缓解梯度下降问题的常用技术。在 ResNet 中,残差模块允许输入绕过当前层到达下一层,这有效地增加了网络的深度。

缩放

缩放输入特征。我们通常将特征缩放为以零为均值在特定范围内,如 [-1, 1]。特征的不适当缩放是梯度爆炸或降低的一个最常见的原因。有时我们从训练数据中计算均值和方差,以使数据更接近正态分布。如果缩放验证或测试数据,要再次利用训练数据的均值和方差。

批归一化和层归一化

每层激活函数之前节点输出的不平衡性是梯度问题的另一个主要来源,必要时需要对 CNN 应用批量归一化(BN)。如果适当地标准化(缩放)输入数据,DN 将学习得更快更好。在 BN 中,我们从每批训练数据中计算每个空间位置的均值和方差。例如,批大小为 16,特征图具有 10 X10 的空间维度,我们计算 100 个平均值和 100 个方差(每个位置一个)。每个位置处的均值是来自 16 个样本的对应位置平均值,我们使用均值和方差来重新归一化每个位置的节点输出。BN 提高了准确度,同时缩短了训练时间。

然而,BN 对 RNN 无效,我们需要使用层归一化。在 RNN 中,来自 BN 的均值和方差不适合用来重新归一化 RNN 单元的输出,这可能是因为 RNN 和共享参数的循环属性。在层归一化中,输出由当前样本的层输出计算的平均值和方差重新归一化。一个含有 100 个元素的层仅使用来自当前输入的一个平均值方差来重新归一化该层。

Dropout

可以将 Dropout 应用于层以归一化模型。2015 年批量归一化兴起之后,dropout 热度降低。批量归一化使用均值和标准差重新缩放节点输出。这就像噪声一样,迫使层对输入中的变量进行更鲁棒的学习。由于批量归一化也有助于解决梯度下降问题,因此它逐渐取代了 Dropout。

结合 Dropout 和 L2 正则化的好处是领域特定的。通常,我们可以在调优过程中测试 dropout,并收集经验数据来证明其益处。

激活函数

在 DL 中,ReLU 是最常用的非线性激活函数。如果学习速率太高,则许多节点的激活值可能会处于零值。如果改变学习速率没有帮助,我们可以尝试 leaky ReLU 或 PReLU。在 leaky ReLU 中,当 x < 0 时,它不输出 0,而是具有小的预定义向下斜率(如 0.01 或由超参数设置)。参数 ReLU(PReLU)往前推动一步。每个节点将具有可训练斜率。

拆分数据集

为了测试实际性能,我们将数据分为三部分: 70 % 用于训练,20 % 用于验证,10 % 用于测试。确保样本在每个数据集和每批训练样本中被充分打乱。在训练过程中,我们使用训练数据集来构建具有不同超参数的模型。我们使用验证数据集来运行这些模型,并选择精确度最高的模型。但是保险起见,我们使用 10 % 的测试数据进行最后的错乱检查。如果你的测试结果与验证结果有很大差异,则应将数据打乱地更加充分或收集更多的数据。

基线

设置基线有助于我们比较模型和 Debug,例如我们可使用 VGG19 模型作为分类问题的基线。或者,我们可以先扩展一些已建立的简单模型来解决我们的问题。这有助于我们更好地了解问题,并建立性能基线进行比较。在我们的项目中,我们修改了已建立的 GAN 实现并重新设计了作为基线的生成网络。

检查点

我们定期保存模型的输出和度量以供比较。有时,我们希望重现模型的结果或重新加载模型以进一步训练它。检查点允许我们保存模型以便以后重新加载。但是,如果模型设计已更改,则无法加载所有旧检查点。我们也使用 Git 标记来跟踪多个模型,并为特定检查点重新加载正确的模型。我们的设计每个检查点占用 4gb 空间。在云环境中工作时,应相应配置足够的存储。我们经常启动和终止 Amazon 云实例,因此我们将所有文件存储在 Amazon EBS 中,以便于重新连接。

自定义层

深度学习软件包中的内建层已经得到了更好的测试和优化。尽管如此,如果想自定义层,你需要:

  • 用非随机数据对前向传播和反向传播代码进行模块测试;
  • 将反向传播结果和朴素梯度检查进行对比;
  • 在分母中添加小量的&#1013;或用对数计算来避免 NaN 值。


归一化

深度学习的一大挑战是可复现性。在调试过程中,如果初始模型参数在 session 间保持变化,就很难进行调试。因此,我们明确地对所有随机发生器初始化了种子。我们在项目中对 python、NumPy 和 TensorFlow 都初始化了种子。在精调过程中,我们我们关闭了种子初始化,从而为每次运行生成不同的模型。为了复现模型的结果,我们将对其进行 checkpoint,并在稍后重新加载它。


6. 优化器

Adam 优化器是深度学习中最流行的优化器之一。它适用于很多种问题,包括带稀疏或带噪声梯度的模型。其易于精调的特性使得它能快速获得很好的结果。实际上,默认的参数配置通常就能工作得很好。Adam 优化器结合了 AdaGrad 和 RMSProp 的优点。Adam 对每个参数使用相同的学习率,并随着学习的进行而独立地适应。Adam 是基于动量的算法,利用了梯度的历史信息。因此,梯度下降可以运行得更加平滑,并抑制了由于大梯度和大学习率导致的参数振荡问题。

Adam 优化器调整

Adam 有 4 个可配置参数:

  • 学习率(默认 0.001);
  • β1:第一个矩估计的指数衰减率(默认 0.9);
  • β2:第二个矩估计的指数衰减率(默认 0.999),这个值在稀疏梯度问题中应该被设置成接近 1;
  • &#1013;(默认值 1e^-8)是一个用于避免除以零运算的小值。


β(动量)通过累积梯度的历史信息来平滑化梯度下降。通常对于早期阶段,默认设置已经能工作得很好。否则,最可能需要改变的参数应该是学习率。


7. 总结
以下是对深度学习项目的主要步骤的简单总结:
[mw_shl_code=text,true]&#8226; Define task (Object detection, Colorization of line arts)
&#8226; Collect dataset (MS Coco, Public web sites)
    &#9702; Search for academic datasets and baselines
    &#9702; Build your own (From Twitter, News, Website,…)
&#8226; Define the metrics
    &#9702; Search for established metrics
&#8226; Clean and preprocess the data
    &#9702; Select features and transform data
    &#9702; One-hot vector, bag of words, spectrogram etc...
    &#9702; Bucketize, logarithm scale, spectrogram
    &#9702; Remove noise or outliers
    &#9702; Remove invalid and duplicate data
    &#9702; Scale or whiten data
&#8226; Split datasets for training, validation and testing
    &#9702; Visualize data
    &#9702; Validate dataset
&#8226; Establish a baseline
    &#9702; Compute metrics for the baseline
    &#9702; Analyze errors for area of improvements
&#8226; Select network structure
    &#9702; CNN, LSTM…
&#8226; Implement a deep network
    &#9702; Code debugging and validation
    &#9702; Parameter initialization
    &#9702; Compute loss and metrics
    &#9702; Choose hyper-parameters
    &#9702; Visualize, validate and summarize result
    &#9702; Analyze errors
    &#9702; Add layers and nodes
    &#9702; Optimization
&#8226; Hyper-parameters fine tunings
&#8226; Try our model variants[/mw_shl_code]

下一篇自学构建深度学习项目:需要思考的问题及如何实现2
http://www.aboutyun.com/forum.php?mod=viewthread&tid=24615


本帖被以下淘专辑推荐:

已有(1)人评论

跳转到指定楼层
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条