tensorflow打印模型结构_边缘计算笔记(三):从Tensorflow生成TensorRT引擎的方法(完结篇)...

5a365ec8d9864939f6467e663b27c2b7.png

到这里,我们已经讲解了

边缘计算笔记(一): Jetson TX2上从TensorFlow 到TensorRT

边缘计算笔记(二): 从tensorflow生成tensorRT引擎的方法

这是第三个部分,也是最后一个部分,我们继续讲解如何转换生成TensorRT优化的引擎,

042e04cf882247817c383681cfafa146.gif

d0b7a482b6b89e1a0ed9484d9cba62f3.png

c7041fb86da6cd41787b7693ae797be1.png

4388345f6348e0efe17ed733d4a4e4b7.png

例如我们想将训练好的Inception V1现成模型,从TensorFlow转换为TensorRT, 我们可以从(TensorBoard)显示的结构图的最发现找到输入节点,(从该节点的右上角信息)中,可以看出来它被叫做input,具有placeholder运算类型,然后在这段信息的output部分,我们可以看到该节点的张量输出维度(信息)。第一个维度我们可以看到这里被画上了"?"号(Question mark), 因为它代表了batch size, 是可变的。 后续的三个维度,分别代表了图像的高度、宽带、以及通道数。(这信息框)里的这些数值,在我们转换到TensorRT的时候,需要用来作为参考.

1b2c6b13a54597bae7ba79216c7c1312.png

6eb2dc3f351122dd252891962481e479.png

 在这个网络结构图的最上方,是输出节点。它的操作类型为Squeeze, 在本网络中/在本实例中,只是用来去除输入的空间维度。这个操作层的名字叫做InceptionV1/Logits/SpatialSqueeze,从上一个节点的输出可以看到,1001个不同class label作为本节点的输入。

2141100149cf79b0b4ec3fb57dd9666a.png

 我们还注意到,该网络图中的每层操作,都属于被TensorRT支持的类型,所以这就允许我们转换生成TensorRT优化的引擎。

732a8c1010e79a227ff1c7f973782974.png

 好了,既然确定了网络图层的相关信息,也生成过了冻结图文件,则在创建TensorRT推理引擎的时候,使用上这些参数就可以了!

3132285bb132a7ea7b36412c3f2d9522.png

对模型优化和创建引擎的时候,TensorRT允许设定一些自定义的引擎构建参数。 这里我们具体看下TX2的,相关优化构建参数。 首先我们可以更改最大batch size参数,该参数通常是我们调用一次推理引擎,所能一次处理的最大图片数量。 当然在运行的时候,使用比创建引擎时候所制定的这个参数小的数量,也是可以的。 第二点则是我们可以设定引擎使用的内部数据类型。如同我们之前了解过的那样,当使用FP16而不是FP32的时候,往往有显著的性能提升。  注意即使引擎内部使用了FP16数据类型,它所执行的推理网络的输入和输出依然以原来的FP32不变(这里说,FP16会提升性能。用了FP16不需要用户接口发生变化,因为网络的输入输出还是用的老类型,这样用户不需要改动代码就能享受到内部的提速)。最后第三点这是,我们设定最大的WorkSpace大小。该大小是指的网络中的不同层运行的时候,所能用到的内存大小

22eaeb55b9f6b5b13cfc5c1bea7b0f47.png

在NV GitHub代码库中,提供了转换脚本。而现在我们已经有了所需要的全部输入数据和信息,可以运行该脚本了。

代码库从github克隆到本地后,我们从该项目的根目录下,调用python来执行脚本。这里我们演示了一个转换InceptionV1网络模型的例子。 按照从上到下的顺序,先是冻结图文件的路径,然后是要生成的引擎序列化后的保存路径,网络的输入层名称,输入高度、大小,输出层名字,最大的batch size,最大的worksapce大小,以及最后是用FP32还是半精度。

08c7b8002ea38a015566db0914a47c39.png

 对于一些模型来说,这个转换脚本能够毫无问题的运行,并生成序列化后的引擎。但对于一些其他模型,包含有TensorRT所不支持的操作类型的时候,会出现这个幻灯片中类似的这种警告信息。在这种情况下引擎生成/导出的过程可能会依然能够成功,但再次的反序列化/解析二进制引擎文件,和创建引擎,都会失败。 TensorRT当前并不支持TensorFlow所导出的intermediate文件中的插件层。因此我们不能在网络结果图中有不被支持的操作。 对于这种情况,我们有两种可选的处理方案:

 第一种方案是,对于这些不被TensorRT支持的部分,手工在TRT引擎的输入前面,或者在TRT引擎的输出后面,用CUDA或者C++写上处理过程。

 第二种方案则是修改TensorFlow中的网络结构图,删除或者替换掉这些不被支持的操作层。这种方案并不总是可行的。但只要它可行,这就意味着我们不需要手工拆分网络结构图成多个部分,并在每个部分中间手工的添加实现不被支持的操作。

3135dbdef2c031c7da22992c52dc762e.png

下面的例子,我们将替换TensorFlow网络结构图中的,一种不被支持的操作,将它替换成一系列其他(支持的)操作。

在TensorFlow-Slim模型库中,有一种叫MobileNet的预先训练好的现成网络模型,这种模型使用了Relu6()操作层,而该操作/函数,并不被TensorRT支持。

但是,常规ReLU()函数和减法操作,可以被TensorRT支持。只要你意识到,ReLU()可以等价于这两种操作/运算的组合,我们就可以将ReLU6()替换成对应的子网络。

 我们直接对GraphDef进行修改,以完成这种替换。

 你可以看到如图的代码片段,我们循环遍历网络结构图中的所有节点,并判断如果它是ReLu6()运算, 那么我们先保存/标记它原本的输入和输出名,我们将一个等效的子网络结构图,同样使用刚才保存的输入和输出,然后这将原本主网络中的Relu6()节点替换成这个子图。

 注意我们之前说过的,这种方法并不能对网络中所有不被支持的操作生效。 想看到更多实现该网络修改的细节,请直接参考GitHub项目页面的convert_relu6.py这个Python模块代码。既然这TensorFlow网络结构图里面已经不再有任何不被支持的操作了,我们可以运行转换脚本来生成优化的推理引擎了。

c8634da0326fdebdf570c04082eb1f16.png

我们和之前一样,运行那个9个参数的python脚本,来生成优化的推理引擎。 只是这里我们可以确信了,只要用新的修改后冻结图文件作为输入,则转换脚本执行完成后,我们一定能得到优化的推理引擎,和能得到它序列化后保存到的文件。

8eb9ec23625f762b3af4b61f3a6f2696.png

 到这里就结束了如何用TensorRT来优化TensorFlow模型的讨论。(然后我再讲一点)如何执行你刚才生成的优化引擎。 在台式机上,推理引擎可以通过TensorRT的C++或者Python接口(API)来执行。然而在Jetson上,TensorRT没有提供Python接口,所以我们只能用C++来执行推理引擎。 首先用任何(你喜欢的)的方法,将序列化后的引擎数据,载入到内存。 这样就得到了一些二进制字节表示的我们的引擎。 然后,通过简单的一些TensorRT的(C++ )API调用,我们将可以反序列化该引擎,并创建ExecutionContext。引擎对象保存了网络中的常数,例如权重值;而ExecutionContext对象,则保存了每次调用会变化的的数据,例如网络的activations。

 一般来说,反序列化引擎,然后用它创建ExecutionContext对象,只需要进行一次。

 一旦我们从引擎对象创建好了ExecutionContext对象后,我们就能通过它一句话运行网络,进行推理了!,Yeah!但在运行引擎进行推理之前,我们需要确保,能正确读取要处理的图片,还需要保证图片格式正确。 你可以用任何方式获取/读取图片,但重要的是,你需要确保图片的格式和形状大小,变成该TensorRT推理引擎所期待的样子。 因此我们需要做一些简单的图像预处理工作,来格式化图片。这种工作可以通过CUDA或者C++来完成。 当图片格式转换好后,我们需要将图片像素内容传到显存,然后获取该图片在显存中的指针。 以及,还需要准备一个指向存放引擎推理结果内容的显存指针,

 两个指针一同在执行推理引擎的时候使用。 最后我们调用引擎,然后再做任何所需的后处理过程,例如将结果从显存复制回内存,然后在从结果中找到最大概率的类别索引。 

4841ac6ef02d043cd25a579129edcb2b.png

我们在GitHub上的代码库里,提供了一个范例程序,演示给你/能让你看如何执行推理引擎的过程。该范例程序,从磁盘读取序列化后的引擎文件,然后读取图像文件,预处理图片,然后调用TensorRT推理引擎。然后继续后续处理引擎的的执行结果,从中选出最可能的类别。

c192cce4a30e26daf12f347ebb6e79e4.png

本范例程序,分别以要被分类的图片、序列化后的引擎文件,以及其他参数作为输入。 只需在你从github上克隆到本地项目的根目录中,调用classify_image可执行文件,即可执行该程序。 执行后等一小会,就看看到程序打印出来了Top 5最可能的类别。 请注意!屏幕上这里显示的调用命令行只是用于演示目的。关于具体如何调用该范例程序,请参考GitHub上的代码库中的描述。

3ff7f55a06c08a16ad748bc9bf535625.png

好了,本次笔记所涉及知识点的资源都在此了,

但是注意!!这里有一个bug!,第5个地址应该是:https://github.com/NVIDIA-AI-IOT/tf_to_trt_image_classification 

a46b27b95fdbdd0ead630cafe28cae85.png

更多关于TensorRT:

来份TensorRT的教程,要实战的哟!

c79f26d182193a3095b794b4a978c189.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值