虽然我在南方的寒冬里瑟瑟发抖,但我还是坚持把这事儿告诉你。PyTorch 1.0 稳定版发布啦!
对于一个程序出生的 AI 小白而言,程序还是直观的好,tensorflow 的 api 着实不习惯呀。之前看一些文章说 学 tensorflow 等于学习一门新语言,我想这样说也不为过。而 pytorch 的口号是“Python First”,这当然符合我们这类人的胃口。希望 pytorch 1.0 不会让我们失望吧。
让我们一起来看看 1.0 有哪些新东西。
看点
JIT
JIT(Just-In-Time)是一组编译工具,用于弥合 PyTorch 研究与生产之间的差距。
它允许创建可以在不依赖 Python 解释器的情况下运行的模型,并且可以更积极地进行优化。使用程序注解可以将现有模型转换为 PyTorch 可以直接运行的 Python 子集 Torch Script。模型代码仍然是有效的 Python 代码,可以使用标准的 Python 工具链进行调试。
PyTorch 1.0 提供了 torch.jit.trace
和 torch.jit.script
两种方式使现有代码与 JIT 兼容。一经注解,Torch Script 代码便可以被更好地优化,并且可以被序列化以在新的 C++ API 中使用,并且 C++ API 不依赖于 Python。
# Write in Python, run anywhere!
@torch.jit.script
def RNN(x, h, W_h, U_h, b_h):
y = []
for t in range(x.size(0)):
h = torch.tanh(x[t] @ W_h + h @ U_h + b_h)
y += [h]
return torch.stack(y), h
全新且更快的分布式库
torch.distributed
软件包和 torch.nn.parallel.DistributedDataParallel
模块采用了重新设计的全新分布式库,亮点包括:
- 新的
torch.distributed
是性能驱动的,并且对所有后端完全异步操作,包括:Gloo
、NCCL
和MPI
。 - 显着的分布式数据并行性能改进,尤其适用于网络较慢的主机,如基于以太网的主机。
- 为
torch.distributed
包中的所有分布式集合操作添加异步支持。 - 在 Gloo 后端添加了一些 CPU 操作:
send
、recv
、reduce
、all_gather
、gather
与scatter
。 - 在 NCCL 后端添加
barrier
操作。 - 在 NCCL 后端添加
new_group
支持。
C++ 前端
C++ 前端是 PyTorch 后端的纯 C++ 接口,它遵循已建立的 Python 前端的 API 和体系结构,旨在实现高性能、低延迟和裸机 C++ 应用的研究。它提供了 torch.nn
、torch.optim
、torch.data
和 Python 前端的其它组件的等价物。下边是两种语言前端的简单比较:
Python:
import torch
model = torch.nn.Linear(5, 1)
optimizer = torch.optim.SGD(model.parameters(), lr=0.1)
prediction = model.forward(torch.randn(3, 5))
loss = torch.nn.functional.mse_loss(prediction, torch.ones(3, 1))
loss.backward()
optimizer.step()
C ++:
#include <torch/torch.h>
torch::nn::Linear model(5, 1);
torch::optim::SGD optimizer(model->parameters(), /*lr=*/0.1);
torch::Tensor prediction = model->forward(torch::randn({3, 5}));
auto loss = torch::mse_loss(prediction, torch::ones({3, 1}));
loss.backward();
optimizer.step();
需要注意的是,C++ API 还不稳定。
Torch Hub
Torch Hub 是一个经过预先训练的模型库,旨在促进研究的可重复性。
Torch Hub 支持使用简单的 hubconf.py
文件将预先训练的模型(模型定义和预先训练的权重)发布到 github存储库。发布后,用户可以使用 torch.hub.load
API 加载预先训练的模型。
重大改变
- 对于 0 维的张量,进行索引操作会抛出错误,而不是警告。使用
tensor.item()
代替。 - 去掉了
torch.legacy
。 - 去掉了
torch.masked_copy_
,使用torch.masked_scatter
代替。 - 对于返回值是 0 元素的张量,形状可能会变。
# Previously: all 0-element tensors are collapsed to shape (0,)
>>> torch.nonzero(torch.zeros(2, 3))
tensor([], dtype=torch.int64)
# Now, proper shape is returned
>>> torch.nonzero(torch.zeros(2, 3))
tensor([], size=(0, 2), dtype=torch.int64)
- 之前,所有的 0 元素张量的形状都坍缩到
shape *(0,)
,torch.nonzero
记录返回一个形状为(n,z)
的张量,其中n为非零元素的数量,z 是输入的维度数量,如果没有非 0 元素的时候,永远返回一个形状是shape _(0,)
的张量。 - 现在,返回他们的记录形状。
- 稀疏的张量的索引和值的形状现在改成更加恒定,在 0 元素的张量中。具体细节看这个这里。
-
torch.distributed
TCP 的后端去掉了,我们推荐对 cpu 使用Gloo
和MPI
后端,对 GPU 使用NCCL 后端。 - 一些内部类型的操作(如
*
),用于torch.Tensors
和 Numpy 数组之间,将更偏向于得到 torch 的变体。可能会得到不同类型的返回类型。 - 隐式的 numpy 变换不再是隐式的移动到 cpu 的 tensor 中,在隐式的转化之前,你需要显式的将CUDA 中的 tensor 移动到 CPU 中
tensor.to('cpu')
。 -
torch.randint
现在默认使用类型torch.int64
,而不是默认的浮点类型。 -
torch.tensor
函数使用一个 Tensor 的参数,现在返回的是一个 detached 张量(也是就是grad_fn
是None
)。这样更加接近这个函数的初衷,返回一个张量的拷贝数据,不需要历史的梯度数据。 -
torch.nn.functional.multilabel_soft_margin_loss
现在返回形状是(N,)
的张量替代了原来形状是(N, C)
的张量,目的是为了匹配torch.nn.MultiMarginLoss
,数值上更加稳定。 -
torch.float16
类型,0 元素的张量以及整数的返回类型现在是torch.float16
,之前是torch.float32
或torch.float64
,依赖于不同的整数的类型。 -
torch.potrf
重命名成了torch.cholesky
。有新的默认参数(upper=False)
。 - 对于 loss 函数,
elementwise_mean
重命名成了mean
。
增加了新的功能
N维空张量
- 0 元素的张量现在可以有任意的维度数量 了,而且支持索引和其他的张量操作,之前,0 元素的张量的形状被限制成了
shape (0,)
。
>>> torch.empty((0, 2, 4, 0), dtype=torch.float64)
tensor([], size=(0, 2, 4, 0), dtype=torch.float64)
新的操作符
-
torch.argsort
,类似numpy.argsort
。 -
torch.pdist
,类似scipy.spatial.distance.pdist
。 -
torch.tensordot
,类似numpy.tensordot
。 -
torch.broadcast_tensors
,类似numpy.broadcast_arrays
。 -
torch.narrow
支持稀疏张量。 -
torch.matrix_rank
,类似numpy.linalg.matrix_rank
。 -
torch.matrix_power
,类似numpy.linalg.matrix_power
。 -
torch.nn.CeLU
激活函数。 -
torch.nn.CTCLoss
(做 OCR 的同学笑了)。 -
torch.diag_embed
。 -
torch.roll
操作和numpy.roll
匹配。 -
torch.chain_matmul
进行链式矩阵相乘。 -
torch.finfo
,得到dtype
的更加细节的信息,类似numpy.finfo
和numpy.iinfo
。 -
Tensor.__cuda_array_interface__
,提供了numba
和其他 CUDA 工程的兼容性。