pytorch 0.4.0迁移指南
总说
由于pytorch 0.4版本更新实在太大了, 以前版本的代码必须有一定程度的更新. 主要的更新在于 Variable和Tensor的合并., 当然还有Windows的支持, 其他一些就是支持scalar tensor以及修复bug和提升性能吧. Variable和Tensor的合并导致以前的代码会出错, 所以需要迁移, 其实迁移代价并不大.
Tensor和Variable的合并
说是合并, 其实是按照以前(0.1-0.3版本)的观点是: Tensor现在默认requires_grad=False的Variable了. torch.Tensor
和torch.autograd.Variable
现在其实是同一个类! 没有本质的区别! 所以也就是说, 现在已经没有纯粹的Tensor了, 是个Tensor, 它就支持自动求导! 你现在要不要给Tensor
包一下Variable
, 都没有任何意义了.
查看Tensor
的类型
使用.isinstance()
或是x.type()
, 用type()
不能看tensor的具体类型.
>>> x = torch.DoubleTensor([1, 1, 1])
>>> print(type(x)) # was torch.DoubleTensor
"<class 'torch.Tensor'>"
>>> print(x.type()) # OK: 'torch.DoubleTensor'
'torch.DoubleTensor'
>>> print(isinstance(x, torch.DoubleTensor)) # OK: True
True
requires_grad 已经是Tensor的一个属性了
>>> x = torch.ones(1)
>>> x.requires_grad #默认是False
False
>>> y = torch.ones(1)
>>> z = x + y
>>> # 显然z的该属性也是False
>>> z.requires_grad
False
>>> # 所有变量都不需要grad, 所以会出错
>>> z.backward()
RuntimeError: element 0 of tensors does not require grad and does not have a grad_fn
>>>
>>> # 可以将`requires_grad`作为一个参数, 构造tensor
>>> w = torch.ones(1, requires_grad=True)
>>> w.requires_grad
True
>>> total = w + z
>>> total.requires_grad
True
>>> # 现在可以backward了
>>> total.backward()
>>> w.grad
tensor([ 1.])
>>> # x,y,z都是不需要梯度的,他们的grad也没有计算
>>> z.grad == x.grad == y.grad == None
True
通过.requires_grad()
来进行使得Tensor需要梯度.
不要随便用.data
以前.data
是为了拿到Variable
中的Tensor
,但是后来, 两个都合并了. 所以 .data返回一个新的requires_grad=False的Tensor! 然而新的这个Tensor
与以前那个Tensor
是共享内存的. 所以不安全, 因为
y = x.data # x需要进行autograd
# y和x是共享内存的,但是这里y已经不需要grad了,
# 所以会导致本来需要计算梯度的x也没有梯度可以计算.从而x不会得到更新!
所以, 推荐用x.detach()
, 这个仍旧是共享内存的, 也是使得y
的requires_grad为False, 但是,如果x需要求导, 仍旧是可以自动求导的!
scalar的支持
这个非常重要啊! 以前indexing一个一维Tensor
,返回的是一个number类型,但是indexing一个Variable
确实返回一个size为(1,)的vector. 再比如一些reduction操作, 比如tensor.sum()
返回一个number
, 但是variable.sum()
返回的是一个size为(1,)的vector.
scalar
是0-维度的Tensor, 所以我们不能简单的用以前的方法创建, 我们用一个torch.tensor
注意,是小写的!
>>> torch.tensor(3.1416) # 用torch.tensor来创建scalar
tensor(3.1416) # 注意 scalar是打印出来是没有[]的
>>> torch.tensor(3.1416).size() # size是0
torch.Size([])
>>> torch.tensor([3]).size() # compare to a vector of size 1
torch.Size([1]) # 如果是tensor, 打印出来会用`[]`包上
>>>
>>> vector = torch.arange(2, 6) # this is a vector
>>> vector
tensor([ 2., 3., 4., 5.])
>>> vector[3] # 现在, indexing一个一维tensor返回的是一个tensor了!
tensor(5.)
>>> vector[3].item() # 需要额外加上.item() 来获得里面的值
5.0
>>> mysum = torch.tensor([2, 3]).sum() # 而这种reduction操作, 返回的是一个scalar了(0-dimension的tensor)
>>> mysum
tensor(5)
>>> mysum.size()
torch.Size([])
从上面例子可以看出, 通过引入scalar
, 可以将返回值的类型进行统一.
重点:
1. 取得一个tensor的值(返回number), 用.item()
2. 创建scalar
的话,需要用torch.tensor(number)
3. torch.tensor(list)
也可以进行创建tensor
累加loss
以前了累加loss(为了看loss的大小)一般是用total_loss+=loss.data[0]
, 比较诡异的是, 为啥是.data[0]
? 这是因为, 这是因为loss
是一个Variable, 所以以后累加loss, 用loss.item()
.
这个是必须的, 如果直接加, 那么随着训练的进行, 会导致后来的loss具有非常大的graph, 可能会超内存. 然而total_loss
只是用来看的, 所以没必要进行维持这个graph!
弃用 volatile
现在这个flag已经没用了. 被替换成torch.no_grad()
, torch.set_grad_enable(grad_mode)
等函数
>>> x = torch.zeros(1, requires_grad=True)
>>> with torch.no_grad():
... y = x * 2
>>> y.requires_grad
False
>>>
>>> is_train = False
>>> with torch.set_grad_enabled(is_train):
... y = x * 2
>>> y.requires_grad
False
>>> torch.set_grad_enabled(True) # this can also be used as a function
>>> y = x * 2
>>> y.requires_grad
True
>>> torch.set_grad_enabled(False)
>>> y = x * 2
>>> y.requires_grad
False
dypes
,devices
以及numpy-style的构造函数
dtype
是data types, 对应关系如下:
通过.dtype
可以得到
其他就是以前写device type
都是用.cup()
或是.cuda()
, 现在独立成一个函数, 我们可以
>>> device = torch.device("cuda:1")
>>> x = torch.randn(3, 3, dtype=torch.float64, device=device)
tensor([[-0.6344, 0.8562, -1.2758],
[ 0.8414, 1.7962, 1.0589],
[-0.1369, -1.0462, -0.4373]], dtype=torch.float64, device='cuda:1')
>>> x.requires_grad # default is False
False
>>> x = torch.zeros(3, requires_grad=True)
>>> x.requires_grad
True
新的创建Tensor
方法
主要是可以指定 dtype
以及device
.
>>> device = torch.device("cuda:1")
>>> x = torch.randn(3, 3, dtype=torch.float64, device=device)
tensor([[-0.6344, 0.8562, -1.2758],
[ 0.8414, 1.7962, 1.0589],
[-0.1369, -1.0462, -0.4373]], dtype=torch.float64, device='cuda:1')
>>> x.requires_grad # default is False
False
>>> x = torch.zeros(3, requires_grad=True)
>>> x.requires_grad
True
用 torch.tensor来创建Tensor
这个等价于numpy.array,用途:
1.将python list的数据用来创建Tensor
2. 创建scalar
# 从列表中, 创建tensor
>>> cuda = torch.device("cuda")
>>> torch.tensor([[1], [2], [3]], dtype=torch.half, device=cuda)
tensor([[ 1],
[ 2],
[ 3]], device='cuda:0')
>>> torch.tensor(1) # 创建scalar
tensor(1)
torch.*like以及torch.new_*
第一个是可以创建, shape相同, 数据类型相同.
>>> x = torch.randn(3, dtype=torch.float64)
>>> torch.zeros_like(x)
tensor([ 0., 0., 0.], dtype=torch.float64)
>>> torch.zeros_like(x, dtype=torch.int)
tensor([ 0, 0, 0], dtype=torch.int32)
当然如果是单纯想要得到属性与前者相同的Tensor, 但是shape不想要一致:
>>> x = torch.randn(3, dtype=torch.float64)
>>> x.new_ones(2) # 属性一致
tensor([ 1., 1.], dtype=torch.float64)
>>> x.new_ones(4, dtype=torch.int)
tensor([ 1, 1, 1, 1], dtype=torch.int32)
书写 device-agnostic 的代码
这个含义是, 不要显示的指定是gpu, cpu之类的. 利用.to()
来执行.
# at beginning of the script
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
...
# then whenever you get a new Tensor or Module
# this won't copy if they are already on the desired device
input = data.to(device)
model = MyModule(...).to(device)
迁移代码对比
以前的写法
model = MyRNN()
if use_cuda:
model = model.cuda()
# train
total_loss = 0
for input, target in train_loader:
input, target = Variable(input), Variable(target)
hidden = Variable(torch.zeros(*h_shape)) # init hidden
if use_cuda:
input, target, hidden = input.cuda(), target.cuda(), hidden.cuda()
... # get loss and optimize
total_loss += loss.data[0]
# evaluate
for input, target in test_loader:
input = Variable(input, volatile=True)
if use_cuda:
...
...
现在的写法
# torch.device object used throughout this script
device = torch.device("cuda" if use_cuda else "cpu") model = MyRNN().to(device) # train
total_loss = 0
for input, target in train_loader:
input, target = input.to(device), target.to(device)
hidden = input.new_zeros(*h_shape) # has the same device & dtype as `input`
... # get loss and optimize
total_loss += loss.item() # get Python number from 1-element Tensor # evaluate
with torch.no_grad(): # operations inside don't track history
for input, target in test_loader:
...
REFERENCES:https://zhuanlan.zhihu.com/p/36116749
pytorch 0.4.0迁移指南的更多相关文章
- 【翻译】Flume 1.8.0 User Guide(用户指南) Processors
翻译自官网flume1.8用户指南,原文地址:Flume 1.8.0 User Guide 篇幅限制,分为以下5篇: [翻译]Flume 1.8.0 User Guide(用户指南) [翻译]Flum ...
- 【翻译】Flume 1.8.0 User Guide(用户指南) Channel
翻译自官网flume1.8用户指南,原文地址:Flume 1.8.0 User Guide 篇幅限制,分为以下5篇: [翻译]Flume 1.8.0 User Guide(用户指南) [翻译]Flum ...
- 【翻译】Flume 1.8.0 User Guide(用户指南) source
翻译自官网flume1.8用户指南,原文地址:Flume 1.8.0 User Guide 篇幅限制,分为以下5篇: [翻译]Flume 1.8.0 User Guide(用户指南) [翻译]Flum ...
- Asp.Net MVC4.0 官方教程 入门指南之五--控制器访问模型数据
Asp.Net MVC4.0 官方教程 入门指南之五--控制器访问模型数据 在这一节中,你将新创建一个新的 MoviesController类,并编写代码,实现获取影片数据和使用视图模板在浏览器中展现 ...
- Asp.Net MVC4.0 官方教程 入门指南之四--添加一个模型
Asp.Net MVC4.0 官方教程 入门指南之四--添加一个模型 在这一节中,你将添加用于管理数据库中电影的类.这些类是ASP.NET MVC应用程序的模型部分. 你将使用.NET Framewo ...
- Asp.Net MVC4.0 官方教程 入门指南之三--添加一个视图
Asp.Net MVC4.0 官方教程 入门指南之三--添加一个视图 在本节中,您需要修改HelloWorldController类,从而使用视图模板文件,干净优雅的封装生成返回到客户端浏览器HTML ...
- Asp.Net MVC4.0 官方教程 入门指南之二--添加一个控制器
Asp.Net MVC4.0 官方教程 入门指南之二--添加一个控制器 MVC概念 MVC的含义是 “模型-视图-控制器”.MVC是一个架构良好并且易于测试和易于维护的开发模式.基于MVC模式的应用程 ...
- Windows下通过pip安装PyTorch 0.4.0 import报错
问题:通过pip安装PyTorch 0.4.0成功,但是import时报错. import torch File "D:\Python\Python36\lib\site-packages ...
- 【翻译】Flume 1.8.0 User Guide(用户指南) Sink
翻译自官网flume1.8用户指南,原文地址:Flume 1.8.0 User Guide 篇幅限制,分为以下5篇: [翻译]Flume 1.8.0 User Guide(用户指南) [翻译]Flum ...
随机推荐
- 现有某电商网站用户对商品的收藏数据,记录了用户收藏的商品id以及收藏日期,名为buyer_favorite1。 buyer_favorite1包含:买家id,商品id,收藏日期这三个字段,数据以“\t”分割
实验内容(mapReduce安装请按照林子雨教程http://dblab.xmu.edu.cn/blog/631-2/) 现有某电商网站用户对商品的收藏数据,记录了用户收藏的商品id以及收藏日期,名为 ...
- fillter根据value来匹配字段
字段对应 let cashBackState = { 'WAIT_FIVE': '满5单可返现', 'FINISHED': '已返现' } filters: { cashBackStateFilter ...
- Windows 安装R
下载 R 的安装包 双击 安装包 进行安装 安装完成 测试 修改 R 中的CRAN镜像 添加到 Windows 的环境变量中 测试
- 当变量超过任意设定的变量限制时终止fluent模拟【翻译】
一些时候某个特定的变量(压力,速度,温度等)发散会造成不合理的计算结果.在许多算例,当变量超过某些合理的限制时,自动停止/打断模拟是有帮助的. 解决方法是联合UDF和scheme文件.UDF将会遍历所 ...
- maven 私服上有jar包但是却下载不下来
解决办法: 在parent中执行deploy命令就解决了. 原因:第一次建项目,上传jar包的时候直接进入到该项目中进行deploy到私服.最终发现私服仓库有,但是别人引用的时候无法下载.是因为别人下 ...
- 基于hive的《反贪风暴4》的影评
一:将爬虫大作业产生的csv文件上传到HDFS 查看文件中前10条信息,即可证明是否上传成功. 二.对CSV文件进行预处理生成无标题文本文件 创建一个deal.sh,主要实现数据分割成什么样的意思 执 ...
- Oracle定时任务执行存储过程备份日志记录表
写在前面 需求 1.备份系统日志表T_S_LOG, 按照操作时间字段OPERATETIME, 将每天的日志增量备份到另一张表. 思路 1.创建一张数据结构完全相同的表T_S_LOG_BAK作为备份表 ...
- web编辑器的使用比较
一开始测试的时候发现都还可以,只是出于后续考虑,选择了ckeditor,但是有时候会莫名出现Cannot read property 'XXX' of undefined,如下: Uncaught T ...
- NFS的安装与使用
一.服务器端: 1.1安装NFS服务: #执行以下命令安装NFS服务器, #apt会自动安装nfs-common.rpcbind等13个软件包 sudo apt install nfs-kernel- ...
- win10 配置git 环境变量
'git' 不是内部或外部命令,也不是可运行的程序 或批处理文件. 解决办法: 去百度大概搜了一下,是因为没有配置Git环境变量的原因,但是没有具体的解决步骤,特此记录一下. 右键查看git安装目录: ...