PyTorch到Tensorflow的模型转换
⽂章⽬录
在本⽂中,我们将学习如何将PyTorch模型转换为TensorFlow。
如果您是深度学习的新⼿,那么使⽤哪种框架可能会让您不知所措。我们个⼈认为PyTorch是您应该学习的第⼀个框架,但它可能不是您想要学习的唯⼀框架。
好消息是您不需要嫁给框架。您可以在PyTorch中训练模型,然后将其轻松转换为Tensorflow,只要使⽤标准图层即可。实现此转换的最佳⽅法是先将PyTorch模型转换为ONNX,然后再转换为Tensorflow/Keras格式。
1 结果相同,使⽤ONNX的不同框架
我们可以观察到,在有关的早期⽂章中,所实现的模型⽐版本更准确地预测了图⽚中的单峰骆驼区域:
PyTorch FCN ResNet18激活:
TensorFlow FCN ResNet50激活:
假设我们想捕获结果并将它们转移到另⼀个领域,例如,从PyTorch到TensorFlow。有什么办法可以执⾏吗?答案是肯定的。⼀种可能的⽅法是使⽤库。如其名称所述,该⼯具提供了在PyTorch和Keras等框架之间进⾏模型转换的简便⽅法。您可以使⽤pip轻松安装它:
pip3 install pytorch2keras
2 PyTorch模型转换pipeline
从pytorch2keras的中可以看到,中描述了 pipeline 的逻辑。让我们查看其关键点:
def pytorch_to_keras(
model, args, input_shapes=None,
change_ordering=False, verbose=False, name_policy=None,
use_optimizer=False, do_constant_folding=False
):
# ...
# load a ModelProto structure with ONNX
onnx_model = onnx.load(stream)
# ...
#
k_model = onnx_to_keras(onnx_model=onnx_model, input_names=input_names,
input_shapes=input_shapes, name_policy=name_policy,
verbose=verbose, change_ordering=change_ordering)
return k_model
您可能已经注意到,该⼯具基于。ONNX是⼀个开源AI项⽬,其⽬标是使不同⼯具之间的神经⽹络模型互换,以选择这些⼯具的更好组合。将获得的过渡的top-level ONNX ModelProto容器传递给onnx2keras⼯具的函数,以进⾏进⼀步的层映射。
让我们以全卷积⽹络架构为例来研究PyTorch ResNet18转换过程:
# import transferring tool
verter import pytorch_to_keras
def converted_fully_convolutional_resnet18(
input_tensor, pretrained_resnet=True,
):
# define input tensor
input_var = Variable(torch.FloatTensor(input_tensor))
# get PyTorch ResNet18 model
model_to_transfer = FullyConvolutionalResnet18(pretrained=pretrained_resnet)
model_to_transfer.eval()
# convert PyTorch model to Keras
model = pytorch_to_keras(
model_to_transfer,
input_var,
[input_var.shape[-3:]],
change_ordering=True,
verbose=False,
name_policy="keep",
)
return model
现在我们可以⽐较PyTorch和TensorFlow FCN版本了。让我们看⼀下第⼀堆PyTorch FullyConvolutionalResnet18层。值得注意的是,我们使⽤了⼯具来实现PyTorch和TensorFlow模型摘要的视觉⼀致性:
from torchsummary import summary
summary(model_to_transfer, input_size=input_var.shape[-3:])
输出为:
----------------------------------------------------------------
Layer (type)              Output Shape        Param #
================================================================
Conv2d-1        [-1, 64, 363, 960]          9,408
BatchNorm2d-2        [-1, 64, 363, 960]            128
ReLU-3        [-1, 64, 363, 960]              0
MaxPool2d-4        [-1, 64, 182, 480]              0
Conv2d-5        [-1, 64, 182, 480]          36,864
BatchNorm2d-6        [-1, 64, 182, 480]            128
ReLU-7        [-1, 64, 182, 480]              0
Conv2d-8        [-1, 64, 182, 480]          36,864
BatchNorm2d-9        [-1, 64, 182, 480]            128
ReLU-10        [-1, 64, 182, 480]              0
BasicBlock-11        [-1, 64, 182, 480]              0
Conv2d-12        [-1, 64, 182, 480]          36,864
BatchNorm2d-13        [-1, 64, 182, 480]            128
ReLU-14        [-1, 64, 182, 480]              0
Conv2d-15        [-1, 64, 182, 480]          36,864
BatchNorm2d-16        [-1, 64, 182, 480]            128
transform和convert的区别
ReLU-17        [-1, 64, 182, 480]              0
使⽤pytorch_to_keras函数转换后获得的TensorFlow模型包含与初始PyTorch ResNet18模型相同的层,但TF特定的InputLayer和ZeroPadding2D作为填充参数包含在中。
以下摘要是使⽤类的内置Keras ⽅法⽣成的:
model.summary()
输出中的相应层已标记有⽤于PyTorch-TF映射的适当数字:
Layer (type)                    Output Shape        Param #
===============================================================
input_0 (InputLayer)            [(None, 725, 1920, 3 0
_______________________________________________________________
125_pad (ZeroPadding2D)        (None, 731, 1926, 3) 0
_______________________________________________________________
125 (Conv2D)                  (None, 363, 960, 64) 9408    1
_______________________________________________________________
126 (BatchNormalization)        (None, 363, 960, 64) 256    2
_______________________________________________________________
127 (Activation)                (None, 363, 960, 64) 0      3
_______________________________________________________________
128_pad (ZeroPadding2D)        (None, 365, 962, 64) 0
_______________________________________________________________
128 (MaxPooling2D)              (None, 182, 480, 64) 0      4
_______________________________________________________________
129_pad (ZeroPadding2D)        (None, 184, 482, 64) 0
_______________________________________________________________
129 (Conv2D)                    (None, 182, 480, 64) 36864  5
_______________________________________________________________
130 (BatchNormalization)        (None, 182, 480, 64) 256    6
_______________________________________________________________
131 (Activation)                (None, 182, 480, 64) 0      7
_______________________________________________________________
132_pad (ZeroPadding2D)        (None, 184, 482, 64) 0
_______________________________________________________________
132 (Conv2D)                    (None, 182, 480, 64) 36864  8
_______________________________________________________________
133 (BatchNormalization)        (None, 182, 480, 64) 256    9
_______________________________________________________________
134 (Add)                      (None, 182, 480, 64) 0
_______________________________________________________________
135 (Activation)                (None, 182, 480, 64) 0      10
_______________________________________________________________
136_pad (ZeroPadding2D)        (None, 184, 482, 64) 0
_______________________________________________________________
136 (Conv2D)                    (None, 182, 480, 64) 36864  12
_______________________________________________________________
137 (BatchNormalization)        (None, 182, 480, 64) 256    13
_______________________________________________________________
138 (Activation)                (None, 182, 480, 64) 0      14
_______________________________________________________________
139_pad (ZeroPadding2D)        (None, 184, 482, 64) 0
_______________________________________________________________
139 (Conv2D)                    (None, 182, 480, 64) 36864  15
_______________________________________________________________
140 (BatchNormalization)        (None, 182, 480, 64) 256    16
_______________________________________________________________
141 (Add)                      (None, 182, 480, 64) 0
_______________________________________________________________
142 (Activation)                (None, 182, 480, 64) 0      17
_______________________________________________________________
143_pad (ZeroPadding2D)        (None, 184, 482, 64) 0
_______________________________________________________________
以下⽅案部分介绍了两种版本的TensorFlow和PyTorch的FCN ResNet18块的可视化表⽰:
左侧为转换后的TensorFlow FCN ResNet18模型,右侧为初始的PyTorchFCN ResNet18模型。
使⽤开源查看器⽣成模型图。它⽀持从ONNX,TensorFlow,Caffe,PyTorch等获得的各种模型格式。保存的模型图作为输⼊传递给Netron,Netron进⼀步⽣成详细的模型图。
3 转移模型结果
因此,我们将整个模型及其权重转换为TensorFlow,将NCHW(批次⼤⼩,通道,⾼度,宽度)格式更改为NHWC,并带有
change_ordering = True参数。
这样做是因为在PyTorch模型中,输⼊层的 shape 为3×725×1920,⽽在TensorFlow中,其输⼊层的 shape 已更改为
725×1920×3,因为TF中的默认数据格式为。我们还应该记住,要获得与PyTorch (1, 1000, 3, 8)相同的预测shape,我们应该再次转置⽹络输出:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。