torch.Tensor.repeat()
转换#
%cd ../../..
import set_env
from d2py.utils.file import mkdir
temp_dir = ".temp"
mkdir(temp_dir)
/media/pc/data/lxw/ai/tvm-book/doc/tutorials/frontend
import torch
from torch import nn
class Model(nn.Module):
def forward(self, x):
return x.repeat(3, 3, 4)
shape = 3, 1, 4
x = torch.rand(*shape)
torch_model = Model()
# 导出模型
output_name = "repeat"
torch.onnx.export(
torch_model, # torch 模型
x, # 模型输入或者对于多个输入,使用元组
f"{temp_dir}/{output_name}.onnx", # 模型保存的位置(可以是文件或类似文件的对象)
export_params=True, # 将训练后的参数权重存储在模型文件内
opset_version=17, # 导出模型的 ONNX 版本
do_constant_folding=True, # 是否执行常量折叠以进行优化
input_names = ['data'], # 模型的输入名称
output_names = ['output'], # 模型的输出名称
verbose=True,
# dynamic_axes={'data' : {0 : 'batch_size'}, # 可变长度的轴
# 'output' : {0 : 'batch_size'}}
)
Exported graph: graph(%data : Float(3, 1, 4, strides=[4, 4, 1], requires_grad=0, device=cpu)):
%onnx::Tile_1 : Long(3, strides=[1], device=cpu) = onnx::Constant[value= 3 3 4 [ CPULongType{3} ]]()
%/Constant_output_0 : Long(1, strides=[1], requires_grad=0, device=cpu) = onnx::Constant[value={3}, onnx_name="/Constant"](), scope: __main__.Model:: # /tmp/ipykernel_1020703/3833725313.py:6:0
%/ConstantOfShape_output_0 : Long(3, strides=[1], device=cpu) = onnx::ConstantOfShape[value={1}, onnx_name="/ConstantOfShape"](%/Constant_output_0), scope: __main__.Model:: # /tmp/ipykernel_1020703/3833725313.py:6:0
%/Expand_output_0 : Float(3, 1, 4, strides=[4, 4, 1], device=cpu) = onnx::Expand[onnx_name="/Expand"](%data, %/ConstantOfShape_output_0), scope: __main__.Model:: # /tmp/ipykernel_1020703/3833725313.py:6:0
%output : Float(9, 3, 16, strides=[48, 16, 1], requires_grad=0, device=cpu) = onnx::Tile[onnx_name="/Tile"](%/Expand_output_0, %onnx::Tile_1), scope: __main__.Model:: # /tmp/ipykernel_1020703/3833725313.py:6:0
return (%output)
# onnx_program = torch.onnx.dynamo_export(torch_model, x)
# onnx_program.save("test_dynamo.onnx")
import onnx
import tvm
from tvm import relay
onnx_model = onnx.load(f"{temp_dir}/{output_name}.onnx")
mod, params = relay.frontend.from_onnx(onnx_model, {"data": shape}, freeze_params=True)
with tvm.transform.PassContext(opt_level=3):
mod = relay.quantize.prerequisite_optimize(mod, params)
mod.show()
def @main(%data: Tensor[(3, 1, 4), float32] /* ty=Tensor[(3, 1, 4), float32] span=/Expand.data:0:0 */) -> Tensor[(9i64, 3i64, 16i64), float32] {
%0 = broadcast_to(%data, shape=[3i64, 1i64, 4i64]) /* ty=Tensor[(3i64, 1i64, 4i64), float32] span=/Expand:0:0 */;
tile(%0, reps=[3i64, 3i64, 4i64]) /* ty=Tensor[(9i64, 3i64, 16i64), float32] span=/Tile:0:0 */
}
with tvm.transform.PassContext(opt_level=3):
with relay.quantize.qconfig(
skip_conv_layers=[],
# calibrate_mode="kl_divergence",
weight_scale="max",
round_for_shift=True,
# rounding="TONEAREST", # "UPWARD" or "TONEAREST"
# calibrate_skip_layers=[],
skip_dense_layer=False,
):
qmod = relay.quantize.quantize(mod, params)
qmod.show()
def @main(%data: Tensor[(3, 1, 4), float32] /* ty=Tensor[(3, 1, 4), float32] span=/Expand.data:0:0 */) -> Tensor[(9i64, 3i64, 16i64), float32] {
%0 = broadcast_to(%data, shape=[3i64, 1i64, 4i64]) /* ty=Tensor[(3i64, 1i64, 4i64), float32] span=/Expand:0:0 */;
tile(%0, reps=[3i64, 3i64, 4i64]) /* ty=Tensor[(9i64, 3i64, 16i64), float32] span=/Tile:0:0 */
}