将onnx的静态batch改为动态batch及修改输入输出层的名称
时间:2023-07-02 18:40:12来源:博客园


(资料图片)

目录背景操作修改输入输出层修改输入输出层名称完整代码背景

在模型的部署中,为了高效利用硬件算力,常常会需要将多个输入组成一个batch同时输入网络进行推理,这个batch的大小根据系统的负载或者摄像头的路数时刻在变化,因此网络的输入batch是在动态变化的。对于pytorch等框架来说,我们并不会感受到这个问题,因为整个网络在pytorch中都是动态的。而在实际的工程化部署中,为了运行效率,却并不能有这样的灵活性。可能会有人说,那我就把batch固定在一个最大值,然后输入实际的batch,这样实际上网络是以最大batch在推理的,浪费了算力。所以我们需要能支持动态的batch,能够根据输入的batch数来运行。

一个常见的训练到部署的路径是:pytorch→onnx→tensorrt。在pytorch导出onnx时,我们可以指定输出为动态的输入:

torch_out = torch.onnx.export(model, inp,                              save_path,input_names=["data"],output_names=["fc1"],dynamic_axes={        "data":{0:"batch_size"},"fc1":{0:"batch_size"}    })

而另一些时候,我们部署的模型来源于他人或开源模型,已经失去了原始的pytorch模型,此时如果onnx是静态batch的,在移植到tensorrt时,其输入就为静态输入了。想要动态输入,就需要对onnx模型本身进行修改了。另一方面,算法工程师在导模型的时候,如果没有指定输入层输出层的名称,导出的模型的层名有时候可读性比较差,比如输出是batchnorm_274这类名称,为了方便维护,也有需要对onnx的输入输出层名称进行修改。

操作修改输入输出层
def change_input_output_dim(model):    # Use some symbolic name not used for any other dimension    sym_batch_dim = "batch"    # The following code changes the first dimension of every input to be batch-dim    # Modify as appropriate ... note that this requires all inputs to    # have the same batch_dim     inputs = model.graph.input    for input in inputs:        # Checks omitted.This assumes that all inputs are tensors and have a shape with first dim.        # Add checks as needed.        dim1 = input.type.tensor_type.shape.dim[0]        # update dim to be a symbolic value        dim1.dim_param = sym_batch_dim        # or update it to be an actual value:        # dim1.dim_value = actual_batch_dim        outputs = model.graph.output    for output in outputs:        # Checks omitted.This assumes that all inputs are tensors and have a shape with first dim.        # Add checks as needed.        dim1 = output.type.tensor_type.shape.dim[0]        # update dim to be a symbolic value        dim1.dim_param = sym_batch_dimmodel = onnx.load(onnx_path)change_input_output_dim(model)

通过将输入层和输出层的shape的第一维修改为非数字,就可以将onnx模型改为动态batch。

修改输入输出层名称
def change_input_node_name(model, input_names):    for i,input in enumerate(model.graph.input):        input_name = input_names[i]        for node in model.graph.node:            for i, name in enumerate(node.input):                if name == input.name:                    node.input[i] = input_name        input.name = input_name        def change_output_node_name(model, output_names):    for i,output in enumerate(model.graph.output):        output_name = output_names[i]        for node in model.graph.node:            for i, name in enumerate(node.output):                if name == output.name:                    node.output[i] = output_name        output.name = output_name

代码中input_names和output_names是我们希望改到的名称,做法是遍历网络,若有node的输入层名与要修改的输入层名称相同,则改成新的输入层名。输出层类似。

完整代码
import onnxdef change_input_output_dim(model):    # Use some symbolic name not used for any other dimension    sym_batch_dim = "batch"    # The following code changes the first dimension of every input to be batch-dim    # Modify as appropriate ... note that this requires all inputs to    # have the same batch_dim     inputs = model.graph.input    for input in inputs:        # Checks omitted.This assumes that all inputs are tensors and have a shape with first dim.        # Add checks as needed.        dim1 = input.type.tensor_type.shape.dim[0]        # update dim to be a symbolic value        dim1.dim_param = sym_batch_dim        # or update it to be an actual value:        # dim1.dim_value = actual_batch_dim        outputs = model.graph.output    for output in outputs:        # Checks omitted.This assumes that all inputs are tensors and have a shape with first dim.        # Add checks as needed.        dim1 = output.type.tensor_type.shape.dim[0]        # update dim to be a symbolic value        dim1.dim_param = sym_batch_dimdef change_input_node_name(model, input_names):    for i,input in enumerate(model.graph.input):        input_name = input_names[i]        for node in model.graph.node:            for i, name in enumerate(node.input):                if name == input.name:                    node.input[i] = input_name        input.name = input_name        def change_output_node_name(model, output_names):    for i,output in enumerate(model.graph.output):        output_name = output_names[i]        for node in model.graph.node:            for i, name in enumerate(node.output):                if name == output.name:                    node.output[i] = output_name        output.name = output_nameonnx_path = ""save_path = ""model = onnx.load(onnx_path)change_input_output_dim(model)change_input_node_name(model, ["data"])change_output_node_name(model, ["fc1"])onnx.save(model, save_path)

经过修改后的onnx模型输入输出将成为动态batch,可以方便的移植到tensorrt等框架以支持高效推理。

标签:

最新
  • 将onnx的静态batch改为动态batch及修改输入输出层的名称

    [toc] 背景在模型的部署中,为了高效利用硬件算力,常常会需要将多个输

  • 交易商协会:用好“第二支箭”提升民营企业发债便利 环球微速讯

    交易商协会:用好“第二支箭”提升民营企业发债便利

  • 世界即时:2023年6月30日山东省乙二醇丁醚价格最新行情预测

    中国报告大厅2023年6月30日山东省乙二醇丁醚价格最新走势监测显示:宝

  • 【世界热闻】宁波色母:融资净买入15.78万元,融资余额2338.39万元(06-28)

    宁波色母融资融券信息显示,2023年6月28日融资净买入万元;融资余额万

  • “迪士尼有望落户武汉”是真是假?去迪士尼玩一次大概消费多少?|当前热闻

    迪士尼有望落户武汉是真是假?据湖北发布消息,近日有网友询问武汉市

  • 当前头条:欧洲冠军联赛和世界杯是什么比赛?穿红色衣服10号球衣的球星是谁?

    欧洲冠军联赛和世界杯是什么比赛?欧洲冠军联赛(UEFA Champions Le

  • 重庆钢铁: 2022年年度股东大会决议公告-微动态

    重庆钢铁:2022年年度股东大会决议公告

  • 经常吃完吐会引起胃癌吗?为什么胃癌一发现就活不了多久了?

    经常吃完吐会引起胃癌吗:你好,呕吐是胃癌的一个症状,但是经常吐

  • 【世界热闻】组建坏小子军团,灰熊3年8500万诚邀格林加盟,勇士队痛心疾首

    组建坏小子军团,灰熊3年8500万诚邀格林加盟,勇士队痛心疾首,库里,勇

  • 换手板和一字板有哪些不同?换手板的意思是什么?

    换手板和一字板有哪些不同?股票换手板和一字板的主要区别就是股票涨

  • 判断转基因食品的标准有哪些?吃转基因食品对人体有什么危害?|全球微头条

    判断转基因食品的标准有哪些?1、季节。除了大棚蔬菜外,其它的反季

  • 暑期临近,热门线路来了!

    暑期临近,热门线路来了!

  • 全球今亮点!中港照相(01123)将于9月6日派发末期股息每股0.01港元

    来源:智通财经中港照相(01123)发布公告,该公司将于2023年9月6日派发

  • 当前观察:天准科技:光伏镀铜图形化设备预计将在今年交付客户试用

    天准科技在互动平台表示,公司在2022年启动了光伏镀铜图形化设备的研发

  • 今日热搜:遂宁市肿瘤医院、遂宁市口腔医院揭牌仪式举行

    6月26日,遂宁市肿瘤医院、遂宁市口腔医院揭牌仪式举行,市委常委、秘

  • 郴州市17路公交车拒载

    郴州市17路公交车拒载投诉直通车是湖南日报、华声在线、新湖南主办的投

  • 旅游
    • 今年全国快递业务量已达600亿件-今日报

    • 累计产气超50亿立方米!“深海一号”投产两年成绩单——

    • 退休前医保一次性补缴20年,可以享受终身医保待遇划算吗?

    • 亿腾医药港交所递交招股书 当前速看