1. 关于parameters()方法

Pytorch中继承了torch.nn.Module的模型类具有named_parameters()/parameters()方法,这两个方法都会返回一个用于迭代模型参数的迭代器(named_parameters还包括参数名字):

import torch

net = torch.nn.LSTM(input_size=512, hidden_size=64)
print(net.parameters())
print(net.named_parameters())
# <generator object Module.parameters at 0x12a4e9890>
# <generator object Module.named_parameters at 0x12a4e9890>

我们可以将net.parameters()迭代器和将net.named_parameters()转化为列表类型,前者列表元素是模型参数,后者是包含参数名和模型参数的元组。

当然,我们更多的是对迭代器直接进行迭代:

for param in net.parameters():
print(param.shape)
# torch.Size([256, 512])
# torch.Size([256, 64])
# torch.Size([256])
# torch.Size([256])
for name, param in net.named_parameters():
print(name, param.shape)
# weight_ih_l0 torch.Size([256, 512])
# weight_hh_l0 torch.Size([256, 64])
# bias_ih_l0 torch.Size([256])
# bias_hh_l0 torch.Size([256])

我们知道,Pytorch在进行优化时需要给优化器传入这个参数迭代器,如:

from torch.optim import RMSprop
optimizer = RMSprop(net.parameters(), lr=0.01)

2. 关于参数修改

那么底层具体是怎么对参数进行修改的呢?

我们在博客《Python对象模型与序列迭代陷阱》中介绍过,Python序列中本身存放的就是对象的引用,而迭代器返回的是序列中的对象的二次引用,如果序列的引用指向基础数据类型,则是不可以通过遍历序列进行修改的,如:

my_list = [1, 2, 3, 4]
for x in my_list:
x += 1
print(my_list) #[1, 2, 3, 4]

而序列中的引用指向复合数据类型,则可以通过遍历序列来完成修改操作,如:

my_list = [[1, 2],[3, 4]]
for sub_list in my_list:
sub_list[0] += 1
print(my_list)
# [1, 2, 3, 4]
# [[2, 2], [4, 4]]

具体原理可参照该篇博客,此处我就不在赘述。这里想提到的是,用net.parameters()/net.named_parameters()来迭代并修改参数,本质上就是上述第二种对复合数据类型序列的修改。我们可以如下写:

for param in net.parameters():
with torch.no_grad():
param += 1

with torch.no_grad():表示将将所要修改的张量关闭梯度计算。所增加的1会广播到param张量的中的每一个元素上。上述操作本质上为:

for param in net.parameters():
with torch.no_grad():
param += torch.ones(param.shape)

但是需要注意,如果我们想让参数全部置为0,切不可像下列这样写:

for param in net.parameters():
with torch.no_grad():
param = torch.zeros(param.shape)

param是二次引用,param=0操作再语义上会被解释为让param这个二次引用去指向新的全0张量对象,但是对参数张量本身并不会产生任何变动。该操作实际上类似下列这种操作:

list_1 = [1, 2]
list_2 = list_1
list_2 = [0, 0]
print(list_1) # [1, 2]

修改二次引用list_2自然不会影响到list_1引用的对象。

下面让我们纠正这种错误,采用下列方法直接来将参数张量中的所有数值置0:

for param in net.parameters():
with torch.no_grad():
param[:] = 0 #张量类型自带广播操作,等效于param[:] = torch.zeros(param.shape)

这时语义上就类似

list_1 = [1, 2]
list_2 = list_1
list_2[:] = [0, 0]
print(list_1) # [0, 0]

自然就能完成修改的操作了。

参考

Pytorch:利用torch.nn.Modules.parameters修改模型参数的更多相关文章

  1. pytorch中torch.nn构建神经网络的不同层的含义

    主要是参考这里,写的很好PyTorch 入门实战(四)--利用Torch.nn构建卷积神经网络 卷积层nn.Con2d() 常用参数 in_channels:输入通道数 out_channels:输出 ...

  2. [pytorch笔记] torch.nn vs torch.nn.functional; model.eval() vs torch.no_grad(); nn.Sequential() vs nn.moduleList

    1. torch.nn与torch.nn.functional之间的区别和联系 https://blog.csdn.net/GZHermit/article/details/78730856 nn和n ...

  3. PyTorch官方中文文档:torch.nn

    torch.nn Parameters class torch.nn.Parameter() 艾伯特(http://www.aibbt.com/)国内第一家人工智能门户,微信公众号:aibbtcom ...

  4. 到底什么是TORCH.NN?

    该教程是在notebook上运行的,而不是脚本,下载notebook文件. PyTorch提供了设计优雅的模块和类:torch.nn, torch.optim, Dataset, DataLoader ...

  5. 从 relu 的多种实现来看 torch.nn 与 torch.nn.functional 的区别与联系

    从 relu 的多种实现来看 torch.nn 与 torch.nn.functional 的区别与联系 relu多种实现之间的关系 relu 函数在 pytorch 中总共有 3 次出现: torc ...

  6. 小白学习之pytorch框架(3)-模型训练三要素+torch.nn.Linear()

    模型训练的三要素:数据处理.损失函数.优化算法    数据处理(模块torch.utils.data) 从线性回归的的简洁实现-初始化模型参数(模块torch.nn.init)开始 from torc ...

  7. pytorch保存模型等相关参数,利用torch.save(),以及读取保存之后的文件

    本文分为两部分,第一部分讲如何保存模型参数,优化器参数等等,第二部分则讲如何读取. 假设网络为model = Net(), optimizer = optim.Adam(model.parameter ...

  8. 小白学习之pytorch框架(4)-softmax回归(torch.gather()、torch.argmax()、torch.nn.CrossEntropyLoss())

    学习pytorch路程之动手学深度学习-3.4-3.7 置信度.置信区间参考:https://cloud.tencent.com/developer/news/452418 本人感觉还是挺好理解的 交 ...

  9. 小白学习之pytorch框架(1)-torch.nn.Module+squeeze(unsqueeze)

    我学习pytorch框架不是从框架开始,从代码中看不懂的pytorch代码开始的 可能由于是小白的原因,个人不喜欢一些一下子粘贴老多行代码的博主或者一些弄了一堆概念,导致我更迷惑还增加了畏惧的情绪(个 ...

  10. [深度学习] Pytorch学习(二)—— torch.nn 实践:训练分类器(含多GPU训练CPU加载预测的使用方法)

    Learn From: Pytroch 官方Tutorials Pytorch 官方文档 环境:python3.6 CUDA10 pytorch1.3 vscode+jupyter扩展 #%% #%% ...

随机推荐

  1. Windows wsl2安装Docker

    wsl2的Ubuntu安装好后,就可以安装Docker了. 由于众所周知的原因,国内访问国外的某些网站会访问不了或者访问极慢,Docker的安装网站就在其中. 所以推荐使用阿里的镜像进行安装. 1.使 ...

  2. Centos环境部署SpringBoot项目

    centos JDK Jenkins maven tomcat git myslq nginx 7.9 11.0.19 2.418 3.8.1 9.0.78 2.34.4 5.7.26 1.24.0 ...

  3. cas登录成功后跳转地址和退出后跳转首页

    cas登录成功后跳转地址和退出后跳转首页 CAS版本5.3 1.登录页面 的登录链接地址为 login.html ...<span v-if="username == ''" ...

  4. HarmonyOS Codelab样例—弹窗基本使用

    一.介绍 本篇 Codelab 主要基于 dialog 和 button 组件,实现弹窗的几种自定义效果,具体效果有: 1.  警告弹窗,点击确认按钮弹窗关闭. 2.  确认弹窗,点击取消按钮或确认按 ...

  5. 在python中实现二叉树

    二叉树设计 定义节点类 class Node: # 修改初始化方法 def init(self,value): self.value = value # 节点值 self.left = None # ...

  6. Leetcode-栈的压入弹出序列

    /* 输入:pushed = [1,2,3,4,5], popped = [4,5,3,2,1] 输出:true 解释:我们可以按以下顺序执行: push(1), push(2), push(3), ...

  7. chrome浏览器代理插件SwitchyOmega使用

    第一步:下载SwitchyOmega插件 Proxy_SwitchyOmega_2.5.21.crx 第二步:安装插件, 1,在chrome扩展程序开启开发者模式: 2,将插件拖过来: 第三步:设置代 ...

  8. 获取电脑真实的IP地址,忽略虚拟机等IP地址的干扰

    /** * @author yins * @date 2018年8月12日下午9:53:58 */ import java.net.Inet4Address; import java.net.Inet ...

  9. 力扣19(java&python)-删除链表的倒数第 N 个结点(中等)

    题目: 给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点. 示例 1: 输入:head = [1,2,3,4,5], n = 2 输出:[1,2,3,5] 示例2: 输入:head = ...

  10. 科学地花钱:基于端智能的在线红包分配方案 (CIKM2020)

    简介: 红包是电商平台重要的用户运营手段,本文将介绍1688基于端智能技术开发的two-stage红包分发方案.这一方案持续在线上生效,相较于原有算法有明显提升. 一.前言 本文是作者在1688进行新 ...