虽然我在南方的寒冬里瑟瑟发抖,但我还是坚持把这事儿告诉你。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
包中的所有分布式集合操作添加异步支持。send
、recv
、reduce
、all_gather
、gather
与 scatter
。barrier
操作。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 加载预先训练的模型。
tensor.item()
代替。torch.legacy
。torch.masked_copy_
,使用 torch.masked_scatter
代替。# 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)
shape *(0,)
,torch.nonzero
记录返回一个形状为(n,z)
的张量,其中n为非零元素的数量,z 是输入的维度数量,如果没有非 0 元素的时候,永远返回一个形状是 shape _(0,)
的张量。torch.distributed
TCP 的后端去掉了,我们推荐对 cpu 使用 Gloo
和 MPI
后端,对 GPU 使用NCCL 后端。*
),用于 torch.Tensors
和 Numpy 数组之间,将更偏向于得到 torch 的变体。可能会得到不同类型的返回类型。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)
。elementwise_mean
重命名成了 mean
。N维空张量
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 工程的兼容性。