慎用预训练深度学习模型

预训练的模型很容易使用,但是您是否忽略了可能影响模型性能的细节?

你有多少次运行以下代码片段:

代码语言:javascript
复制
1import torchvision.models as models
2inception = models.inception_v3(pretrained=True)

或者

代码语言:javascript
复制
1from keras.applications.inception_v3 import InceptionV3
2base_model = InceptionV3(weights='imagenet', include_top=False)

似乎使用这些预训练模型已经成为行业最佳实践的新标准。合情合理,为什么不利用一个经过大量数据和计算训练的模型呢?

来看看国外两个网站Reddit和HackerNews上的讨论:

预训模型万岁!

利用预培训的模型有几个重要的好处:

  • 合并起来超级简单
  • 快速实现稳定(相同甚至更好)的模型性能
  • 不需要那么多标记数据
  • 从转移学习、预测和特征提取的通用用例

NLP领域的进步也鼓励使用预训练语言模型,如GPT和GPT-2、AllenNLP的ELMo、谷歌的BERT、Sebastian Ruder和Jeremy Howard的ULMFiT。

利用预训练模型的一种常见技术是特征提取,在此过程中检索由预训练模型生成的中间表示,并将这些表示用作新模型的输入。通常假定这些最终完全连接层捕获与解决新任务相关的信息。

每个人都参与其中

每一个主要的框架,如Tensorflow, Keras, PyTorch, MXNet等,都提供了预训练模型,如Inception V3, ResNet, AlexNet等,权重为:

  • Keras应用程序
  • PyTorch torchvision.models
  • Tensorflow官方模型(现在是Tensorflow hub)
  • MXNet模型动物园
  • ai应用程序

但是,这些基准测试是可重复的吗?

这篇文章的灵感来自麻省理工学院计算机科学博士研究生柯蒂斯·诺斯卡特。他的文章《走向可重复性:Keras和PyTorch的基准测试》提出了几个有趣的观点:

  1. resnet架构在PyTorch中表现更好,而inception架构在Keras中表现更好。
  2. 不能复制Keras应用程序上发布的基准测试,即使完全复制示例代码也是如此。事实上,他们报告的准确性(截至2019年2月)通常高于实际的准确性。
  3. 当部署在服务器上或与其他Keras模型按顺序运行时,一些预训练的Keras模型产生不一致或较低的准确性。
  4. 使用批处理规范化的Keras模型可能不可靠。对于某些模型,前向传递计算(假定梯度为off)仍然会导致在推断时权重发生变化。

你可能会想:这怎么可能?它们不是同一种模型吗?如果在相同的条件下训练,它们不应该有相同的性能吗?

好吧,你不是一个人这样认为。柯蒂斯的文章也在推特上引发了一些不同的声音。

了解(并信任)这些基准测试非常重要,因为它们允许您根据要使用的框架做出明智的决策,并且通常用作研究和实现的基准。

那么,当你利用这些预训练模型时,需要注意什么呢?

使用预训练模型的注意事项:

1.你的任务相似吗?您的数据有多相似?

您是否期望引用0.945%的验证精度为Keras Xception模型,如果您正在使用您的新x射线数据集,首先,您需要检查您的数据与模型所训练的原始数据集(在本例中为ImageNet)有多相似。您还需要知道特性是从何处(网络的底部、中部或顶部)传输的,因为这将根据任务相似性影响模型性能。

2.你是如何预处理数据的?

您的模型的预处理应该与原始模型的训练相同。几乎所有的torchvision模型都使用相同的预处理值。对于Keras模型,您应该始终为相应的模型级模块使用preprocess_input函数。例如:

代码语言:javascript
复制
1# VGG16
2keras.applications.vgg16.preprocess_input# InceptionV3
3keras.applications.inception_v3.preprocess_input#ResNet50
4keras.applications.resnet50.preprocess_input

3.你的后端是什么?

有一些关于黑客新闻网站的传言称,将Keras的后端从Tensorflow更改为CNTK (Microsoft Cognitive toolkit)可以提高性能。由于Keras是一个模型级库,它不处理诸如张量积、卷积等低级操作,所以它依赖于其他张量操作框架,如TensorFlow后端和Theano后端。

Max Woolf提供了一个优秀的基准测试项目,该项目发现CNTK和Tensorflow之间的准确性是相同的,但CNTK在LSTMs和多层感知(MLPs)方面更快,而Tensorflow在CNNs和embeddings方面更快。

伍尔夫的帖子是2017年的,所以如果能得到一个更新的比较结果,也包括Theano和MXNet作为后端,那将会很有趣(虽然Theano现在已经被弃用了)。

也有一些说法,有些版本的Theano可能会忽略您的种子(有关Keras的post表单,请参阅本文)。

4.你的硬件是什么?

您使用的是亚马逊EC2 NVIDIA Tesla K80还是谷歌计算NVIDIA Tesla P100?甚至可能是TPU??看看这些有用的基准参考资料,了解这些不同的预训练模型运行时间。

  • Apache MXNet的GluonNLP 0.6:缩小了与BERT重复研究的差距
  • Caleb Robinson的“如何重现ImageNet验证结果”(当然,还有Curtis的“基准测试文章”)
  • DL Bench
  • Stanford DAWNBench
  • TensorFlow的性能基准

5.你的学习速度如何?

在实践中,您应该保持预训练的参数不变(即使用预训练模型作为特征提取器),或者对它们进行微微调整,以避免在原始模型中忘记所有内容。

6.在使用批处理规范化或退出等优化时,特别是在训练模式和推理模式之间,有什么不同吗?

正如柯蒂斯的文章所说:

使用批处理规范化的Keras模型可能不可靠。对于某些模型,前向传递计算(假定梯度为off)仍然会导致在推断时权重发生变化。

但为什么会这样呢?

Expedia的首席数据科学家Vasilis Vryniotis首先发现了Keras中冷冻批次标准化层的问题:

Keras当前实现存在的问题是,当冻结批处理规范化(BN)层时,它在培训期间继续使用小批处理统计信息。我相信当BN被冻结时,更好的方法是使用它在训练中学习到的移动平均值和方差。为什么?由于同样的原因,在冻结层时不应该更新小批统计数据:它可能导致较差的结果,因为下一层的训练不正确。

Vasilis还引用了这样的例子,当Keras模型从列车模式切换到测试模式时,这种差异导致模型性能显著下降(从100%下降到50%)。

好了,请带着这些问题来指导您如何与下一个项目的预培训模型进行交互。有评论、问题或补充吗?可以在下面发表评论!