TorchScript使用的注意事项和常见错误
Pytorch1.3新出了移动端部署功能,想尝试一下,目前已将除安卓端部署以外的流程走通,但是因为pytorch量化不太好用,目前已经转向研究ONNX。
在这里分享一下使用torch.jit将Python代码转成TorchScript的过程中遇到的问题,希望能找到一起踩坑的朋友~
网上关于TorchScript的比较完整的资料并不多,我在留言提问的时候发现很多博主都已经弃坑了╮(╯▽╰)╭。而我因为不可抗力必须把这个坑趟下去,后续如果遇到更多的问题也会分享出来,如果有在研究TorchScript的朋友,欢迎与我交流。
注意事项
1. 如果代码中有`if`条件控制,尽量避免使用`torch.jit.trace`来转换代码,因为它不能处理变化条件,如果非要用`trace`的话,可以把`if`条件控制改成别的形式,比如:
def f(x):
if x > 0:
return False
else:
return True
可以改成:
def f(x):
return x <= 0
2. jit不能转换第三方Python库中的函数,尽量所有代码都使用pytorch实现,如果速度不理想的话,可以参考PyTorch官网的用C++自定义TorchScript算子的教程,用C++实现需要的功能,然后注册成jit操作,最后转成torchscript;
3. 如果要转Mobilenet,最好使用pytorch1.3以上,否则识别不出来其中的depth wise conv,转换出来的torchscript模型会比原模型大很多;
4. 模型的forward函数中尽量不要包含中文注释;
5. 函数的默认参数如果不是tensor的话,需要指定类型;
6. list中元素默认为tensor,如果不是,也要指定类型;
7. tensor.bool()操作不支持,可以直接用tensor>0来替代;
8. 不支持with语句;
9. 不支持花式赋值,比如下面这种:
[[pt1[0]], [pt1[1]]] = t
10. 如果在model的forward函数中调用了另一个model0,需要先在model的构造函数中将model0设为model的子模型;
11. 在TorchScript中,有一种Optional类型,举例:在一个函数中,如果可以通过if控制来返回None或者tensor,那么这个返回值会被认定为Optional[Tensor],这会导致无法对该返回值使用tensor的内置方法或属性,比如tensor.shape,tensor.size()等;
12. TorchScript中对tensor类型的要求严格得多,比如torch.tensor(1.0)这个变量会被默认为doubletensor,可能会在计算中出现错误;
13. TorchScript中带有梯度的零维张量无法当做标量进行计算,这个问题可能会在使用C++自定义TorchScript算子时遇到。
常见错误
ValueError: substring not found
forward函数中不允许出现中文注释
Module is not iterable(大概是这样的错误)
不支持模型遍历及对模型取下标的操作
torch.jit.frontend.UnsupportedNodeError: Dict aren’t supported
forward 函数里初始化字典,由 a={} 改成 a=dict(),不过dict类型尽量不要在forward中使用,容易出错
torch.jit.frontend.UnsupportedNodeError: continue statements aren’t supported
不支持continue
torch.jit.frontend.UnsupportedNodeError: try blocks aren’t supported
不支持try-except
Unknown builtin op: aten::Tensor
不能使用torch.Tensor(),如果是把python中的int,float等类型转成tensor可以使用torch.tensor()
- MySQL修改数据类型的问题总结(r10笔记第74天)
- 深究|Elasticsearch单字段支持的最大字符数?
- Go语言中Socket通信之Tcp客户端
- Oracle 12c PDB迁移及ORA-00600错误分析和解决(r10笔记第72天)
- 【Go 语言社区】epoll详解
- Oracle 12c数据库升级实战(r10笔记第70天)
- Oracle 12c升级检查问题分析(r10笔记第69天)
- 转--使用Revel(go)开发网站
- GoldenGate数据迁移的问题总结(二)(r10笔记第85天)
- Elasticsearch究竟要设置多少分片数?
- 设计模式(1)-使用简单工厂优化代码
- 简单易学的机器学习算法——因子分解机(Factorization Machine)
- Elasticsearch全文检索实战小结——复盘我带的第二个项目
- golang语言是如何处理栈的
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 固定QPS压测模式探索
- Centos6 网络配置的实例详解
- centos6.5升级安装配置supervisor的教程
- Linux的路由表详细介绍
- Centos7.3下vsftp服务的安装方法
- 详解Linux 安装 JDK、Tomcat 和 MySQL(图文并茂)
- 浅析Linux root设置初始值的方法
- 详解 Linux中的关机和重启命令
- 数据分析入门系列教程-KNN原理
- Selenium自动化的JUnit参数化实践
- linux云主机安装pdo详细教程
- Linux常用命令last的使用方法详解
- Linux命令搜索命令whereis与which的区别
- centos6.5服务器安装Nginx设置服务和开机自启的方法
- linux系统挂载数据盘的方法(视频图文教程)