30.md 7.6 KB
Newer Older
W
wizardforcel 已提交
1 2 3 4 5 6 7 8
# torch.onnx

`torch.onnx`模块包含将模型导出为`ONNX IR`格式的功能。这些模型可以加载`ONNX`库,然后转换为在其他深度学习框架上运行的模型。 ![ONNX](2017121722000236815.jpg)

### 示例:从 PyTorch 到 Caffe2 的端到端的 AlexNet

这是一个简单的脚本,将`torchvision`中定义的预训练的`AlexNet`导出到`ONNX`中。它运行一轮推理,然后将结果跟踪模型保存到`alexnet.proto`

W
wizardforcel 已提交
9
```py
W
wizardforcel 已提交
10 11 12 13 14 15 16 17 18 19 20
from torch.autograd import Variable
import torch.onnx
import torchvision

dummy_input = Variable(torch.randn(10, 3, 224, 224)).cuda()
model = torchvision.models.alexnet(pretrained=True).cuda()
torch.onnx.export(model, dummy_input, "alexnet.proto", verbose=True) 
```

保存文件`alexnet.proto`是一个二进制`protobuf`文件,其中包含您导出的模型(在本例中为`AlexNet`)的网络结构和参数。关键字参数`verbose=True`导致导出器打印出一个人类可读的网络表示:

W
wizardforcel 已提交
21
```py
W
wizardforcel 已提交
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
# All parameters are encoded explicitly as inputs.  By convention,
# learned parameters (ala nn.Module.state_dict) are first, and the
# actual inputs are last.
graph(%1 : Float(64, 3, 11, 11)
      %2 : Float(64)
      # The definition sites of all variables are annotated with type
      # information, specifying the type and size of tensors.
      # For example, %3 is a 192 x 64 x 5 x 5 tensor of floats.
      %3 : Float(192, 64, 5, 5)
      %4 : Float(192)
      # ---- omitted for brevity ----
      %15 : Float(1000, 4096)
      %16 : Float(1000)
      %17 : Float(10, 3, 224, 224)) { # the actual input!
  # Every statement consists of some output tensors (and their types),
  # the operator to be run (with its attributes, e.g., kernels, strides,
  # etc.), its input tensors (%17, %1)
  %19 : UNKNOWN_TYPE = Conv[kernels=[11, 11], strides=[4, 4], pads=[2, 2, 2, 2], dilations=[1, 1], group=1](%17, %1), uses = [[%20.i0]];
  # UNKNOWN_TYPE: sometimes type information is not known.  We hope to eliminate
  # all such cases in a later release.
  %20 : Float(10, 64, 55, 55) = Add[broadcast=1, axis=1](%19, %2), uses = [%21.i0];
  %21 : Float(10, 64, 55, 55) = Relu(%20), uses = [%22.i0];
  %22 : Float(10, 64, 27, 27) = MaxPool[kernels=[3, 3], pads=[0, 0, 0, 0], dilations=[1, 1], strides=[2, 2]](%21), uses = [%23.i0];
  # ...
  # Finally, a network returns some tensors
  return (%58);
} 
```

您也可以使用[onnx](https://github.com/onnx/onnx/)库来验证`protobuf`。你可以`onnx``conda`安装:

W
wizardforcel 已提交
53
```py
W
wizardforcel 已提交
54 55 56 57 58
conda install -c conda-forge onnx 
```

然后,你可以运行:

W
wizardforcel 已提交
59
```py
W
wizardforcel 已提交
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
import onnx

# Load the ONNX model
model = onnx.load("alexnet.proto")

# Check that the IR is well formed
onnx.checker.check_model(model)

# Print a human readable representation of the graph
onnx.helper.printable_graph(model.graph) 
```

要用`caffe2`运行导出的脚本,您将需要三件事情:

*   1、您需要安装`Caffe2`。如果您还没有,请 按照安装说明进行操作。

*   2、你需要`onnx-caffe2`,一个纯`Python`库,为`ONNX`提供一个`Caffe2`后端。`onnx-caffe2`你可以用`pip`来安装:

W
wizardforcel 已提交
78
```py
W
wizardforcel 已提交
79 80 81 82 83
pip install onnx-caffe2 
```

安装完成后,您可以使用`Caffe2`的后端:

W
wizardforcel 已提交
84
```py
W
wizardforcel 已提交
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
# ...continuing from above
import onnx_caffe2.backend as backend
import numpy as np

rep = backend.prepare(model, device="CUDA:0") # or "CPU"
# For the Caffe2 backend:
#     rep.predict_net is the Caffe2 protobuf for the network
#     rep.workspace is the Caffe2 workspace for the network
#       (see the class onnx_caffe2.backend.Workspace)
outputs = rep.run(np.random.randn(10, 3, 224, 224).astype(np.float32))
# To run networks with more than one input, pass a tuple
# rather than a single numpy ndarray.
print(outputs[0]) 
```

未来,其他框架也会有后端。

### 限制与不足

*   `ONNX`出口是一个基于跟踪的出口,这意味着它通过执行一次模型来运行,并导出在此运行期间实际运行的运营商。这意味着如果您的模型是动态的,例如,根据输入数据改变行为,则导出将不准确。类似地,跟踪可能仅对特定输入大小有效(这是我们为什么需要明确输入跟踪的一个原因)。我们建议检查模型跟踪并确保跟踪的运算符看起来合理。
*   `PyTorch``Caffe2`通常具有一些数字差异的操作符的实现。根据模型结构的不同,这些差异可能是微不足道的,但是它们也会造成行为上的重大分歧(特别是在未经训练的模型上)。在未来的版本中,我们计划让`Caffe2`直接调用操作员的`Torch`实现,以帮助您平滑在精度很重要的时候处理这些差异,并记录这些差异。

### 支持的运算函数

支持以下运算符: `add (nonzero alpha not supported)`,`sub (nonzero alpha not supported)`,`mul`,`div`,`cat`,`mm`,`addmm`,`neg`,`tanh`,`sigmoid`,`mean`,`t`,`expand (only when used before a broadcasting ONNX operator; e.g. add)`,`transpose`,`view`,`split`,`squeeze`,`prelu (single weight shared among input channels not supported)`,`threshold (non-zero threshold/non-zero value not supported)`,`leaky_relu`,`glu`,`softmax`,`avg_pool2d (ceil_mode not supported)`,`log_softmax`,`unfold (experimental support with ATen-Caffe2 integration)`,`elu`,`Conv`,`BatchNorm`,`MaxPool1d (ceil_mode not supported)`,`MaxPool2d (ceil_mode not supported)`,`MaxPool3d (ceil_mode not supported)`,`Embedding (no optional arguments supported)`,`RNN`,`ConstantPadNd`,`Dropout`,`FeatureDropout (training mode not supported)`,`Index (constant integer and tuple indices supported)`,`Negate`

以上设置的操作足以导出以下型号: `AlexNet`,`DCGAN`,`DenseNet`,`Inception (warning: this model is highly sensitive to changes in operator implementation)`,`ResNet`,`SuperResolution`,`VGG`,`word_language_model`

用于指定运算符定义的界面是高度实验性的,并且没有记录; 有冒险精神的用户应该注意,这些`API`可能会在未来的界面中发生变化。

### torch.onnx 功能

W
wizardforcel 已提交
117
```py
W
wizardforcel 已提交
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
torch.onnx.export(model, args, f, export_params=True, verbose=False, training=False) 
```

将模型导出为`ONNX`格式。这个导出器运行你的模型一次,以获得其导出的执行轨迹; 目前,它不支持动态模型(例如,`RNN`)。

另见:`onnx-export`

#### 参数:

*   模型(`torch.nn.Module`) - 要导出的模型。
*   args(参数元组) - 模型的输入,例如,这-model(*args)是模型的有效调用。任何非变量参数将被硬编码到导出的模型中; 任何变量参数都将成为输出模型的输入,按照它们在参数中出现的顺序。如果 args 是一个变量,这相当于用该变量的一个元组来调用它。(注意:将关键字参数传递给模型目前还不支持,如果需要,给我们留言。)

*   f - 类文件对象(必须实现返回文件描述符的 fileno)或包含文件名的字符串。一个二进制 Protobuf 将被写入这个文件。

*   export_params(布尔,默认为 True) - 如果指定,所有参数将被导出。如果要导出未经训练的模型,请将其设置为 False。在这种情况下,导出的模型将首先将其所有参数作为参数,按照指定的顺序 model.state_dict().values()

*   verbose(布尔,默认为 False) - 如果指定,我们将打印出一个调试描述的导出轨迹。

*   training(布尔,默认为 False) - 在训练模式下导出模型。目前,ONNX 只是为了推导出口模型,所以你通常不需要将其设置为 True。

### 译者署名

| 用户名 | 头像 | 职能 | 签名 |
| --- | --- | --- | --- |
| [Song](https://ptorch.com) | ![](img/2018033000352689884.jpeg) | 翻译 | 人生总要追求点什么 |