前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >PyTorch 1.3 —新增功能?

PyTorch 1.3 —新增功能?

作者头像
代码医生工作室
发布2019-10-15 17:22:19
3.1K0
发布2019-10-15 17:22:19
举报
文章被收录于专栏:相约机器人相约机器人

作者 | Wabaf Kumar

来源 | Medium

编辑 | 代码医生团队

Facebook刚刚发布了PyTorch v1.3,其中包含了一些最期待的功能。最具吸引力的三个是:

  • 名为Tensor-使机器学习从业人员的生活更加轻松的事物。
  • 量化 -适用于性能至关重要的系统,例如IoT设备和嵌入式系统。
  • 移动支持 -适用于Android和iOS设备。

将简要介绍所有这些内容,并将链接到其他一些重要功能。

命名张量

PyTorch v1.3最终添加了对命名张量的支持,该功能使用户可以使用显式关联的名称访问张量尺寸,而无需记住尺寸编号。例如,到目前为止,在与计算机视觉相关的任务中,必须记住批处理的一般结构,如下所示-[N,C,H,W]。其中N是批处理大小,C是通道数,H和W分别是图像的高度和宽度。在对该批处理执行操作时,必须跟踪这种结构,但是现在只能使用维度名称,而无需跟踪其索引。此外,这些命名的表示形式可以提供增强的运行时错误检查。将在本文中进一步讨论它们。

代码语言:javascript
复制
import torch
batch = torch.zeros(64, 3, 100, 100, names=('N', 'C', 'H', 'W'))
print(batch.names)

创建命名张量

batch.namesbatch按顺序在张量上打印每个维的名称。

按名称对齐

使用align_as()或align_to()按名称将张量尺寸与指定顺序对齐。

在计算机视觉模型中,批次的表示通常需要在[N,C,H,W](用于模型的正向和反向传递)和[N,H,W,C](用于绘制和保存图像)之间改变。到现在为止,必须像在直觉上相反地完成此操作,batch.permute([0, 2, 3, 1])但是现在可以通过使用align_as()or align_to()运算符以更简单的方式来完成。

代码语言:javascript
复制
import torch
 
batch = torch.zeros(64, 3, 100, 100, names=('N', 'C', 'H', 'W'))
print(batch.shape) #torch.Size([64, 3, 100, 100])
batch = batch.align_to('N', 'H', 'W', 'C')
print(batch.shape) #torch.Size([64, 100, 100, 3])

对于大量维,普通置换运算符甚至需要交换所有维的位置,也需要所有维的明确列表。但是,在命名张量的情况下,维的排列或重新排序可以通过以下更简单的方式完成:

代码语言:javascript
复制
#####################
# Before PyTorch v1.3
#####################
import torch
 
batch = torch.zeros(2, 3, 2, 2, 2, 2, 2, 2, 2, 2)
print(batch.shape)
batch = batch.permute([0, 2, 1, 3, 4, 5, 6, 7, 8, 9])
print(batch.shape)
 
#####################
# After PyTorch v1.3
#####################
import torch
alphas = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
batch = torch.zeros(2, 3, 2, 2, 2, 2, 2, 2, 2, 2, names=alphas)
print(batch.shape)
batch = batch.align_to('a', 'c', 'b', ...)
print(batch.shape)

检查命名

除了使张量更直观之外,命名张量还提供其他错误检查。当运算符应用于命名张量时(对于二进制运算符,任何一个或两个命名张量)将隐式检查某些维名称在运行时是否匹配。这为错误提供了额外的安全性。在下面的示例中显示:

代码语言:javascript
复制
import torch
 
# The following will produce no error as the dimensions match
batch1= torch.zeros(64, 3, 100, 100, names=('N', 'C', 'H', 'W'))
batch2 = torch.zeros(64, 3, 100, 100, names=('N', 'C', 'H', 'W'))
batch3 = batch1 + batch2
 
# The following will produce an error as the dimensions don't match
batch1= torch.zeros(64, 3, 100, 100, names=('N', 'C', 'H', 'W'))
batch2 = torch.zeros(64, 3, 100, 100, names=('N', 'C', 'W', 'H'))
batch3 = batch1 + batch2

在上面的示例中,如果不是用于命名张量,batch1并且batch2可以被添加而没有任何错误,因为height = width =100。但是,batch2高度和宽度尺寸已互换,将其添加到该对象batch1可能不是预期的操作。多亏命名张量,此逻辑错误将通过名称检查(“ N”,“ C”,“ H”,“ W”)和(“ N”,“ C”,“ W”,“ H”)来捕获不一样。

名称何时匹配?

这些规则与numpy或PyTorch中尺寸的广播规则非常相似。引用官方的PyTorch文档:

如果两个名称相等(字符串相等),或者至少一个为,则两个名称匹配None。从本质上讲,没有一个是特殊的“通配符”名称。”

在下面的示例中展示了这一点:

代码语言:javascript
复制
import torch
 
batch1= torch.zeros(64, 3, 100, 100, names=('N', 'C', 'H', 'W'))
batch2 = torch.zeros(64, 3, 100, 100, names=('N', 'C', 'H', 'W'))
batch3 = torch.zeros(64, 3, 100, 100)
batch4 = torch.zeros(64, 3, 100, 100)
batch5 = torch.zeros(64, 3, 100, 100, names=('N', 'C', 'W', 'H'))
 
#Name tuple strings are equal so name matches
res1 = batch1 + batch2
#Name of one of the inputs (batch3) is None so matches
res2 = batch1 + batch3
#Name of both the inputs are None so matches
res2 = batch3 + batch4
#Name tuple strings are not equal so no name match and error
res3 = batch1 + batch5

名称传播

在对张量执行运算后,无需再次输入尺寸名称,它们将自动传播。PyTorch利用了两个运营商- match和unify 为名称的传播。

  • match 与上面定义的运算符相同,它检查两个命名张量是否可以匹配。
  • unify是一个运算符,用于确定应将两个输入张量名称中的哪一个传播为结果张量。引用官方的PyTorch文档:

unify(A, B)确定哪个名称A并将B其传播到输出。如果两个名称匹配,则返回两个名称中更具体的一个。如果名称不匹配,则错误。

下面的示例展示了名称传播:

  • 一元运算符:
代码语言:javascript
复制
import torch
 
# Unary operator on named tensors
t = torch.randn(4, 2, names=('N', 'C'))
t = t.abs()
t.names #output: ('N', 'C')
  • 二进制运算符:
代码语言:javascript
复制
import torch
 
# Binary operator on named tensors
t1 = torch.randn(4, names=('X'))
t2 = torch.randn(4)
t3 = t1 * t2
t3.names #output: ('X',)

局限性

在撰写本文时,命名的张量功能处于实验模式,可能会发生许多变化。但是,命名张量当前最大的限制之一是它们无法完全支持Autograd引擎。尽管命名张量的梯度计算完全相同,但autograd引擎完全忽略了该名称,并忽略了其提供的其他安全性。

量化

PyTorch 1.3现在支持张量量化。Tensorflow已经支持了这一点,并且在PyTorch中已经等待了很多。量化是一个相当简单但精心设计的概念。在这里,将通过回答三个问题(什么,为什么和如何)来简要概述它们。

什么是量化?

量化是一种以低精度格式执行操作或将高精度数据格式转换为低精度数据格式的技术。例如,通过将32位浮点格式视为8位定点格式来完成此操作。如果有兴趣,可以阅读定点和浮点算法及其相关的复杂性,以更好地理解量化的需求。

为什么要 量化?

进行研究和创建神经网络模型的全部目的是部署它们并使之对公众有利。虽然模型训练的需求仅与研究人员和机器学习从业人员的数量成比例地增长,但对模式推理的需求却与消费者的数量成比例地增长。为了允许更多更好地访问最终用户,部署用于推理的模型的表示需要比训练时的表示更为紧凑。要记住的另一件事是,反向传播需要模型权重和偏差的高精度表示。但是,在推论过程中,模型更加健壮,不需要高精度表示。从而,可以将32位浮点表示中大小为113.9MB的模型量化为int8,大小为76.8MB。

https://pytorch.org/tutorials/advanced/dynamic_quantization_tutorial.html#test-dynamic-quantization

如何在PyTorch v1.3中使用量化?

引用官方PyTorch文档:

与典型的FP32型号相比,PyTorch支持INT8量化,从而可将模型尺寸减少4倍,并将内存带宽要求减少4倍。与FP32计算相比,对INT8计算的硬件支持通常快2到4倍。

为了进行量化,PyTorch引入了三种新的数据类型,如下所示:

  • torch.quint8 — 8位无符号整数。
  • torch.qint8 — 8位带符号整数。
  • torch.qint32 — 32位带符号整数。

PyTorch现在为模型提供了三种量化方法:

  • 训练后的动态量化 -提前量化权重,但在运行时动态量化网络激活。可以这样完成:torch.quantization.quantize_dynamic(model, dtype=torch.qint8)
  • 训练后的静态量化 -提前量化权重,激活偏差和比例因子。这可以通过调用校准函数来完成。有关更多详细信息,请参阅原始文档。
  • 量化意识训练 —在此模型中,以FP32表示形式进行训练,但随后将其量化为精度较低的精度表示形式,例如INT8。这在正常量化无法提供准确结果的极少数情况下使用。因此,我们开始用量化值训练模型。

需要注意的另一件事是PyTorch从一开始就支持量化。这意味着,还可以使用以下方程式(非常直观)和代码对张量进行量化:

此等式用于量化张量的int表示,可以使用 t.int_repr()

代码语言:javascript
复制
import torch
 
t = torch.tensor([1.111111111])
t_q = torch.quantize_per_tensor(t, 0.1, 10, torch.quint8)
#output: tensor([21], dtype=torch.uint8)
print(t_q.int_repr())
#output: tensor([1.1000], size=(1,), dtype=torch.quint8, quantization_scheme=torch.per_tensor_affine, scale=0.1, zero_point=10)
print(t_q)  

这是量化张量上所有受支持的操作的列表。

行动支持

允许量化的自然目的是在性能至关重要的手机(和其他设备)上交付PyTorch模型。已经为Android和iOS实现了端到端PyTorch API。这将对减少推理延迟和用户隐私产生重大影响。但是,PyTorch移动设备目前处于试验阶段,它存在一些局限性。例如,当前版本仅支持正向传播(推断),不支持向后操作。

可以在PyTorch官方网站上访问iOS和Android的hello world教程。

https://pytorch.org/mobile/ios/

https://pytorch.org/mobile/android/

更多更新

除了这三个主要更新之外,PyTorch v1.3还实现了其他一些更改和错误修复。可以在官方PyTorch Github存储库上查看所有更改的列表。其中一些功能是:

https://github.com/pytorch/pytorch/releases

  • TPU支持Google Cloud上的PyTorch。这是一个Github仓库,展示了如何在PyTorch中使用TPU。
  • 扩展支持TensorBoard:3D网格和超参数
  • 火炬手的主要更新(主要用于手机)
  • 性能改进torch.nn,torch.nn.functional,Autograd引擎等等。

此外,如果要将代码从先前版本的PyTorch移植到PyTorch v1.3,则需要注意可能会导致错误或意外行为的功能。其中一些功能是(我直接引用了前面提到的发行说明中的这些更改):

  • 数据类型提升:例如,torch.tensor(5) + 1.5输出一个值为6.5的张量。在早期版本中,输出为6。
  • 就地运算符的数据类型提升:例如,请考虑以下代码:a = torch.tensor(0); a.add_(0.5)在早期版本中,这将给出张量为1的张量作为输出。但是到目前为止,PyTorch不再支持具有较低数据类型的就地操作,因此上面的代码会输出错误。
  • torch.flatten:输出torch.flatten(torch.tensor(0))是tensor([0])比较tensor(0)早。现在,它返回一个1D张量,而不是返回0D张量。
  • nn.functional.affine_grid:当align_corners = True时,更改了对1D数据的2D仿射变换和对2D数据的3D仿射变换的行为(即,当空间维之一具有单位大小时)。以前,单位维度上的所有网格点都被任意认为是-1,现在它们被认为是0(输入图像的中心)。
  • torch.gels:已删除不推荐使用的运算符,请torch.lstsq改用。
  • utils.data.DataLoader 将多个Iterator属性设为私有(例如num_workers,pin_memory)。
  • pyTorch for C ++的其他更改。

https://github.com/pytorch/pytorch/releases

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-10-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 相约机器人 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档