精华内容
下载资源
问答
  • 2019-01-01 19:20:34

    Pytorch 中retain_graph的用法

    用法分析

    在查看SRGAN源码时有如下损失函数,其中设置了retain_graph=True,其作用是什么?

    
    		############################
            # (1) Update D network: maximize D(x)-1-D(G(z))
            ###########################
            real_img = Variable(target)
            if torch.cuda.is_available():
                real_img = real_img.cuda()
            z = Variable(data)
            if torch.cuda.is_available():
                z = z.cuda()
            fake_img = netG(z)
    
            netD.zero_grad()
            real_out = netD(real_img).mean()
            fake_out = netD(fake_img).mean()
            d_loss = 1 - real_out + fake_out
            d_loss.backward(retain_graph=True) #####
            optimizerD.step()
    
            ############################
            # (2) Update G network: minimize 1-D(G(z)) + Perception Loss + Image Loss + TV Loss
            ###########################
            netG.zero_grad()
            g_loss = generator_criterion(fake_out, fake_img, real_img)
            g_loss.backward()
            optimizerG.step()
            fake_img = netG(z)
            fake_out = netD(fake_img).mean()
    
            g_loss = generator_criterion(fake_out, fake_img, real_img)
            running_results['g_loss'] += g_loss.data[0] * batch_size
            d_loss = 1 - real_out + fake_out
            running_results['d_loss'] += d_loss.data[0] * batch_size
            running_results['d_score'] += real_out.data[0] * batch_size
            running_results['g_score'] += fake_out.data[0] * batch_size
    

    ​ 在更新D网络时的loss反向传播过程中使用了retain_graph=True,目的为是为保留该过程中计算的梯度,后续G网络更新时使用;

    其实retain_graph这个参数在平常中我们是用不到的,但是在特殊的情况下我们会用到它,

    如下代码:

    import torch
    y=x**2
    z=y*4
    output1=z.mean()
    output2=z.sum()
    output1.backward()
    output2.backward()
    

    输出如下错误信息:

    ---------------------------------------------------------------------------
    RuntimeError                              Traceback (most recent call last)
    <ipython-input-19-8ad6b0658906> in <module>()
    ----> 1 output1.backward()
          2 output2.backward()
    
    D:\ProgramData\Anaconda3\lib\site-packages\torch\tensor.py in backward(self, gradient, retain_graph, create_graph)
         91                 products. Defaults to ``False``.
         92         """
    ---> 93         torch.autograd.backward(self, gradient, retain_graph, create_graph)
         94 
         95     def register_hook(self, hook):
    
    D:\ProgramData\Anaconda3\lib\site-packages\torch\autograd\__init__.py in backward(tensors, grad_tensors, retain_graph, create_graph, grad_variables)
         88     Variable._execution_engine.run_backward(
         89         tensors, grad_tensors, retain_graph, create_graph,
    ---> 90         allow_unreachable=True)  # allow_unreachable flag
         91 
         92 
    
    RuntimeError: Trying to backward through the graph a second time, but the buffers have already been freed. Specify retain_graph=True when calling backward the first time.
    

    修改成如下正确:

    import torch
    y=x**2
    z=y*4
    output1=z.mean()
    output2=z.sum()
    output1.backward(retain_graph=True)
    output2.backward()
    
    # 假如你有两个Loss,先执行第一个的backward,再执行第二个backward
    loss1.backward(retain_graph=True)
    loss2.backward() # 执行完这个后,所有中间变量都会被释放,以便下一次的循环
    optimizer.step() # 更新参数
    

    Variable 类源代码

    class Variable(_C._VariableBase):
     
        """
        Attributes:
            data: 任意类型的封装好的张量。
            grad: 保存与data类型和位置相匹配的梯度,此属性难以分配并且不能重新分配。
            requires_grad: 标记变量是否已经由一个需要调用到此变量的子图创建的bool值。只能在叶子变量上进行修改。
            volatile: 标记变量是否能在推理模式下应用(如不保存历史记录)的bool值。只能在叶变量上更改。
            is_leaf: 标记变量是否是图叶子(如由用户创建的变量)的bool值.
            grad_fn: Gradient function graph trace.
     
        Parameters:
            data (any tensor class): 要包装的张量.
            requires_grad (bool): bool型的标记值. **Keyword only.**
            volatile (bool): bool型的标记值. **Keyword only.**
        """
     
        def backward(self, gradient=None, retain_graph=None, create_graph=None, retain_variables=None):
            """计算关于当前图叶子变量的梯度,图使用链式法则导致分化
            如果Variable是一个标量(例如它包含一个单元素数据),你无需对backward()指定任何参数
            如果变量不是标量(包含多个元素数据的矢量)且需要梯度,函数需要额外的梯度;
            需要指定一个和tensor的形状匹配的grad_output参数(y在指定方向投影对x的导数);
            可以是一个类型和位置相匹配且包含与自身相关的不同函数梯度的张量。
            函数在叶子上累积梯度,调用前需要对该叶子进行清零。
     
            Arguments:
                grad_variables (Tensor, Variable or None):
                               变量的梯度,如果是一个张量,除非“create_graph”是True,否则会自动转换成volatile型的变量。
                               可以为标量变量或不需要grad的值指定None值。如果None值可接受,则此参数可选。
                retain_graph (bool, optional): 如果为False,用来计算梯度的图将被释放。
                                               在几乎所有情况下,将此选项设置为True不是必需的,通常可以以更有效的方式解决。
                                               默认值为create_graph的值。
                create_graph (bool, optional): 为True时,会构造一个导数的图,用来计算出更高阶导数结果。
                                               默认为False,除非``gradient``是一个volatile变量。
            """
            torch.autograd.backward(self, gradient, retain_graph, create_graph, retain_variables)
     
     
        def register_hook(self, hook):
            """Registers a backward hook.
     
            每当与variable相关的梯度被计算时调用hook,hook的申明:hook(grad)->Variable or None
            不能对hook的参数进行修改,但可以选择性地返回一个新的梯度以用在`grad`的相应位置。
     
            函数返回一个handle,其``handle.remove()``方法用于将hook从模块中移除。
     
            Example:
                >>> v = Variable(torch.Tensor([0, 0, 0]), requires_grad=True)
                >>> h = v.register_hook(lambda grad: grad * 2)  # double the gradient
                >>> v.backward(torch.Tensor([1, 1, 1]))
                >>> v.grad.data
                 2
                 2
                 2
                [torch.FloatTensor of size 3]
                >>> h.remove()  # removes the hook
            """
            if self.volatile:
                raise RuntimeError("cannot register a hook on a volatile variable")
            if not self.requires_grad:
                raise RuntimeError("cannot register a hook on a variable that "
                                   "doesn't require gradient")
            if self._backward_hooks is None:
                self._backward_hooks = OrderedDict()
                if self.grad_fn is not None:
                    self.grad_fn._register_hook_dict(self)
            handle = hooks.RemovableHandle(self._backward_hooks)
            self._backward_hooks[handle.id] = hook
            return handle
     
        def reinforce(self, reward):
            """Registers a reward obtained as a result of a stochastic process.
            区分随机节点需要为他们提供reward值。如果图表中包含任何的随机操作,都应该在其输出上调用此函数,否则会出现错误。
            Parameters:
                reward(Tensor): 带有每个元素奖赏的张量,必须与Variable数据的设备位置和形状相匹配。
            """
            if not isinstance(self.grad_fn, StochasticFunction):
                raise RuntimeError("reinforce() can be only called on outputs "
                                   "of stochastic functions")
            self.grad_fn._reinforce(reward)
     
        def detach(self):
            """返回一个从当前图分离出来的心变量。
            结果不需要梯度,如果输入是volatile,则输出也是volatile。
     
            .. 注意::
              返回变量使用与原始变量相同的数据张量,并且可以看到其中任何一个的就地修改,并且可能会触发正确性检查中的错误。
            """
            result = NoGrad()(self)  # this is needed, because it merges version counters
            result._grad_fn = None
            return result
     
        def detach_(self):
            """从创建它的图中分离出变量并作为该图的一个叶子"""
            self._grad_fn = None
            self.requires_grad = False
     
        def retain_grad(self):
            """Enables .grad attribute for non-leaf Variables."""
            if self.grad_fn is None:  # no-op for leaves
                return
            if not self.requires_grad:
                raise RuntimeError("can't retain_grad on Variable that has requires_grad=False")
            if hasattr(self, 'retains_grad'):
                return
            weak_self = weakref.ref(self)
     
            def retain_grad_hook(grad):
                var = weak_self()
                if var is None:
                    return
                if var._grad is None:
                    var._grad = grad.clone()
                else:
                    var._grad = var._grad + grad
     
            self.register_hook(retain_grad_hook)
            self.retains_grad = True
    

    参考

    https://oldpan.me/archives/pytorch-retain_graph-work

    https://www.cnblogs.com/hellcat/p/8449031.html

    更多相关内容
  • torch.Tensor.retain_grad()的使用举例

    千次阅读 2021-01-21 12:22:30
    参考链接: torch.Tensor.retain_grad() 原文及翻译: retain_grad() 方法: retain_grad() Enables .grad attribute for non-leaf Tensors. 对非叶节点(即中间节点张量)张量启用用于保存梯度的属性(.grad). (译者...

    参考链接: torch.Tensor.retain_grad()

    在这里插入图片描述
    原文及翻译:

    retain_grad()
    方法: retain_grad()
        Enables .grad attribute for non-leaf Tensors.
        对非叶节点(即中间节点张量)张量启用用于保存梯度的属性(.grad).
        (译者注: 默认情况下对于非叶节点张量是禁用该属性grad,计算完梯度之后就被
        释放回收内存,不会保存中间结果的梯度.)
    

    实验代码展示:

    Microsoft Windows [版本 10.0.18363.1316]
    (c) 2019 Microsoft Corporation。保留所有权利。
    
    C:\Users\chenxuqi>conda activate ssd4pytorch1_2_0
    
    (ssd4pytorch1_2_0) C:\Users\chenxuqi>python
    Python 3.7.7 (default, May  6 2020, 11:45:54) [MSC v.1916 64 bit (AMD64)] :: Anaconda, Inc. on win32
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import torch
    >>> torch.manual_seed(seed=20200910)
    <torch._C.Generator object at 0x000001CDB4A5D330>
    >>> data_in = torch.randn(3,5,requires_grad=True)
    >>> data_in
    tensor([[ 0.2824, -0.3715,  0.9088, -1.7601, -0.1806],
            [ 2.0937,  1.0406, -1.7651,  1.1216,  0.8440],
            [ 0.1783,  0.6859, -1.5942, -0.2006, -0.4050]], requires_grad=True)
    >>> data_mean = data_in.mean()
    >>> data_mean
    tensor(0.0585, grad_fn=<MeanBackward0>)
    >>> data_in.requires_grad
    True
    >>> data_mean.requires_grad
    True
    >>> data_1 = data_mean * 20200910.0
    >>> data_1
    tensor(1182591., grad_fn=<MulBackward0>)
    >>> data_2 = data_1 * 15.0
    >>> data_2
    tensor(17738864., grad_fn=<MulBackward0>)
    >>> data_2.retain_grad()
    >>> data_3 = 2 * (data_2 + 55.0)
    >>> loss = data_3 / 2.0 +89.2
    >>> loss
    tensor(17739010., grad_fn=<AddBackward0>)
    >>>
    >>> data_in.grad
    >>> data_mean.grad
    >>> data_1.grad
    >>> data_2.grad
    >>> data_3.grad
    >>> loss.grad
    >>> print(data_in.grad, data_mean.grad, data_1.grad, data_2.grad, data_3.grad, loss.grad)
    None None None None None None
    >>>
    >>> loss.backward()
    >>> data_in.grad
    tensor([[20200910., 20200910., 20200910., 20200910., 20200910.],
            [20200910., 20200910., 20200910., 20200910., 20200910.],
            [20200910., 20200910., 20200910., 20200910., 20200910.]])
    >>> data_mean.grad
    >>> data_mean.grad
    >>> data_1.grad
    >>> data_2.grad
    tensor(1.)
    >>> data_3.grad
    >>> loss.grad
    >>>
    >>>
    >>> print(data_in.grad, data_mean.grad, data_1.grad, data_2.grad, data_3.grad, loss.grad)
    tensor([[20200910., 20200910., 20200910., 20200910., 20200910.],
            [20200910., 20200910., 20200910., 20200910., 20200910.],
            [20200910., 20200910., 20200910., 20200910., 20200910.]]) None None tensor(1.) None None
    >>>
    >>>
    >>> print(data_in.is_leaf, data_mean.is_leaf, data_1.is_leaf, data_2.is_leaf, data_3.is_leaf, loss.is_leaf)
    True False False False False False
    >>>
    >>>
    >>>
    
    展开全文
  • 8.3747, 4.1625, -7.0606], [ 4.4866, 3.3759, 0.7133, 2.7435]], grad_fn=) >>> >>> torch.set_grad_enabled(False) # 以函数调用的方式来使用 <torch.autograd.grad_mode.set_grad_enabled object at 0x...

    参考链接: Locally disabling gradient computation-1
    参考链接: Locally disabling gradient computation-2
    参考链接: class torch.autograd.no_grad的使用举例
    参考链接: class torch.autograd.enable_grad的使用举例
    参考链接: class torch.autograd.set_grad_enabled(mode: bool)的使用举例

    在这里插入图片描述
    在这里插入图片描述

    原文及翻译:

    Locally disabling gradient computation
    在局部区域内关闭(禁用)梯度的计算.
    
    The context managers torch.no_grad(), torch.enable_grad(), 
    and torch.set_grad_enabled() are helpful for locally disabling 
    and enabling gradient computation. See Locally disabling gradient 
    computation for more details on their usage. These context 
    managers are thread local, so they won’t work if you send 
    work to another thread using the threading module, etc.
    上下文管理器torch.no_grad()、torch.enable_grad()和
    torch.set_grad_enabled()可以用来在局部范围内启用或禁用梯度计算.
    在Locally disabling gradient computation章节中详细介绍了
    局部禁用梯度计算的使用方式.这些上下文管理器具有线程局部性,
    因此,如果你使用threading模块来将工作负载发送到另一个线程,
    这些上下文管理器将不会起作用.
    
    
    
    no_grad   Context-manager that disabled gradient calculation.
    no_grad   用于禁用梯度计算的上下文管理器.
    
    enable_grad  Context-manager that enables gradient calculation.
    enable_grad  用于启用梯度计算的上下文管理器.
    
    set_grad_enabled  Context-manager that sets gradient calculation to on or off.
    set_grad_enabled  用于设置梯度计算打开或关闭状态的上下文管理器.
    

    例子1:

    Microsoft Windows [版本 10.0.18363.1440]
    (c) 2019 Microsoft Corporation。保留所有权利。
    
    C:\Users\chenxuqi>conda activate pytorch_1.7.1_cu102
    
    (pytorch_1.7.1_cu102) C:\Users\chenxuqi>python
    Python 3.7.9 (default, Aug 31 2020, 17:10:11) [MSC v.1916 64 bit (AMD64)] :: Anaconda, Inc. on win32
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import torch
    >>> torch.manual_seed(seed=20200910)
    <torch._C.Generator object at 0x000001A2E55A8870>
    >>> a = torch.randn(3,4,requires_grad=True)
    >>> a
    tensor([[ 0.2824, -0.3715,  0.9088, -1.7601],
            [-0.1806,  2.0937,  1.0406, -1.7651],
            [ 1.1216,  0.8440,  0.1783,  0.6859]], requires_grad=True)
    >>> b = a * 2
    >>> b
    tensor([[ 0.5648, -0.7430,  1.8176, -3.5202],
            [-0.3612,  4.1874,  2.0812, -3.5303],
            [ 2.2433,  1.6879,  0.3567,  1.3718]], grad_fn=<MulBackward0>)
    >>> b.requires_grad
    True
    >>> b.grad
    __main__:1: UserWarning: The .grad attribute of a Tensor that is not a leaf Tensor is being accessed. Its .grad attribute won't be populated during autograd.backward(). If you indeed want the gradient for a non-leaf Tensor, use .retain_grad() on the non-leaf Tensor. If you access the non-leaf Tensor by mistake, make sure you access the leaf Tensor instead. See github.com/pytorch/pytorch/pull/30531 for more informations.
    >>> print(b.grad)
    None
    >>> a.requires_grad
    True
    >>> a.grad
    >>> print(a.grad)
    None
    >>>
    >>> with torch.no_grad():
    ...     c = a * 2
    ...
    >>> c
    tensor([[ 0.5648, -0.7430,  1.8176, -3.5202],
            [-0.3612,  4.1874,  2.0812, -3.5303],
            [ 2.2433,  1.6879,  0.3567,  1.3718]])
    >>> c.requires_grad
    False
    >>> print(c.grad)
    None
    >>> a.grad
    >>>
    >>> print(a.grad)
    None
    >>> c.sum()
    tensor(6.1559)
    >>>
    >>> c.sum().backward()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "D:\Anaconda3\envs\pytorch_1.7.1_cu102\lib\site-packages\torch\tensor.py", line 221, in backward
        torch.autograd.backward(self, gradient, retain_graph, create_graph)
      File "D:\Anaconda3\envs\pytorch_1.7.1_cu102\lib\site-packages\torch\autograd\__init__.py", line 132, in backward
        allow_unreachable=True)  # allow_unreachable flag
    RuntimeError: element 0 of tensors does not require grad and does not have a grad_fn
    >>>
    >>>
    >>> b.sum()
    tensor(6.1559, grad_fn=<SumBackward0>)
    >>> b.sum().backward()
    >>>
    >>>
    >>> a.grad
    tensor([[2., 2., 2., 2.],
            [2., 2., 2., 2.],
            [2., 2., 2., 2.]])
    >>> a.requires_grad
    True
    >>>
    >>>
    

    例子2:

    Microsoft Windows [版本 10.0.18363.1440]
    (c) 2019 Microsoft Corporation。保留所有权利。
    
    C:\Users\chenxuqi>conda activate pytorch_1.7.1_cu102
    
    (pytorch_1.7.1_cu102) C:\Users\chenxuqi>python
    Python 3.7.9 (default, Aug 31 2020, 17:10:11) [MSC v.1916 64 bit (AMD64)] :: Anaconda, Inc. on win32
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import torch
    >>> torch.manual_seed(seed=20200910)
    <torch._C.Generator object at 0x000002109ABC8870>
    >>>
    >>> a = torch.randn(3,4,requires_grad=True)
    >>> a
    tensor([[ 0.2824, -0.3715,  0.9088, -1.7601],
            [-0.1806,  2.0937,  1.0406, -1.7651],
            [ 1.1216,  0.8440,  0.1783,  0.6859]], requires_grad=True)
    >>> a.requires_grad
    True
    >>>
    >>> with torch.set_grad_enabled(False):
    ...     b = a * 2
    ...
    >>> b
    tensor([[ 0.5648, -0.7430,  1.8176, -3.5202],
            [-0.3612,  4.1874,  2.0812, -3.5303],
            [ 2.2433,  1.6879,  0.3567,  1.3718]])
    >>> b.requires_grad
    False
    >>>
    >>> with torch.set_grad_enabled(True):
    ...     c = a * 3
    ...
    >>> c
    tensor([[ 0.8472, -1.1145,  2.7263, -5.2804],
            [-0.5418,  6.2810,  3.1219, -5.2954],
            [ 3.3649,  2.5319,  0.5350,  2.0576]], grad_fn=<MulBackward0>)
    >>> c.requires_grad
    True
    >>>
    >>> d = a * 4
    >>> d.requires_grad
    True
    >>>
    >>> torch.set_grad_enabled(True)  # this can also be used as a function
    <torch.autograd.grad_mode.set_grad_enabled object at 0x00000210983982C8>
    >>>
    >>> # 以函数调用的方式来使用
    >>>
    >>> e = a * 5
    >>> e
    tensor([[ 1.4119, -1.8574,  4.5439, -8.8006],
            [-0.9030, 10.4684,  5.2031, -8.8257],
            [ 5.6082,  4.2198,  0.8917,  3.4294]], grad_fn=<MulBackward0>)
    >>> e.requires_grad
    True
    >>>
    >>> d
    tensor([[ 1.1296, -1.4859,  3.6351, -7.0405],
            [-0.7224,  8.3747,  4.1625, -7.0606],
            [ 4.4866,  3.3759,  0.7133,  2.7435]], grad_fn=<MulBackward0>)
    >>>
    >>> torch.set_grad_enabled(False) # 以函数调用的方式来使用
    <torch.autograd.grad_mode.set_grad_enabled object at 0x0000021098394C48>
    >>>
    >>> f = a * 6
    >>> f
    tensor([[  1.6943,  -2.2289,   5.4527, -10.5607],
            [ -1.0836,  12.5621,   6.2437, -10.5908],
            [  6.7298,   5.0638,   1.0700,   4.1153]])
    >>> f.requires_grad
    False
    >>>
    >>>
    >>>
    
    展开全文
  • 如果使用自定义的函数,得到的不是标量,则backward()时需要传入 grad_variable 参数,这一点详见博客 https://sherlockliao.github.io/2017/07/10/backward/ 。 对于自己的非标量,第一个传入 偏导系数 即可: ...

    总体过程

    对于epoch训练开始之前,经历数据加载、模型定义、权重初始化、优化器定义

    netG=netG = net.dehaze(inputChannelSize, outputChannelSize, ngf)
    
    netG.apply(weights_init)
    if opt.netG != '':
        netG.load_state_dict(torch.load(opt.netG),strict=False)
        
    optimizerG = optim.Adam(netG.parameters(), lr = opt.lrG, betas = (opt.beta1, 0.999), weight_decay=0.00005)
    

    对于每个epoch中的batch大都进行下述操作:

    ### 梯度可导
    for p in netD.parameters():
              p.requires_grad = True
    ### forward + backward 
        outputs = netD(inputs)
        loss = criterion(outputs, labels)
    ### optimize
     # zero the parameter gradients
           optimizer.zero_grad()     #等效netD.zero_grad()
            loss.backward()  
            optimizer.step()   # update parameters
    
    

    权重更新需注意

    第一个地方:

    requires_grad

    #coding=utf-8
    
    # 如果调用backward的时候,所有的变量都是不可导的,那么最后会报出没有可到变量的错误
    import torch
    from torch import  autograd
    input=torch.FloatTensor([1,2,3])
    input_v=autograd.Variable(input,requires_grad=False)#False改为true才可行,不加requires_grad默认为false
    loss=torch.mean(input_v)
     
    print (loss.requires_grad)
    loss.backward()
    print( input_v)
    print (input_v.grad)
    
    • 对于继承自 nn.Module 的某一网络 net 或网络层,定义好后,发现 默认情况下,net.paramters 的 requires_grad 就是 True 的,这跟普通的Variable张量不同。因此,当x.requires_grad == False , y = net(x) 后, 有 y.requires_grad == True ;
    • 但值得注意,虽然nn.xxloss和激活层函数,是继承nn.Module的,但是这两种并没有网络参数,就更谈不上 paramters.requires_grad 的值了。所以类似这两种函数的输出,其requires_grad只跟输入有关,不一定是 True .

    第二个地方:

    .zero_grad()

    根据pytorch中的backward()函数的计算,当网络参量进行反馈时,梯度是被积累的而不是被替换掉;但是在每一个batch时毫无疑问并不需要将两个batch的梯度混合起来累积,因此这里就需要每个batch设置一遍zero_grad 了。

    当optimizer=optim.Optimizer(model.parameters())时,两者等效

    model.zero_grad()
    optimizer.zero_grad() 
    

    backward()

    梯度求解。

    eg

    # simple gradient
    a = v(t.FloatTensor([2, 3]), requires_grad=True)
    b = a + 3
    c = b * b * 3
    out = c.mean()
    out.backward()
    print('*'*10)
    print('=====simple gradient======')
    print('input')
    print(a.data)
    print('compute result is')
    print(out.item())
    print('input gradients are')
    print(a.grad.data)#输出梯度
    

    out

    =====simple gradient======
    input
    tensor([2., 3.])
    compute result is
    91.5
    input gradients are
    tensor([15., 18.])
    

    在这里插入图片描述

    对a 求偏导:
    在这里插入图片描述
    可以看到执行backward后,tensor 的 .grad数据更新

    参数

    相关标志位/函数
    
    1 
    requires_grad
    volatile
    detach()/detach_()
    2 
    retain_graph
    retain_variables
    create_graph
    前三个标志位中,最关键的就是 requires_grad,另外两个都可以转化为 requires_grad 来理解。 
    后三个标志位,与计算图的保持与建立有关系。
    
    其中 retain_variables 与 retain_graph等价,retain_variables 在pytorch0.4+ 新版本中被取消掉。
    
    

    当需要两次backward时候,改参数
    out.backward(retain_graph=True)

    每次 backward() 时,默认会把整个计算图free掉。一般情况下是每次迭代,只需一次 forward() 和一次 backward() ,前向运算forward() 和反向传播backward()是成对存在的,一般一次backward()也是够用的。但是不排除,由于自定义loss等的复杂性,需要一次forward(),多个不同loss的backward()来累积同一个网络的grad,来更新参数。于是,若在当前backward()后,不执行forward() 而可以执行另一个backward(),需要在当前backward()时,指定保留计算图,即backward(retain_graph)

    注意:只有标量才能直接使用 backward(),即loss.backward() , pytorch 框架中的各种nn.xxLoss(),得出的都是minibatch 中各结果 平均/求和 后的值。如果使用自定义的函数,得到的不是标量,则backward()时需要传入 grad_variable 参数,这一点详见博客 https://sherlockliao.github.io/2017/07/10/backward/

    对于自己的非标量,第一个传入 偏导系数 即可:

    对于一维向量:

    m=(x1,x2)=(2,3),n=(x12,x23)

    在这里插入图片描述

    m = Variable(torch.FloatTensor([[2, 3]]), requires_grad=True)
    n = Variable(torch.zeros(1, 2))
    n[0, 0] = m[0, 0] ** 2
    n[0, 1] = m[0, 1] ** 3
    
    n.backward(torch.FloatTensor([[1, 1]]),retain_graph=True)########既有两次求导,又需要设置[1,1]的系数,具体体现在下面二维可以看出
    
    print(m.grad)
    
    print(m.grad)
    tensor([[ 4., 27.]])
    

    对于高维向量:

    求jacobian矩阵,
    在这里插入图片描述

    求偏导2*2矩阵:
    在这里插入图片描述

    # jacobian
    j = t.zeros(2 ,2)
    k = v(t.zeros(1, 2))
    m.grad.data.zero_()
    k[0, 0] = m[0, 0] ** 2 + 3 * m[0 ,1]
    k[0, 1] = m[0, 1] ** 2 + 2 * m[0, 0]
    k.backward(t.FloatTensor([[1, 0]]), retain_variables=True)###只获取对x1的偏导
    j[:, 0] = m.grad.data
    m.grad.data.zero_()
    k.backward(t.FloatTensor([[0, 1]]))###只获取对x2的偏导
    j[:, 1] = m.grad.data
    print('jacobian matrix is')
    print(j)
    

    out:

    jacobian matrix is
    tensor([[4., 2.],
            [3., 6.]])
    

    更新 .step()

    • 一些特殊的情况:
      固定特定网络:
    for p in sub_module.parameters():
        p.requires_grad = False
    

    ref

    https://blog.csdn.net/douhaoexia/article/details/78821428

    展开全文
  • 参考链接: requires_grad_(requires_grad=True) → Tensor
  • with torch.no_grad()理解

    2022-01-20 14:14:37
    2.手动创建的为叶子结点,由叶子结点生产的表达式会继承叶子结点的requires_grad(有True就继承True,没True就继承False) import torch x_1 = torch.tensor([1.,2.,3.],requires_grad=True)#不能是整数 y_1 = x*x ...
  • 首先 :retain_variables=True 与 retain_graph=True没有任何区别 只是 retain_variables 会在pytorch 新版本中被取消掉,将使用 retain_graph 。 所以 在使用 retain_variables=True 时报错: TypeError: ...
  • 既然涉及梯度,不得不先谈谈requires_grad。 import torch 下面先来做做题: a=torch.tensor([1.1]) print(a.requires_grad) #答案是? a=torch.tensor([1.1],requires_grad=True) b=a*2 print(b.requires_grad) #...
  • Pytorch中retain_graph参数的作用

    千次阅读 2020-09-19 20:38:30
    Specify retain_graph=True when calling backward the first time. 前言 在pytorch神经网络迁移的官方教程中有这样一个损失层函数(具体看这里提供0.3.0版中文链接:https://oldpan.me/archives/pyto
  • DEBUG:tensor got an unexpected keyword argument 'requires_grad_' 现象 w1=torch.tensor(2.,requires_grad_=True) 可能报错 可以拆开写 w1=torch.tensor(2.) w1.requires_grad_=True
  • c_core=c_core.requires_grad_() LR=0.01 # 定义一个损失函数 loss_fun=nn.MSELoss() for i in range(10): y_pre=nn.functional.conv2d(x_in,c_core) loss=loss_fun(y_pre,y_out) print(c_core.grad) loss....
  • Pytorch关于requires_grad_(True)的理解

    万次阅读 多人点赞 2021-04-25 10:11:25
      在学习图像迁移的时候,发现使用的vgg19模型需要保证模型... param.requires_grad_(False)   但是疑惑的是,requires_grad_(False)的作用是让参数不被追踪。百思不解其意,故使用如下代码测试: import torch
  • x = torch.randn((1, 4), dtype=torch.float32, requires_grad=True) x Out[54]: tensor([[ 0.1351, 0.8179, 0.1422, -0.3021]], requires_grad=True) y = x ** 2 z = y * 4 output1 = z.mean() output2 = z.sum...
  • 在这个下面进行运算得到的tensor没有grad_fn,也就是它不带梯度(因为没有上一级的函数),因此loss无法从这些tensor向上传递,产生这些tensor的网络的参数将不会更新。下面这种情况一般使用with torch.no_grad(): ...
  • grad 梯度 什么样的tensor有grad? pytorch中只有torch.float和复杂类型才能有grad。 x = torch.tensor([1, 2, 3, 4], requires_grad=True) 这里没有指定x的dtype=torch.float,那么是会报错的。 RuntimeError: ...
  • 出现这个报错的原因是,在新版本的Python下,原来的变量retain_variables被替换成了retain_graph。因此,在调用位置将其替换就可以了。 注:retain_graph的作用是为了避免内存在反向传播之后被释放,从而导致的无法...
  • Pytorch中有多次backward时需要retain_graph参数 背景介绍 Pytorch中的机制是每次调用loss.backward()时都会free掉计算图中所有缓存的buffers,当模型中可能有多次...optimizer.zero_grad() 清空过往梯度; loss1.b
  • Pytorch中backward(retain_graph=True)的 retain_graph参数解释

    千次阅读 多人点赞 2020-02-28 16:41:26
    但是不排除,由于自定义loss等的复杂性,需要一次forward(),多个不同loss的backward()来累积同一个网络的grad,来更新参数。于是, 若在当前backward()后,不执行forward() 而是执行另一个backward() ,需要在当前...
  • 【pytorch】|tensor grad

    千次阅读 2021-11-10 11:04:10
    data_mean.requires_grad True >>> data_1 = data_mean * 20200910.0 >>> data_1 tensor(1182591., grad_fn=) >>> data_2 = data_1 * 15.0 >>> data_2 tensor(17738864., grad_fn=) >>> data_2.retain_grad() >>> ...
  • requires_grad require_grad意为是否需要计算梯度 使用backward()函数反向传播计算梯度时,并不是计算所有tensor的梯度,只有满足下面条件的tensor的梯度才会被计算:1. 当前tensor的 require_grad=True(代码示例一...
  • 参考链接: class torch.autograd.no_grad
  • pytorch 中retain_graph==True的作用

    万次阅读 多人点赞 2020-01-31 23:05:45
    总的来说进行一次backward之后,各个节点的值会清除,这样进行第二次backward会报错,如果加上retain_graph==True后,可以...retain_graph (bool, optional) – If False, the graph used to compute the grad will ...
  • Pytorch 中retain_graph的坑

    千次阅读 2019-04-19 10:34:23
    Pytorch 中retain_graph的坑 在查看SRGAN源码时有如下损失函数,其中设置了retain_graph=True,其作用就是 在更新D网络时的loss反向传播过程中使用了retain_graph=True,目的为是为保留该过程中计算的梯度,后续G...
  • 首先 :retain_variables=True 与 retain_graph=True 没有任何区别   只是 retain_variables 会在pytorch 新版本中被取消掉,将使用 retain_graph 。  所以 在使用 retain_variables=True 时报错:  ...
  • Pytorch: retain_graph=True错误信息

    千次阅读 2020-06-25 13:00:13
    (Pytorch:RuntimeError: Trying ... Specify retain_graph=True when calling backward the first time) 1. 具有多个loss值 retain_graph设置True,一般多用于两次backward # 假如有两个Loss,先执行第一个的backward,
  • pytorch入门(一)

    2021-08-08 01:00:32
    b.retain_grad() loss= (w1*b).mean() loss.backward() tmp是对张量a切片操作,b是对张量tmp复制操作,它们带有grad_fn属性,我们打印看看: 它们需要通过retain_grad()方法保留梯度,否则在反向传播后会被释放,而...
  • 1:model.eval()会固定网络的nn.BN层和nn.Dropout层,nn.BN层在train的时候针对每一个batch会计算一次均值方差,然后最后归纳...2:loss.backward(retain_graph = True),首先,forward一次会建立一个计算图,正常back
  • 一篇讲得比较好的文章 首先明确一点,no_grad与detach有异曲同工之妙,都是逃避autograd的追踪。...b.sum().backward(retain_graph = True ) print(a, a.grad, a.requires_grad ) with torch.no_grad(): a = a .

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,629
精华内容 1,051
关键字:

retain_grad