Pytorch模型中的parameter与buffer用法

 更新时间:2021年06月01日 11:24:27   作者:CV/NLP大虾  
这篇文章主要介绍了Pytorch模型中的parameter与buffer用法,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

Parameter 和 buffer

If you have parameters in your model, which should be saved and restored in the state_dict, but not trained by the optimizer, you should register them as buffers.Buffers won't be returned in model.parameters(), so that the optimizer won't have a change to update them.

模型中需要保存下来的参数包括两种

一种是反向传播需要被optimizer更新的,称之为 parameter

一种是反向传播不需要被optimizer更新,称之为 buffer

第一种参数我们可以通过 model.parameters() 返回;第二种参数我们可以通过 model.buffers() 返回。因为我们的模型保存的是 state_dict 返回的 OrderDict,所以这两种参数不仅要满足是否需要被更新的要求,还需要被保存到OrderDict。

那么现在的问题是这两种参数如何创建呢,创建好了如何保存到OrderDict呢?

第一种参数有两种方式

我们可以直接将模型的成员变量(http://self.xxx) 通过nn.Parameter() 创建,会自动注册到parameters中,可以通过model.parameters() 返回,并且这样创建的参数会自动保存到OrderDict中去;

通过nn.Parameter() 创建普通Parameter对象,不作为模型的成员变量,然后将Parameter对象通过register_parameter()进行注册,可以通model.parameters() 返回,注册后的参数也会自动保存到OrderDict中去;

第二种参数我们需要创建tensor

然后将tensor通过register_buffer()进行注册,可以通model.buffers() 返回,注册完后参数也会自动保存到OrderDict中去。

Pytorch中Module,Parameter和Buffer区别

下文都将torch.nn简写成nn

Module: 就是我们常用的torch.nn.Module类,你定义的所有网络结构都必须继承这个类。

Buffer: buffer和parameter相对,就是指那些不需要参与反向传播的参数

示例如下:

class MyModel(nn.Module):
 def __init__(self):
  super(MyModel, self).__init__()
  self.my_tensor = torch.randn(1) # 参数直接作为模型类成员变量
  self.register_buffer('my_buffer', torch.randn(1)) # 参数注册为 buffer
  self.my_param = nn.Parameter(torch.randn(1))
 def forward(self, x):
  return x 

model = MyModel()
print(model.state_dict())
>>>OrderedDict([('my_param', tensor([1.2357])), ('my_buffer', tensor([-0.9982]))])
Parameter: 是nn.parameter.Paramter,也就是组成Module的参数。例如一个nn.Linear通常由weight和bias参数组成。它的特点是默认requires_grad=True,也就是说训练过程中需要反向传播的,就需要使用这个
import torch.nn as nn
fc = nn.Linear(2,2)

# 读取参数的方式一
fc._parameters
>>> OrderedDict([('weight', Parameter containing:
              tensor([[0.4142, 0.0424],
                      [0.3940, 0.0796]], requires_grad=True)),
             ('bias', Parameter containing:
              tensor([-0.2885,  0.5825], requires_grad=True))])
     
# 读取参数的方式二(推荐这种)
for n, p in fc.named_parameters():
 print(n,p)
>>>weight Parameter containing:
tensor([[0.4142, 0.0424],
        [0.3940, 0.0796]], requires_grad=True)
bias Parameter containing:
tensor([-0.2885,  0.5825], requires_grad=True)

# 读取参数的方式三
for p in fc.parameters():
 print(p)
>>>Parameter containing:
tensor([[0.4142, 0.0424],
        [0.3940, 0.0796]], requires_grad=True)
Parameter containing:
tensor([-0.2885,  0.5825], requires_grad=True)

通过上面的例子可以看到,nn.parameter.Paramter的requires_grad属性值默认为True。另外上面例子给出了三种读取parameter的方法,推荐使用后面两种,因为是以迭代生成器的方式来读取,第一种方式是一股脑的把参数全丢给你,要是模型很大,估计你的电脑会吃不消。

另外需要介绍的是_parameters是nn.Module在__init__()函数中就定义了的一个OrderDict类,这个可以通过看下面给出的部分源码看到,可以看到还初始化了很多其他东西,其实原理都大同小异,你理解了这个之后,其他的也是同样的道理。

class Module(object):
 ...
    def __init__(self):
        self._backend = thnn_backend
        self._parameters = OrderedDict()
        self._buffers = OrderedDict()
        self._backward_hooks = OrderedDict()
        self._forward_hooks = OrderedDict()
        self._forward_pre_hooks = OrderedDict()
        self._state_dict_hooks = OrderedDict()
        self._load_state_dict_pre_hooks = OrderedDict()
        self._modules = OrderedDict()
        self.training = True

每当我们给一个成员变量定义一个nn.parameter.Paramter的时候,都会自动注册到_parameters,具体的步骤如下:

import torch.nn as nn
class MyModel(nn.Module):
 def __init__(self):
  super(MyModel, self).__init__()
  # 下面两种定义方式均可
  self.p1 = nn.paramter.Paramter(torch.tensor(1.0))
  print(self._parameters)
  self.p2 = nn.Paramter(torch.tensor(2.0))
  print(self._parameters)

首先运行super(MyModel, self).__init__(),这样MyModel就初始化了_paramters等一系列的OrderDict,此时所有变量还都是空的。

self.p1 = nn.paramter.Paramter(torch.tensor(1.0)): 这行代码会触发nn.Module预定义好的__setattr__函数,该函数部分源码如下:

def __setattr__(self, name, value):
 ...
 params = self.__dict__.get('_parameters')
 if isinstance(value, Parameter):
  if params is None:
   raise AttributeError(
    "cannot assign parameters before Module.__init__() call")
  remove_from(self.__dict__, self._buffers, self._modules)
  self.register_parameter(name, value)
 ...

__setattr__函数作用简单理解就是判断你定义的参数是否正确,如果正确就继续调用register_parameter函数进行注册,这个函数简单概括就是做了下面这件事

def register_parameter(self,name,param):
 ...
 self._parameters[name]=param

下面我们实例化这个模型看结果怎样

model = MyModel()
>>>OrderedDict([('p1', Parameter containing:
tensor(1., requires_grad=True))])
OrderedDict([('p1', Parameter containing:
tensor(1., requires_grad=True)), ('p2', Parameter containing:
tensor(2., requires_grad=True))])

结果和上面分析的一致。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 简单介绍Ruby中的CGI编程

    简单介绍Ruby中的CGI编程

    这篇文章主要介绍了简单介绍Ruby中的CGI编程,包括创建Form表单等基本内容,需要的朋友可以参考下
    2015-04-04
  • Python多项式回归的实现方法

    Python多项式回归的实现方法

    这篇文章主要介绍了Python多项式回归的实现方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-03-03
  • Python 流媒体播放器的实现(基于VLC)

    Python 流媒体播放器的实现(基于VLC)

    这篇文章主要介绍了Python 流媒体播放器的实现(基于VLC),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-04-04
  • Python关于迭代器的使用

    Python关于迭代器的使用

    这篇文章主要介绍了Python关于迭代器的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-06-06
  • 一文搞懂Python读取text,CSV,JSON文件的方法

    一文搞懂Python读取text,CSV,JSON文件的方法

    文件处理是一种用于创建文件、写入数据和从中读取数据的过程,Python 拥有丰富的用于处理不同文件类型的包,从而使得我们可以更加轻松方便的完成文件处理的工作,本文将来为大家详细讲讲
    2022-06-06
  • Python叠加矩形框图层2种方法及效果

    Python叠加矩形框图层2种方法及效果

    这篇文章主要介绍了Python叠加矩形框图层2种方法及效果,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-06-06
  • python抓取最新博客内容并生成Rss

    python抓取最新博客内容并生成Rss

    本文给大家分享的是使用python抓取最新博客内容并生成Rss的代码,主要用到了PyRSS2Gen方法,非常的简单实用,有需要的小伙伴可以参考下。
    2015-05-05
  • 初探利用Python进行图文识别(OCR)

    初探利用Python进行图文识别(OCR)

    这篇文章主要介绍了初探利用Python进行图文识别(OCR),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-02-02
  • Numpy数组的广播机制的实现

    Numpy数组的广播机制的实现

    这篇文章主要介绍了Numpy数组的广播机制的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11
  • tensorboard 可以显示graph,却不能显示scalar的解决方式

    tensorboard 可以显示graph,却不能显示scalar的解决方式

    今天小编就为大家分享一篇tensorboard 可以显示graph,却不能显示scalar的解决方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-02-02

最新评论