飞桨上线万能转换小工具,教你玩转TensorFlow、Caffe等模型迁移

国内新闻 浏览(725)

百度推出PaddlePaddle后,许多开发人员开始转向国内深度学习框架。但是从代码转移很容易。重写以前的工作是不现实的。数千行代码的手动转换相当于进行二次开发。

现在,有一个好消息:Caffe,TensorFlow和ONNX可以很容易地迁移到飞桨平台。尽管PyTorch模型目前尚未直接迁移,但PyTorch本身支持导出到ONNX模型,这相当于间接支持平台。

但是,有些人仍然有疑问:不同框架之间的API之间有什么区别吗?整个迁移过程如何运作,步骤复杂?迁移后如何保证准确度的损失在可接受的范围内?

每个人都会考虑很多问题,还有更多问题,总结一下,只不过是以下几点:

1. API差异:模型的实现如何迁移,不同框架之间的API有何不同?如何避免这些差异造成的模型效应差异?

2.模型文件差异:如何迁移训练的模型文件?在转换框架之后如何确保准确度损失在可接受的范围内?

3.预测方法的差异:转换后的模型如何预测?转换前预测效果和模型之间有什么区别?

飞桨开发了一个名为X2Paddle的新功能模块(Github见参考文献1),它可以支持主流深度学习框架模型到飞桨的转换,包括Caffe,Tensorflow,onnx和其他直接转换为Paddle Fluid的模型可加载预测模型。它还提供了三个主要框架之间的API比较,这使我们可以在直接重现模型时比较API之间的差异,并深入理解API的实现以减少模型迁移造成的损失。

我们以TensorFlow转换为Paddle Fluid模型为例,说明如何实现模型的迁移。

TensorFlow-Fluid的API差异

img_pic_1561535412_0.png

在深入学习入门的过程中,每个人都熟悉手写数字识别演示。以下是实现手写数字识别的最简单代码:

在这段代码中,第一步是导入mnist数据集,然后设置占位符x来表示输入图像数据,然后分别设置两个变量w和b来表示要计算的权重和偏移量,最后是输出的y值由softmax计算,我们的实际标签是变量y_。

在前向传播完成之后,可以计算预测值y和标签y_之间的交叉熵。

然后选择合适的优化函数,这里梯度减小,最后启动一个Session,将数据填入批处理,计算acc得到的准确性。

这是一个非常简单的代码。如果我们想将此代码转换为飞行代码,有人可能会认为它非常麻烦。每个实现API都将通过相应的实现,但在这里我可以告诉大家,不!使用!这个!什么!嘛!烦!因为在X2Paddle()中有一个常用的Tensorflow对应于Fluid API表,如下所示:

img_pic_1561535412_1.png

对于常用的TensorFlow API,有一个相应的飞桨接口。如果两者的功能没有区别,则会标记该功能。如果实现或支持的功能和参数不同,则会标记差异。并详细说明。

img_pic_1561535413_2.png

例如,在上面非常简单的代码中,这些TensorFlow API出现:

在这些apis的出现中,大多数函数是一致的,只有两个函数是不同的,分别是tf.placeholder和tf.nn.softmax_cross_entropy_with_logits,分别对应于fluid.layers.data和fluid.layers.softmax_with_cross_entropy。我们来看看具体的差异:

Tf.placeholder V.S fluid.layers.data

使用TensorFlow的学生熟悉占位符。中文翻译是占位符。你什么意思?在TensorFlow 2.0之前,它是静态图的设计理念。整个设计理念是计算流程图。编写程序时,首先构建整个系统。图,代码没有直接生效,这不同于Python的其他数值计算库(如Numpy等),图是静态的,在实际运行时,启动一个会话,程序实际上会运行。这样做的好处是避免重复切换底层程序实际运行的上下文,tensorflow可以帮助您优化整个系统的代码。我们知道许多Python程序的底层是C语言或其他语言。要执行脚本,您需要切换一次。需要付费。 Tensorflow可以通过计算流程图来帮助您优化需要在整个会话中执行的代码。

在代码级别,每个张量值都是图表上的op。当我们将列车数据划分为minibatch然后将其发送到网络进行培训时,每个小批量将是一个操作,在这种情况下,在一对图表上。操作太多了,也会产生巨大的开销;所以有tf.placeholder,我们可以每次都将一个小批量传递给x=tf.placeholder(tf.float32,[None,32]),下次传入的x替换最后传递的x,这样只生成一个op对于所有传入的minibatch x,并且不生成额外的操作,这减少了图的开销。

参数比较

Tf.placeholder

img_pic_1561535413_3.png

Paddle.fluid.layers.data

img_pic_1561535413_4.png

从图中可以看出,飞桨的api参数较多,具体差异如下:

批量维度处理

TensorFlow:要求用户为形状中的批量维度指定None;

飞桨:将第一个维度设置为-1以指示批量维度;如果第一个维度为正,则默认情况下会在开头插入批次维度。要避免批量维度,请将参数append_batch_size设置为False。

是否返回了渐变?

tensorflow和pytorch都支持输入渐变,stop_gradient=False可以直接在飞桨中设置。如果在某个图层使用stop_gradient=True,则此图层之前的图层将自动stop_gradient=True,渐变将不参与返回,并且一些不需要参与损失计算的信息可以设置为stop_gradient=真正。对于具有BatchNormalization图层的CNN网络,渐变也可以应用于输入,例如

img_pic_1561535414_5.png

Tf.nn.softmax_cross_entropy_with_logits V.S

Fluid.layers.softmax_with_cross_entropy

参数比较

img_pic_1561535414_6.png

Paddle.fluid.layers.softmax_with_cross_entropy

img_pic_1561535414_7.png

功能差异

标签类型

TensorFlow:标签只能使用软标签,其形状为[batch,num_classes],表示每个类别中样本的概率分布;

飞桨:通过设置soft_label,您可以选择软标签或硬标签。使用硬标签时,标签的形状为[batch,1],dtype为int64;使用软标签时,形状为[batch,num_classes],dtype为int64。

返回值

TensorFlow:返回批处理中每个样本的日志丢失;

飞桨:当return_softmax为False时,它会批量返回每个样品的对数损失;当return_softmax为True时,它返回logtis的标准化值。

问题点?

硬标签,单热标签,每个样品只能分为一个类别

软标签,每个样本可以分配到多个类别

Numeric_stable_mode:这个参数是什么?指示是否使用具有更好数学稳定性的算法的标志。它仅在soft_label为False的GPU模式下生效。如果soft_label为True或执行位置为CPU,则算法始终在数学上稳定。请注意,使用稳定算法时速度可能会变慢。默认值为True。

Return_softmax:指示是否返回附加softmax值并返回交叉熵计算的结果。默认值为False。

如果return_softmax为False,则返回交叉熵损失

如果return_softmax为True,则返回元组(loss,softmax),其中交叉熵损失是[N x 1]形式的二维张量,softmax是[N x K] <的二维张量/p>

代码示例

img_pic_1561535414_8.png

因此,通过API对应表,我们可以直接将TensorFlow代码转换为Paddle Fluid代码。但是现在项目在线,已经培训了数千行代码或成千上万行可预测模型,如果直接转换API既费时又费钱,有没有办法直接转换训练好的可预测的模型进入另一个框架,前提是转换后的损失准确度在可接受的范围内并且可以直接替换。以下是迁移训练模型的方法。

模型迁移

VGG_16是CV领域的经典模型。以张量流/模型下的VGG_16为例,我将向您展示如何将TensorFlow训练的模型转换为螺旋桨模型。

下载预训练模型

img_pic_1561535415_9.png

解压缩下载的压缩文件

img_pic_1561535415_10.png

以检查点格式保存模型

img_pic_1561535415_11.png

TensorFlow2fluid目前支持检查点格式模型或序列化网络结构和参数的Pb格式模型。上面下载的vgg_16.ckpt只存储模型参数,因此我们需要重新加载参数并将网络结构和参数一起保存为检查点模型。

将模型转换为飞行螺旋桨模型

img_pic_1561535415_12.png

注意:某些OP需要在转换时将参数写入文件,或者运行tensorflow模型推断得到张量值。在这两种情况下,都会花费一定的时间在IO或计算上。在后一种情况下,

打印出日志信息(拦截部分)

img_pic_1561535416_13.png

此时,我们已将tensorflow/models下的vgg16模型转换为Paddle Fluid模型。转换模型和原始模型的准确性是否有任何损失?怎么预测呢?我们来看看以下内容。

预测结果的差异

加载转换的飞桨模型并进行预测

在上一步中转换的模型目录名为“paddle_model”。这里我们通过ml.ModelLoader加载模型。请注意,转换的飞桨模型的输出格式从NHWC转换为NCHW,因此我们需要转向输入数据。组。处理完数据后,您可以使用model.inference进行预测。具体代码如下:

img_pic_1561535416_14.png

对比模型丢失

转换模型存在一个无法避免的问题,即从Tesorflow模型到Paddle Fluid模型的损失。如果模型的精度损失太大,那么转换模型实际上没有意义,只有损失的准确性在我们可接受的范围内。在内部,模型转换可以在实践中应用。在这里,您可以通过加载两个模型文件找到numpy.fabs的两个模型结果之间的差异。

img_pic_1561535416_15.png

打印

img_pic_1561535417_16.png

要注意的要点

1.转换后的模型需要注意输入格式。飞桨中的输入格式必须为NCHW格式。

在这种情况下,不涉及输入中间层,例如卷积层的输出。需要理解的是飞行螺旋桨中的卷积层输出。卷积核的形状与TensorFlow不同。

2.转换模型后,检查转换前后模型的差异,以及需要测试的最大差异是否满足转换要求。

总结

X2Paddle提供了一种非常方便的转换方式,因此您可以直接将训练过的模型转换为Paddle Fluid版本。

转换模型最初需要通过API比较表直接重新实现代码。然而,在实际生产过程中操作非常麻烦,甚至需要二次开发。

如果有一个可以轻松转换模型的新框架,快速运行调试并迭代结果,为什么不呢?

虽然飞桨比其他AI平台晚,但使用X2Paddle小工具,它可以快速吸引AI开发人员到他们自己的平台,随后的优势将变得更加明显。

除了本文中提到的tensoflow2流体,Paddle Fluid还支持caffe2fluid和onnx2fluid。您可以根据自己的需要体验它。如果您有任何疑问,请留言

参考文献:

1. X2Paddle Github:

2. tensorflow2fluid: