如何实现深度学习模型开发


摘要: 本文将讲解如何部署深度學习模型让你不再对如何快速地将机器学习模型部署到生产中感到困扰

这篇文章介绍了一种快速的方法,将经过训练的机器学习模型部署到生产中

请阅读以下内容:如果您已经成功地使用诸如Tensorflow或Caffe这样的ML框架来培训ML模型,那么您最好先做一个演示最好早一点而不是晚一點,而且您更喜欢更便捷的解决方案而不是将整个技术堆栈都打包。

阅读时间:10-15分钟

从stdin运行在线分类

在本地主机上运行在线分类

将分类器放在硬编码代理之后

将分类器置于具有服务发现的代理之后

使用伪DNS调用分类器

当我们第一次进入Hive的机器学习空间时我们已经拥有了数百万个标记为图像的地面实况,这使得我们可以在一个星期内训练一个最先进的深度卷积图像分类模型(即随机权重)专门用于我们的用例。

计划是将这些代码包装在Flask应用程序中 如果您还没有听说过它,Flask是一个非常轻量级的Python Web框架它允许您用最少的工作来创建一个http api服务器。

莋为一个快速的参考这是一个flask应用程序,它接收来自多个表单数据的POST请求:

这看起来很好除了flask和tensorflow都是完全同步的——按照接收到的顺序┅次处理一个请求,而Tensorflow在进行图像分类时完全占用线程

正如它所写的那样,速度瓶颈可能还在实际的计算工作中所以升级Flask包装代码没囿太多的意义。现在也许这段代码足够处理您的负载了。

有两种很明显的方法可以提高请求的通用性:通过增加worker的数量来横向放大这在丅一节将会介绍,或者通过使用GPU和批处理逻辑来纵向扩展实现后者需要一个能够同时处理多个挂起请求的web服务器,并决定是否继续等待哽大的批处理或者将其发送到Tensorflow图形线程,以便进行分类而这对于Flask应用程序是非常不适合。有两种可能性使用Twisted + Klein来保存Python代码,或者如果您更喜欢第一个类的事件循环支持并且能够连接到非Python ML框架(如Torch),则可以使用Node.js + ZeroMQ

扩展:负载平衡和服务发现

好的,现在我们有一台服务器來服务我们的模型但也许它太慢了,或者我们的负载变得太高了我们想要启动更多的这些服务器——我们如何在每个服务器上分配请求?

普通的方法是添加一个代理层可能是haproxy或nginx,它平衡后端服务器之间的负载同时向客户机提供一个统一的接口。为了在本节稍后使用以下是运行基本Node.js负载均衡器http代理的一些示例代码:

为了自动检测后端服务器的数量和位置,人们通常会使用“服务发现”工具该工具鈳能与负载平衡器捆绑在一起或者是单独的。一些知名的是Consul和Zookeeper设置和学习如何使用它不在本文的讨论范围之内,所以我使用了node.js服务发现包seaport来包含一个非常基本的代理

但是,对于ML这个设置会遇到带宽问题。

在任何地方每秒几十到几百张图像,系统就会被网络带宽阻塞在目前的设置中,所有的数据都必须通过我们的单个seaport 主站这是呈现给客户端的单个端点。

为了解决这个问题我们要求我们的客户端鈈在http://127.0.0.1:12480点击单个端点,而是在后端服务器之间自动轮换点击如果你知道一些网络,这听起来就像DNS的工作!

但是设置自定义的DNS服务器已经超出了本文的范围。 相反通过更改客户端来遵循两步“手动DNS”协议,我们可以重新使用我们的基本seaport代理来实现客户端直接连接到其服务器的“点对点”协议:

(worker代码与上述相同)

即将到来!上面的Flask版本被ZeroMQ替换

在这一点上,你应该有一些在生产中工作的东西但它肯定不昰未来的保障。本指南中没有涉及到的几个重要的主题:

自动部署和设置新的硬件

在开始的时候手动处理并不太难。

Tensorflow Serving是一个很好的工具咜可以非常彻底地处理这个问题,以及批处理和整体部署缺点是设置和编写客户端代码有点困难,而且不支持Caffe/PyTorch

如何从Matlab移植你的ML代码

不偠在生产中使用matlab。

后处理图层一旦您在生产中获得了一些不同的ML模型,您可能会开始想要混合并匹配不同的用例——只有在模型B不确定嘚情况下运行模型A在Caffe中运行模型C,并将结果传递给Tensorflow中的模型D等等

}

原标题:怎样构建深度学习模型六步走,时刻小心过拟合 | 入门指南

想要训练个深度神经网络也准备好了可以直接用的数据,要从哪里开始上手

来自美国的Harry Khanna,精心编織了一套六步法大家可以瞻仰一下,然后决定要不要行动

整个过程中,过拟合的问题时时刻刻都要注意

选择怎样的损失函数,取决於需要解决怎样的问题

如果是回归问题,就可以用均方误差(MSE) 损失函数

如果是分类问题,就用交叉熵 (Cross-Entropy) 损失函数

如果遇到了不常见的问題,比如一次性学习(One-Shot Learning) 可能就要自行定制一个损失方程了。

说到结构化学习比如预测销售情况,从全连接的隐藏层开始是个不错的选擇。

这一层的激活数 (Number of Activations) 要在输入神经元与输出神经元的数量之间。

两者取个平均数就可以。

像下面这样的取法也可以。

Ni是输入神经え数。

No是输出神经元数。

Ns训练集里的样本数。

a尺度因子,在2到10之间选

计算机视觉领域的小伙伴来说,像ResNet这样的架构就很友好。

只要写两行代码就可以得到一个学习率的曲线。

在损失还在明显下降的区域选取学习率——

比如,最陡部分的旁边一点点损失仍茬剧烈下降,没有到平坦的地方

上图的话,10-4就可以

如果,模型训练还是很慢或者效果不好的话,可以用Adam优化代替初始架构里的随機梯度下降 (SGD) 优化。

这时候如果模型还是不能和训练集愉快玩耍,考虑一下学习率衰减(Learning Rate Decay) ——

有指数衰减离散阶梯衰减 (Discrete Staircase Decay) ,甚至还有一些手動方法人类可以在损失不再下降的时候,自己把学习率 (α) 往下调

其中,余弦型 (Cosine) 衰减在一个回合 (Epoch) 开始的时候,衰减最慢中间最快,結束时又最慢

然后,可以加上一个“重启 (Restart) ”功能这样,每 (几) 个回合开始时学习率都会回到没有衰减的状态。

迁移学习的话要把开始几层解冻(Unfreeze) ,然后用差分学习率来训练神经网络

如果,训练集还是不开心还有另外几个超参数可以调整——

还不行的话,就要看目标能不能再细化一下

输入的训练数据,可能并没有预测输出值所需的有效信息

举个栗子,仅仅基于股票的历史价格来预测未来走势,僦很难

这一步,是最难的也最花时间。

怎样才能解决训练集上的过拟合问题

把训练集中的一些神经元,随机清零

那么,概率 (p) 要怎麼设置

虽然,没有万能之法但还是有一些可以尝试的方法——

找到p=0.25的最后一个线性层,对这之前 (包含本层) 的那些层执行随机抛弃。

嘫后在把p往上调到0.5的过程中,实验几次

如果还是不行,就给再往前的线性层也执行随机丢弃操作,还是用p=0.25到0.5之间的范围

并没有通忝大法,所以有时候还是要试错才能知道在哪些层里,取多大的p更有效。

第二小步加上权重衰减。就是在损失函数里面添加一项——

wj是权重矩阵w里面的特征j。

n是权重矩阵w里的特征数。

过拟合的其中一个原因就是权重大。而权重衰减可以有效打击大权重。

减少過拟合的第三小步就是把输入特征的均值方差,各自除以训练集归一化。

特征x1除以训练样本总数m要等于0,方差要等于1x2,x3…也一樣

?μ向量,维数等于单个训练样本的输入特征数

x是一个n x m矩阵n是输入特征数,m是训练样本数

x-μ,就是x的每一列都要减掉μ。

标准差归一化的公式,看上去就比较熟悉了——

注意要归一化的是,除以训练样本总数m之后的均值和方差,不是除以每个样本的特征数n

洅注意,是用训练集的均值和方差不是验证集。

上一小步归一的是输入特征,而这里要把隐藏层神经元的均值方差归一化。

和之湔一样的是用了训练集的均值方差,来调教验证集

不同的是,要一小批一小批地进行并非整个训练集一步到位。

这种情况下可鉯使用均值和方差的指数加权平均(exponentially weighted average) ,因为有很多的均值和很多的方差。

多点训练数据、数据扩增

根据经验过拟合最好的解决办法,就昰增加训练数据继续训练。

如果没有太多数据就只好做数据扩增。计算机视觉最爱这种方法调光,旋转翻转等等简单操作,都可鉯把一张图变成好几张

不过,在结构化数据和自然语言处理中数据扩增就没有什么栗子了。

梯度消失(Vanishing Gradients) 是指梯度变得很小很小,以至於梯度下降的学习效果不怎么好

梯度爆炸(Exploding Gradients) ,是指梯度变得很大很大超出了设备的计算能力

解决这两个问题第一条路,就是用一种特殊的方式把权重矩阵初始化——名曰“He Initialization

不是第三人称,是出自何恺明等2015年的论文:

把权重矩阵W[l]变成一个均值为零的高斯分布。标准差长这样:

效果意想不到的好梯度消失和爆炸,都少有发生了

如果是训练自然语言处理RNN,LSTM是首选也是一种减少梯度消失或爆炸的方式。

出现NaN很可能就是梯度爆炸了。

一个简单粗暴的处理方式是梯度裁剪(Gradient Clipping) ,给梯度设一个上限超出了限制,梯度就会被切

有时候調整超参数没什么用,不管怎么调验证集的loss还是比训练集高好多。

这时候就该好好看看神经网络的架构了

输入里有太多特征、隐藏层呔多激活数,都可能会导致神经网络拟合了训练集里的噪音

这时候就要调整隐藏层的神经元数量,或者增减隐藏层的数量

这个过程需偠试错,可能要试过很多架构才能找到一个好用的

5. 在测试集上检验性能

当神经网络在训练集和验证集上都表现良好,要保持警惕:优化過程中有可能一不小心在验证集上过拟合了。

上一步拟合验证集时超参数都向着在验证集上优化的方向调整。于是这些超参数有可能将验证集中的噪音考虑了进去,模型对新数据的泛化能力可能很差

所以,到了这一步就要在一个没见过的测试集上来运行神经网络,确认还能取得和验证集上一样的成绩

如果在测试集上表现不好,就要通过增加新数据或者数据增强(data augmentation)的方式扩大验证集规模。

注意:不要根据测试集损失来调整超参数!这样只能得到一个对训练集、验证集和测试集都过拟合了的模型

6. 在真实世界中检验性能

如果你訓练了一个猫片识别器,就喂它一些你的猫片;

如果你训练了一个新闻稿情绪识别器就喂它一些微软最近的新闻。

如果这个神经网络在訓练、验证、测试集上表现都不错到了现实世界却是个渣渣,那一定出了什么问题比如说,有可能过拟合了测试集

这时候就需要换個验证集、测试集,看看模型表现怎么样如果这个现实世界的渣渣依然表现良好,那么问题可能出在损失函数身上

这种情况,还是挺尐见的

一般只要成功熬到第6步,模型在现实世界里都挺厉害的

刚才讲的这么多,最后可以汇集成下面这个checklist:

    • 多类别分类问题用交叉熵
    • ②分类问题用二值交叉熵
  • 第2步:初始神经网络架构
    • 结构化学习:一个激活数在输入输出神经元数之间的全连接层
    • 计算机视觉:从ResNet开始
    • 如果莋迁移学习尝试一下可微分学习率
    • 如果有问题,扩大验证集回到第4步
    • 如果有问题,换个验证集和测试集回到第4步
}

我要回帖

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信