PyTorch模型定义

简介: 好久没更新了,2022年也过去快一半了,更文量还是不如前几年。近期会尝试加快更新的进度。本篇文章的更新内容是PyTorch模型的定义。

PyTorch模型定义

1. 前言

好久没更新了,2022年也过去快一半了,更文量还是不如前几年。近期会尝试加快更新的进度。

本篇文章的更新内容是PyTorch模型的定义。

2. PyTorch模型定义的方式

PyTorch-DataWhale.png

2.1. Sequential

Sequential 类可以通过更加简单的方式定义模型。它可以接收一个子模块的有序字典(OrderedDict) 或者一系列子模块作为参数来逐一添加 Module 的实例,⽽模型的前向计算就是将这些实例按添加的顺序逐⼀计算

Sequential定义源码:

torch.nn.modules.containerPyTorch1.11.0documentationclassSequential(Module):
r"""A sequential container.    Modules will be added to it in the order they are passed in the    constructor. Alternatively, an ``OrderedDict`` of modules can be    passed in. The ``forward()`` method of ``Sequential`` accepts any    input and forwards it to the first module it contains. It then    "chains" outputs to inputs sequentially for each subsequent module,    finally returning the output of the last module.    The value a ``Sequential`` provides over manually calling a sequence    of modules is that it allows treating the whole container as a    single module, such that performing a transformation on the    ``Sequential`` applies to each of the modules it stores (which are    each a registered submodule of the ``Sequential``).    What's the difference between a ``Sequential`` and a    :class:`torch.nn.ModuleList`? A ``ModuleList`` is exactly what it    sounds like--a list for storing ``Module`` s! On the other hand,    the layers in a ``Sequential`` are connected in a cascading way.    Example::        # Using Sequential to create a small model. When `model` is run,        # input will first be passed to `Conv2d(1,20,5)`. The output of        # `Conv2d(1,20,5)` will be used as the input to the first        # `ReLU`; the output of the first `ReLU` will become the input        # for `Conv2d(20,64,5)`. Finally, the output of        # `Conv2d(20,64,5)` will be used as input to the second `ReLU`        model = nn.Sequential(                  nn.Conv2d(1,20,5),                  nn.ReLU(),                  nn.Conv2d(20,64,5),                  nn.ReLU()                )        # Using Sequential with OrderedDict. This is functionally the        # same as the above code        model = nn.Sequential(OrderedDict([                  ('conv1', nn.Conv2d(1,20,5)),                  ('relu1', nn.ReLU()),                  ('conv2', nn.Conv2d(20,64,5)),                  ('relu2', nn.ReLU())                ]))    """_modules: Dict[str, Module]  # type: ignore[assignment]@overloaddef__init__(self, *args: Module) ->None:
        ...
@overloaddef__init__(self, arg: 'OrderedDict[str, Module]') ->None:
        ...
def__init__(self, *args):
super(Sequential, self).__init__()
iflen(args) ==1andisinstance(args[0], OrderedDict):
forkey, moduleinargs[0].items():
self.add_module(key, module)
else:
foridx, moduleinenumerate(args):
self.add_module(str(idx), module)

以上是节选的源码。

重点需要看的代码区域是:

def__init__(self, *args):
super(Sequential, self).__init__()
iflen(args) ==1andisinstance(args[0], OrderedDict):
forkey, moduleinargs[0].items():
self.add_module(key, module)
else:
foridx, moduleinenumerate(args):
self.add_module(str(idx), module)


由python基础知识可以知道,*args代表输入的参数可以是列表

所以,这个构造函数中的if len(args) == 1 and isinstance(args[0], OrderedDict):用来判断输入的参数是不是一个列表:

第一个判断条件是args的长度是否为1

第二个判断条件是isinstance(args[0], OrderedDict),判断传入的是不是一个OrderedDict

再次:

如果不是以上的情况,那么传入的就是一些Module,接着继续处理。

使用Sequential来定义模型。只需要将模型的层按序排列起来即可,根据层名的不同,排列的时候有两种方式:

2.1.1 使用OrderedDict

对应源码if len(args) == 1 and isinstance(args[0], OrderedDict):判断语句为真。

importcollectionimporttorch.nnasnnnet2=nn.Sequential(collections.OrderedDict([
          ('fc1', nn.Linear(784, 256)),
          ('relu1', nn.ReLU()),
          ('fc2', nn.Linear(256, 10))
          ]))
print(net2)


使用Sequential定义模型的好处在于简单、易读,同时使用Sequential定义的模型不需要再写forward,因为顺序已经定义好了。但使用Sequential也会使得模型定义丧失灵活性,比如需要在模型中间加入一个外部输入时就不适合用Sequential的方式实现。使用时需根据实际需求加以选择。

2.1.2 直接排列

对应源码if len(args) == 1 and isinstance(args[0], OrderedDict):判断语句为假,进入else语句部分

importtorch.nnasnnnet=nn.Sequential(
nn.Linear(784, 256),
nn.ReLU(),
nn.Linear(256, 10), 
        )
print(net)


2.2. ModuleList

对应模块为nn.ModuleList()

部分源码:

classModuleList(Module):
r"""Holds submodules in a list.    :class:`~torch.nn.ModuleList` can be indexed like a regular Python list, but    modules it contains are properly registered, and will be visible by all    :class:`~torch.nn.Module` methods.    Args:        modules (iterable, optional): an iterable of modules to add    Example::        class MyModule(nn.Module):            def __init__(self):                super(MyModule, self).__init__()                self.linears = nn.ModuleList([nn.Linear(10, 10) for i in range(10)])            def forward(self, x):                # ModuleList can act as an iterable, or be indexed using ints                for i, l in enumerate(self.linears):                    x = self.linears[i // 2](x) + l(x)                return x    """_modules: Dict[str, Module]  # type: ignore[assignment]def__init__(self, modules: Optional[Iterable[Module]] =None) ->None:
super(ModuleList, self).__init__()
ifmodulesisnotNone:
self+=modules


可以看到,ModuleList这个类实际上功能实现的比较简单。

ModuleList 接收一个子模块(或层,需属于nn.Module类)的列表作为输入,然后也可以类似List那样进行appendextend操作。同时,子模块或层的权重也会自动添加到网络中来。

net=nn.ModuleList([nn.Linear(784, 256), nn.ReLU()])
net.append(nn.Linear(256, 10)) # # 类似List的append操作print(net[-1])  # 类似List的索引访问print(net)


nn.ModuleList 并没有定义一个网络,它只是将不同的模块储存在一起。ModuleList中元素的先后顺序并不代表其在网络中的真实位置顺序,需要经过forward函数指定各个层的先后顺序后才算完成了模型的定义。具体实现时用for循环即可完成.

classmodel(nn.Module):
def__init__(self, ...):
super().__init__()
self.modulelist= ...
    ...
defforward(self, x):
forlayerinself.modulelist:
x=layer(x)
returnx

2.3. ModuleDict

对应模块为nn.ModuleDict()

ModuleDictModuleList的作用类似,只是ModuleDict能够更方便地为神经网络的层添加名称。

部分源码:

classModuleDict(Module):
r"""Holds submodules in a dictionary.    :class:`~torch.nn.ModuleDict` can be indexed like a regular Python dictionary,    but modules it contains are properly registered, and will be visible by all    :class:`~torch.nn.Module` methods.    :class:`~torch.nn.ModuleDict` is an **ordered** dictionary that respects    * the order of insertion, and    * in :meth:`~torch.nn.ModuleDict.update`, the order of the merged      ``OrderedDict``, ``dict`` (started from Python 3.6) or another      :class:`~torch.nn.ModuleDict` (the argument to      :meth:`~torch.nn.ModuleDict.update`).    Note that :meth:`~torch.nn.ModuleDict.update` with other unordered mapping    types (e.g., Python's plain ``dict`` before Python version 3.6) does not    preserve the order of the merged mapping.    Args:        modules (iterable, optional): a mapping (dictionary) of (string: module)            or an iterable of key-value pairs of type (string, module)    Example::        class MyModule(nn.Module):            def __init__(self):                super(MyModule, self).__init__()                self.choices = nn.ModuleDict({                        'conv': nn.Conv2d(10, 10, 3),                        'pool': nn.MaxPool2d(3)                })                self.activations = nn.ModuleDict([                        ['lrelu', nn.LeakyReLU()],                        ['prelu', nn.PReLU()]                ])            def forward(self, x, choice, act):                x = self.choices[choice](x)                x = self.activations[act](x)                return x    """_modules: Dict[str, Module]  # type: ignore[assignment]def__init__(self, modules: Optional[Mapping[str, Module]] =None) ->None:
super(ModuleDict, self).__init__()
ifmodulesisnotNone:
self.update(modules)

实例:

net=nn.ModuleDict({
'linear': nn.Linear(784, 256),
'act': nn.ReLU(),
})
net['output'] =nn.Linear(256, 10) # 添加print(net['linear']) # 访问print(net.output)
print(net)

3. 方式的区别

Sequential适用于快速验证结果,因为已经明确了要用哪些层,直接写一下就好了,不需要同时写__init__forward

ModuleListModuleDict在某个完全相同的层需要重复出现多次时,非常方便实现,可以”一行顶多行“;

当我们需要之前层的信息的时候,比如 ResNets 中的残差计算,当前层的结果需要和之前层中的结果进行融合,一般使用 ModuleList/ModuleDict 比较方便。

参考资料

5.1 PyTorch模型定义的方式 — 深入浅出PyTorch (datawhalechina.github.io)

Sequential — PyTorch 1.11.0 documentation

torch.nn.modules.container — PyTorch 1.11.0 documentation

ModuleList — PyTorch 1.11.0 documentation

torch.nn.modules.container — PyTorch 1.11.0 documentation

ModuleDict — PyTorch 1.11.0 documentation

torch.nn.modules.container — PyTorch 1.11.0 documentation


目录
相关文章
|
2月前
|
算法 PyTorch 算法框架/工具
Pytorch学习笔记(九):Pytorch模型的FLOPs、模型参数量等信息输出(torchstat、thop、ptflops、torchsummary)
本文介绍了如何使用torchstat、thop、ptflops和torchsummary等工具来计算Pytorch模型的FLOPs、模型参数量等信息。
373 2
|
22天前
|
机器学习/深度学习 人工智能 PyTorch
Transformer模型变长序列优化:解析PyTorch上的FlashAttention2与xFormers
本文探讨了Transformer模型中变长输入序列的优化策略,旨在解决深度学习中常见的计算效率问题。文章首先介绍了批处理变长输入的技术挑战,特别是填充方法导致的资源浪费。随后,提出了多种优化技术,包括动态填充、PyTorch NestedTensors、FlashAttention2和XFormers的memory_efficient_attention。这些技术通过减少冗余计算、优化内存管理和改进计算模式,显著提升了模型的性能。实验结果显示,使用FlashAttention2和无填充策略的组合可以将步骤时间减少至323毫秒,相比未优化版本提升了约2.5倍。
41 3
Transformer模型变长序列优化:解析PyTorch上的FlashAttention2与xFormers
|
2月前
|
机器学习/深度学习 自然语言处理 监控
利用 PyTorch Lightning 搭建一个文本分类模型
利用 PyTorch Lightning 搭建一个文本分类模型
71 8
利用 PyTorch Lightning 搭建一个文本分类模型
|
2月前
|
机器学习/深度学习 自然语言处理 数据建模
三种Transformer模型中的注意力机制介绍及Pytorch实现:从自注意力到因果自注意力
本文深入探讨了Transformer模型中的三种关键注意力机制:自注意力、交叉注意力和因果自注意力,这些机制是GPT-4、Llama等大型语言模型的核心。文章不仅讲解了理论概念,还通过Python和PyTorch从零开始实现这些机制,帮助读者深入理解其内部工作原理。自注意力机制通过整合上下文信息增强了输入嵌入,多头注意力则通过多个并行的注意力头捕捉不同类型的依赖关系。交叉注意力则允许模型在两个不同输入序列间传递信息,适用于机器翻译和图像描述等任务。因果自注意力确保模型在生成文本时仅考虑先前的上下文,适用于解码器风格的模型。通过本文的详细解析和代码实现,读者可以全面掌握这些机制的应用潜力。
127 3
三种Transformer模型中的注意力机制介绍及Pytorch实现:从自注意力到因果自注意力
|
3月前
|
机器学习/深度学习 PyTorch 调度
在Pytorch中为不同层设置不同学习率来提升性能,优化深度学习模型
在深度学习中,学习率作为关键超参数对模型收敛速度和性能至关重要。传统方法采用统一学习率,但研究表明为不同层设置差异化学习率能显著提升性能。本文探讨了这一策略的理论基础及PyTorch实现方法,包括模型定义、参数分组、优化器配置及训练流程。通过示例展示了如何为ResNet18设置不同层的学习率,并介绍了渐进式解冻和层适应学习率等高级技巧,帮助研究者更好地优化模型训练。
210 4
在Pytorch中为不同层设置不同学习率来提升性能,优化深度学习模型
|
3月前
|
机器学习/深度学习 监控 PyTorch
PyTorch 模型调试与故障排除指南
在深度学习领域,PyTorch 成为开发和训练神经网络的主要框架之一。本文为 PyTorch 开发者提供全面的调试指南,涵盖从基础概念到高级技术的内容。目标读者包括初学者、中级开发者和高级工程师。本文探讨常见问题及解决方案,帮助读者理解 PyTorch 的核心概念、掌握调试策略、识别性能瓶颈,并通过实际案例获得实践经验。无论是在构建简单神经网络还是复杂模型,本文都将提供宝贵的洞察和实用技巧,帮助开发者更高效地开发和优化 PyTorch 模型。
56 3
PyTorch 模型调试与故障排除指南
|
2月前
|
存储 并行计算 PyTorch
探索PyTorch:模型的定义和保存方法
探索PyTorch:模型的定义和保存方法
|
4月前
|
机器学习/深度学习 PyTorch 编译器
PyTorch 与 TorchScript:模型的序列化与加速
【8月更文第27天】PyTorch 是一个非常流行的深度学习框架,它以其灵活性和易用性而著称。然而,当涉及到模型的部署和性能优化时,PyTorch 的动态计算图可能会带来一些挑战。为了解决这些问题,PyTorch 引入了 TorchScript,这是一个用于序列化和优化 PyTorch 模型的工具。本文将详细介绍如何使用 TorchScript 来序列化 PyTorch 模型以及如何加速模型的执行。
173 4
|
4月前
|
机器学习/深度学习 边缘计算 PyTorch
PyTorch 与边缘计算:将深度学习模型部署到嵌入式设备
【8月更文第29天】随着物联网技术的发展,越来越多的数据处理任务开始在边缘设备上执行,以减少网络延迟、降低带宽成本并提高隐私保护水平。PyTorch 是一个广泛使用的深度学习框架,它不仅支持高效的模型训练,还提供了多种工具帮助开发者将模型部署到边缘设备。本文将探讨如何将PyTorch模型高效地部署到嵌入式设备上,并通过一个具体的示例来展示整个流程。
782 1
|
4月前
|
机器学习/深度学习 自然语言处理 PyTorch
PyTorch与Hugging Face Transformers:快速构建先进的NLP模型
【8月更文第27天】随着自然语言处理(NLP)技术的快速发展,深度学习模型已经成为了构建高质量NLP应用程序的关键。PyTorch 作为一种强大的深度学习框架,提供了灵活的 API 和高效的性能,非常适合于构建复杂的 NLP 模型。Hugging Face Transformers 库则是目前最流行的预训练模型库之一,它为 PyTorch 提供了大量的预训练模型和工具,极大地简化了模型训练和部署的过程。
248 2