LibtorchTutorials icon indicating copy to clipboard operation
LibtorchTutorials copied to clipboard

使用libtorch训练的pt模型是否能导出onnx

Open ximitiejiang opened this issue 2 years ago • 13 comments

你好,考虑到模型加速的问题,请问下使用libtorch训练得到的pt模型,如何导出onnx?或者如何直接通过tensorRT加速?

ximitiejiang avatar Jun 13 '22 10:06 ximitiejiang

能,预先生成同样模型的onnx,把权重赋值进去即可

AllentDan avatar Jun 13 '22 12:06 AllentDan

感谢您的回复,我尝试了下libtorch训练出来的分类模型,发现在推理这块有几个不同的思路:

  1. 直接用libtorch这套指令,比如如下的方式 torch::load(model, path); model.forward();` 这种方式是把权重加载到已经有代码结构的model上面,推理的速度非常慢(resnet18分类模型都需要k+ms) 这种方式跟python的方式基本没有什么区别。

  2. 另外看到一种利用torch::jit的指令,比如 torch::jit::Module model = torch::jit::load(path); model.forward(); 这种方式不需要用代码先定义模型结构,加载了就可以跑,在速度上可以通过torch-tensorrt库加速。这种方式我理解就属于torchscript模型了,通过pytorch的torch.jit.trace/script导出的模型可以这样操作。但我发现libtorch训练后用torch::save()模型没法用这个指令加载,那就应该需要把libtorch训练的模型也进行一次jit.trace或者jit.script导出?但这个操作用libtorch的c++ api能完成吗?毕竟都已经用libtorch训练了,就不想再用python做ts模型导出了

  3. 您提到的方式,那就要先用pytorch/python构建这个模型,然后导出onnx,然后要把libtorch训练得到的torchscript模型权重赋值到onnx模型,不知道有没有合适的demo可以参考?

希望libtorch训练的模型能够真正部署到应用场景、运行速度也能跟onnx模型部署相当,但感觉这块的资料不太多,还请多指教

ximitiejiang avatar Jun 20 '22 12:06 ximitiejiang

  1. 也就比python快一些些,主要是满足某些c++项目
  2. 没试过,也可以拷贝权重,然后torch-tensorrt加速,可行性应该也ok。
  3. 没demo,这种要花时间,都没时间弄。但是可行性是验证过的。

AllentDan avatar Jun 21 '22 02:06 AllentDan

尝试了两个简单思路:

  1. 用libtorch训练出pt模型(该模型也验证过可以在libtorch中做推理),然后尝试在python中用torch.jit.load()加载该pt模型,该步加载可以成功,但jit_model.forward()会报错,AttributeError: 'RecursiveScriptModule' object has no attribute 'forward',看了下导入的这个jit模型在pycharm的变量栏中forward()函数显示为找不到,对应模型子模块也是同样问题(encoder/header),其他正常jit模型都应该有相应的forward函数。

  2. 用libtorch训练出pt模型,重新通过libtorch的torch::jit::load()加载,forward()同样报错;把该pt模型送入torch_tensorrt做compile转换能够成功得到trt_model,但推理同样报错。 auto device = torch::Device(torch::kCUDA, 0); auto image = cv::imread("D:\\suliang\\My_Dataset\\misc\\cat.jpg"); cv::resize(image, image, cv::Size(512, 512)); auto input_tensor = torch::from_blob(image.data, { image.rows, image.cols, 3 }, torch::kByte).permute({ 2, 0, 1 }).unsqueeze(0).to(torch::kFloat32) / 255.0; torch::jit::Module model = torch::jit::load("clas_model_20220419123718_iter13000_acc0.973592.pt"); model.to(device); model.eval(); auto output = model.forward({ input_tensor.to(device) }).toTensor(); output = torch::softmax(output, 1); 貌似经过libtorch训练后保存得到的torchscript模型跟一般torchscript模型有差异导致。不知道您那边是否有遇到这种情况,还是我这边保存的ts模型有问题?(在github/pytorch论坛上也看到类似issue,但没有解决方案)

  3. 关于您前面提到的torchscript转onnx手动通过权重赋值进去的方式,不知道可行性验证怎么证明,我想这么弄但感觉找不到着手点

ximitiejiang avatar Jun 22 '22 03:06 ximitiejiang

这些问题都有遇到,libtorch的api搭建出的网络如果直接torch::save的话确实不同于jit模型,本质上也是不同的类其实。可行性OK是我了解到有公司是这样做的,但是我目前没有demo开源出来。

AllentDan avatar Jun 22 '22 04:06 AllentDan

翻了半天的libtorch论坛,就看到这个: image

我理解下来libtorch c++的定位就是用来部署torchscript,而libtorch c++训练出来的模型基本没有什么途径转为静态图的部署模型,甚至不能转自家的torchscript模型,那封装出来这些训练相关的api到底有什么实际用处,太不理解了? 把libtorch保存的pt模型要转换到真正的torchscript或者onnx,除了权重要转,还有op这种东西都要转,而pt的文件结构又不清楚,难度不是一般大啊,大佬给点思路啊,要不然真的只能弃疗了~

ximitiejiang avatar Jun 22 '22 09:06 ximitiejiang

onnx模型预先是保存好的,结构和libtorch的一致,然后权重更新进去。固定了模型就没几行代码

AllentDan avatar Jun 22 '22 09:06 AllentDan

而且也可以写得通用,只是预先要有onnx模型文件。

AllentDan avatar Jun 22 '22 09:06 AllentDan

onnx模型我在python里边预先建好了也可以导出来,onnx的proto结构也是可以查到,但libtorch的这种pt模型结构是什么样的呢,我尝试探索了下libtorch_model的结构,发现libtorch_model.graph都解析不出来...

ximitiejiang avatar Jun 22 '22 09:06 ximitiejiang

我也没具体代码,只知道可行性.....最近都没时间弄这些。遍历下api吧

AllentDan avatar Jun 22 '22 09:06 AllentDan

哦,pt模型是个压缩文件,可以解压缩... image 不知道是不是要把data.pkl跟data文件夹里边的东西解析出来...

ximitiejiang avatar Jun 22 '22 09:06 ximitiejiang

可以代码解决的问题.....自己探索下吧

AllentDan avatar Jun 22 '22 09:06 AllentDan

ok,感谢! 我先研究下~

ximitiejiang avatar Jun 22 '22 09:06 ximitiejiang

thanks

ximitiejiang avatar Nov 01 '22 12:11 ximitiejiang

issue 貌似到现在还没有支持

DennisJcy avatar May 29 '23 13:05 DennisJcy