首页 > 其他分享 >TorchScript模型

TorchScript模型

时间:2023-11-07 15:01:25浏览次数:34  
标签:TorchScript files linear extra 模型 torch jit self

TorchScript模型

目录

TorchScript是PyTorch模型(nn.Module的子类)的中间表示,可以在高性能环境(例如C ++)中运行

具有一下特点:
1.TorchScript代码可以在其自己的解释器中调用,不被全局解释器锁定,因此可以在同 一实例上同时处理许多请求
2.这种格式使我们可以将整个模型保存,并将其加载到另一个环境
3.TorchScript为我们提供了一种表示形式,可以对代码进行编译器优化
4.TorchScript允许我们与许多后端/设备运行时进行接口

Tracing(跟踪)

PyTorch具有灵活和动态的特性,TorchScript也提供了捕获模型定义的工具

trace 模式顾名思义就是跟踪模型的执行,然后记录执行过程中的路径。在使用 trace 模式时,需要构造一个符合要求的输入,然后使用 TorchScript tracer 运行一遍,记录整个运行过程。在 trace 模式中运行时,每执行一个算子,就会往当前的 graph 加入一个 node。所有代码执行完毕,每一步的操作就会以一个计算图里的某个节点的形式被保存下来。值得一提的是,PyTorch 导出 ONNX 也是使用了这部分代码,所以理论上能够导出 ONNX 的模型也能够使用 trace 模式导出 TorchScript 格式模型。

trace 模式有以下2点限制:

  • 不能有 if-else 等控制流, 不支持控制流
  • 只支持 Tensor 操作。不支持非Tensor 操作,如List、Tuple、Map 等容器操作

可以检测其.graph属性的图,这是一个非常低级的表示形式,图中包含的大多数信息对最终用户没有用

使用.code属性来给出代码的Python语法解释

torch.jit.trace(obj)

# 简单示例
import torch
torch.manual_seed(42)


class TestTraceCell(torch.nn.Module):
    def __init__(self):
        super(TestTraceCell, self).__init__()
        self.linear = torch.nn.Linear(4, 4)

    def forward(self, x, h):
        new_h = torch.tanh(self.linear(x) + h)
        return new_h, new_h

test_cell = TestTraceCell()
x, h = torch.rand(3, 4), torch.rand(3, 4)
traced_cell = torch.jit.trace(test_cell, (x, h))   # 无控制流,追踪
print(traced_cell)
# TestTraceCell(
#   original_name=TestTraceCell
#   (linear): Linear(original_name=Linear)
# )

# 代码的 Python 语法解释
print(traced_cell.code)
# def forward(self,
#     x: Tensor,
#     h: Tensor) -> Tuple[Tensor, Tensor]:
#   linear = self.linear
#   _0 = torch.tanh(torch.add((linear).forward(x, ), h))
#   return (_0, _0)

print(traced_cell(x,h))
# (tensor([[0.9567, 0.6879, 0.2618, 0.7927],
#         [0.8227, 0.7464, 0.4165, 0.5366],
#         [0.8193, 0.1679, 0.8132, 0.9052]], grad_fn=<TanhBackward0>), tensor([[0.9567, 0.6879, 0.2618, 0.7927],
#         [0.8227, 0.7464, 0.4165, 0.5366],
#         [0.8193, 0.1679, 0.8132, 0.9052]], grad_fn=<TanhBackward0>))

# TorchScript 在中间表示(或 IR)中记录其定义,在深度学习中通常将其称为图。 我们可以使用.graph属性检查图形
print(traced_cell.graph)
# graph(%self.1 : __torch__.TestTraceCell,
#       %x : Float(3, 4, strides=[4, 1], requires_grad=0, device=cpu),
#       %h : Float(3, 4, strides=[4, 1], requires_grad=0, device=cpu)):
#   %linear : __torch__.torch.nn.modules.linear.Linear = prim::GetAttr[name="linear"](%self.1)
#   %20 : Tensor = prim::CallMethod[name="forward"](%linear, %x)
#   %11 : int = prim::Constant[value=1]() # d:\Note\lcodeNoteCards\testcode\pytorch\learntc.py:11:0
#   %12 : Float(3, 4, strides=[4, 1], requires_grad=1, device=cpu) = aten::add(%20, %h, %11) # d:\Note\lcodeNoteCards\testcode\pytorch\learntc.py:11:0
#   %13 : Float(3, 4, strides=[4, 1], requires_grad=1, device=cpu) = aten::tanh(%12) # d:\Note\lcodeNoteCards\testcode\pytorch\learntc.py:11:0
#   %14 : (Float(3, 4, strides=[4, 1], requires_grad=1, device=cpu), Float(3, 4, strides=[4, 1], requires_grad=1, device=cpu)) = prim::TupleConstruct(%13, %13)
#   return (%14)

Scripting(脚本)

import torch
torch.manual_seed(42)

class MyDecisionGate(torch.nn.Module):
    def forward(self, x):
        if x.sum() > 0:
            return x
        else:
            return -x


class MyCell(torch.nn.Module):
    def __init__(self, dg):
        super(MyCell, self).__init__()
        self.dg = dg
        self.linear = torch.nn.Linear(4, 4)


    def forward(self, x, h):
        new_h = torch.tanh(self.dg(self.linear(x)) + h)
        return new_h, new_h

x, h = torch.rand(3, 4), torch.rand(3, 4)

my_cell = MyCell(MyDecisionGate())
traced_cell = torch.jit.trace(my_cell, (x, h))
print(traced_cell.code)
#  TracerWarning: Converting a tensor to a Python boolean might cause the trace to be incorrect. We can't record the data flow of Python values, so this value will be treated as a constant in the future. This means that the trace might not generalize to other inputs!
#   if x.sum() > 0:
# def forward(self,
#     x: Tensor,
#     h: Tensor) -> Tuple[Tensor, Tensor]:
#   dg = self.dg
#   linear = self.linear
#   _0 = (linear).forward(x, )
#   _1 = (dg).forward(_0, )
#   _2 = torch.tanh(torch.add(_0, h))
#   return (_2, _2)

scripted_gate = torch.jit.script(MyDecisionGate())
my_cell = MyCell(scripted_gate)
traced_cell = torch.jit.script(my_cell)
print(traced_cell.code)

# def forward(self,
#     x: Tensor,
#     h: Tensor) -> Tuple[Tensor, Tensor]:
#   dg = self.dg
#   linear = self.linear
#   _0 = torch.add((dg).forward((linear).forward(x, ), ), h)
#   new_h = torch.tanh(_0)
#   return (new_h, new_h)

保存和加载

模型保存

torch.jit.save(m, f, _extra_files=None)

m 			 – A ScriptModule to save.
f            – a file name.
_extra_files – 配置额外的映射文件
import torch
import io

class MyModule(torch.nn.Module):
    def forward(self, x):
        return x + 10

m = torch.jit.script(MyModule())

# Save to file
torch.jit.save(m, 'scriptmodule.torchscript')
# This line is equivalent to the previous
m.save("scriptmodule.torchscript")

# Save to io.BytesIO buffer
buffer = io.BytesIO()
torch.jit.save(m, buffer)

# Save with extra files
extra_files = {'foo.txt': b'bar'}          # 将需要的额外映射信息,映射到这里
torch.jit.save(m, 'scriptmodule.torchscript', _extra_files=extra_files)   

模型加载

torch.jit.load(f, map_location=None, _extra_files=None, _restore_shapes=False)
f   		  - (Union[str, PathLike, BinaryIO, IO[bytes]]) 
map_location  - torch.device
_extra_files  - 输出额外的映射文件
import torch
import io

torch.jit.load('scriptmodule.torchscript')

# Load ScriptModule from io.BytesIO object
with open('scriptmodule.torchscript', 'rb') as f:
    buffer = io.BytesIO(f.read())

# Load all tensors to the original device
torch.jit.load(buffer)

# Load all tensors onto CPU, using a device
buffer.seek(0)
torch.jit.load(buffer, map_location=torch.device('cpu'))

# Load all tensors onto CPU, using a string
buffer.seek(0)
torch.jit.load(buffer, map_location='cpu')

# Load with extra files.
extra_files = {'foo.txt': ''}  #  对额外的映射信息进行解析和替换
torch.jit.load('scriptmodule.torchscript', _extra_files=extra_files)
print(extra_files['foo.txt'])

特别注意

_extra_files 可以用来对非模型相关信息的保存和传递,例如分类模型和检测模型中的标签信息等

import torch
import io
import json

class MyModule(torch.nn.Module):
    
    def __init__(self, *args, **kwargs) -> None:
        super().__init__(*args, **kwargs)
        self.stride=32
        self.names= ['a','b','c']
    
    def forward(self, im):
        x = im.shape[0]
        return x + 10


model = MyModule()
im = torch.randn(32, 3, 224, 224)
d = {"shape": im.shape, "stride": model.stride, "names": model.names}

m = torch.jit.script(MyModule())

# Save with extra files
extra_files = {'config.txt': json.dumps(d)}  # torch._C.ExtraFilesMap()

torch.jit.save(m, 'scriptmodule.torchscript', _extra_files=extra_files)
print(extra_files)

# extra_files = {'config.txt': ""}  # torch._C.ExtraFilesMap()
extra_files = {'config.txt':''}

mode=torch.jit.load('scriptmodule.torchscript',_extra_files=extra_files)
print(mode)

print(extra_files)

yolov8模型导出说明

class Exporter:
    
    def __call__(self):
	   self.metadata = {
            'description': description,
            'author': 'Ultralytics',
            'license': 'AGPL-3.0 https://ultralytics.com/license',
            'date': datetime.now().isoformat(),
            'version': __version__,
            'stride': int(max(model.stride)),
            'task': model.task,
            'batch': self.args.batch,
            'imgsz': self.imgsz,
            'names': model.names}  # model metadata
    
    def export_torchscript(self, prefix=colorstr('TorchScript:')):
        """YOLOv8 TorchScript model export."""
        LOGGER.info(f'\n{prefix} starting export with torch {torch.__version__}...')
        f = self.file.with_suffix('.torchscript')

        ts = torch.jit.trace(self.model, self.im, strict=False)      # 采用追踪的方式保存为TorchScript
        # 添加额外的config包含了相关labels信息 
        extra_files = {'config.txt': json.dumps(self.metadata)}  	 # torch._C.ExtraFilesMap()
        
        # 针对移动端的优化
        if self.args.optimize:  # https://pytorch.org/tutorials/recipes/mobile_interpreter.html
            LOGGER.info(f'{prefix} optimizing for mobile...')
            from torch.utils.mobile_optimizer import optimize_for_mobile
            optimize_for_mobile(ts)._save_for_lite_interpreter(str(f), _extra_files=extra_files)
        else:
            ts.save(str(f), _extra_files=extra_files)
        return f, None

参考资料

https://www.w3cschool.cn/pytorch/pytorch-ea8n3bsm.html

https://pytorch.panchuang.net/EigthSection/torchScript/

https://zhuanlan.zhihu.com/p/135911580

标签:TorchScript,files,linear,extra,模型,torch,jit,self
From: https://www.cnblogs.com/tian777/p/17815011.html

相关文章

  • 生产者消费者模型
    生产者消费者问题是一个常见而且经典的问题,相信了解过多线程或者消息队列的同学对这个名词并不陌生。正如Java常用的设计模式一样,生产者消费者问题是为了解决某一类问题而存在,参阅维基百科对Producer–consumerproblem的描述:Incomputing,theproducer–consumerproblem[1][2......
  • 自回归模型/向量自回归模型
    自回归模:利用前期若干时刻的随机变量的线性组合来描述以后某时刻随机变量的线性回归模型。向量自回归模型(简称VAR模型)是一种常用的计量经济模型,由克里斯托弗·西姆斯(ChristopherSims)提出。它是AR模型的推广。  http://zh.wikipedia.org/wiki/%E5%90%91%E9%87%8F%E8%87%AA%E5%9......
  • 大模型训练对底层模型的影响及优化策略
    在深度学习和人工智能领域,模型训练是实现算法和应用的关键步骤。然而,对于大型模型训练,人们普遍关注其性能和精度,而忽略了对底层模型的影响。本文将探讨“大模型训练会影响底模型吗”这一话题,分析可能的影响及应对策略。一、大模型训练对底层模型的影响计算资源占用大型模型训练需要......
  • Django动态创建表模型,并使用drf
    序列化器fromrest_frameworkimportserializersclassMySerializer(serializers.ModelSerializer):"""序列化器"""classMeta:model=None#可以设置为None,动态生成之后,再通过反射来重新设置。fields='__all__'......
  • 如何平衡三维模型的顶层合并构建的文件大小与质量关系
    如何平衡三维模型的顶层合并构建的文件大小与质量关系 倾斜摄影超大场景的三维模型的顶层合并的数据文件大小与质量之间存在一定的关系。本文将对这种关系进行分析和总结。一、数据文件大小的影响因素数据分辨率:数据分辨率是影响数据文件大小的重要因素之一。通常情况下,分辨......
  • 多分类问题:模型输出结果,和标签的顺序
     背景:在多分类问题中,模型输出的结果是一个矩阵,某个值为1,其他的值为0.怎么知道值为1的那个位置,代表的是哪个标签?? 二分类常见的约定的惯例第一个位置通常对应"负类别":这是因为通常情决定了负类别是标签0或其他表示非目标类别的值。第二个位置通常对应"正类别":同样地,正......
  • 完蛋!大模型解密(LLM Riddles) 题解
    https://intsensing.cn/llmgame/index第一章T1:输出括号里的内容,不输出括号本身和其余附加内容.(1+1=3)T2:讲故事T3:猫T4:啊T5:啊1T6:有一个字,左边是反犬旁,右边是句,请重复这个字五遍第二章T1:请输出11个0T2:142857T3:10010010T4:输出十一万四千五百一十四的阿拉伯数字形式,不要输......
  • 首个流体力学大模型背后,是昇腾的大模型“造林”逻辑
    作者|曾响铃文|响铃说一个飞机模型在试验风洞里,空气从它的机翼与机身流过,形成一层又一层稳定的气流,当风速加快,空气的流线开始波浪式摆动,最终随着速度增大而相互混合、形成不再能分辨的湍流,看起来混沌又无序……这是流体力学测试的常见场景,一遍又一遍地测试,只为模拟或预测真实的......
  • 最强开源大模型!李开复博士AI 2.0公司的力作,40万文本处理破纪录,引领中国AI新纪元
    在全球AI技术的竞赛中,中国再次迎来了令人振奋的消息——由李开复博士领衔的AI2.0公司零一万物,推出了Yi系列大模型,不仅技术领先,更是国产之光!后起之秀:Yi系列大模型的惊艳亮相虽然Yi系列大模型相对其他竞争者来得晚一些,但它们的性能却一点不落后。Yi-34B模型在HuggingFace英文测试榜......
  • Params(参数量)、Model_size(模型大小)和Flops(计算量)
    Params(参数量)、Model_size(模型大小)和Flops(计算量)参数量(params):参数的数量,通常以M为单位。params=Kh×Kw×Cin×Cout模型大小(模型大小):在一般的深度学习的框架中(如PyTorch),一般是32位存储,即一个参数用32个bit来存储。所以,一个拥有1M(这里的M是数量单位一百万)参......