PyTorch 1.3 - 有什么新功能?
支持Android和iOS,命名张量,TPU支持,量化等。
Facebook刚刚发布了PyTorch v1.3,它包含了一些人们最期待的功能。其中最吸引人的有三个:
- 命名张量--这将使机器学习从业者的生活更加轻松。
- 量化-- 对于物联网设备和嵌入式系统等性能关键系统。
- 移动支持-- 适用于安卓和iOS设备。
我将简要地谈论所有这些,并将链接到其他一些重要的功能。
命名的张量
PyTorch v1.3终于增加了对命名张量的支持,这使得用户可以使用明确关联的名称来访问张量维度,而不是记住维度编号。例如,到目前为止,在计算机视觉相关的任务中,我们必须记住一个批处理的一般结构如下 - [N, C, H, W]。其中N是批次大小,C是通道数量,H和W分别是图像的高度和宽度。我们在对这个批处理进行操作时,必须跟踪这样的结构,但现在我们可以直接使用维度名称,而不是跟踪其索引。此外,这些命名的表示法可以提供增强的运行时错误检查。我将在这篇文章中进一步讨论它们。
batch.names按顺序打印张量批中每个维度的名称。
按名称对齐
使用align_as()或align_to()将张量维度按名称对齐到一个指定的顺序。
在计算机视觉模型中,批处理的表示方法经常需要在[N, C, H, W](用于模型的向前和向后传递)和[N, H, W, C](用于绘制和保存图像)之间变化。到目前为止,这必须通过 batch.permute([0, 2, 3, 1])这种反直觉的方式来完成,但现在可以通过使用align_as()或align_to()操作符以更简单的方式完成。
对于大量的维度,普通的permute操作符需要一个明确的所有维度的列表,即使只是交换两个维度的位置。然而,在命名的张量的情况下,维数的互换或重新排序可以用更简单的方式完成,如下所示。
检查名称
除了使张量更直观之外,命名的张量还提供了额外的错误检查。当一个操作者应用于命名的张量时(如果是二进制操作者,任何一个或两个命名的张量),在运行时将隐含地检查某些维度名称是否匹配。这为防止错误提供了额外的安全性。下面的例子说明了这一点。
在上面的例子中,如果没有命名的张量,batch1和batch2可以被添加而没有任何错误,因为高度=宽度=100。然而,batch2的高度和宽度尺寸是互换的,把它加到batch1中可能不是预期的操作。多亏了命名的张量,这个逻辑错误会被名称检查发现,因为('N', 'C', 'H', 'W')和('N', 'C', 'W', 'H')是不相同的。
名字什么时候被匹配?
这些规则与numpy或PyTorch中维度的广播规则差不多。引用PyTorch官方文档的内容。
如果两个名字相等(字符串相等),或者至少有一个是 None,那么就可以匹配 。Nones本质上是一个特殊的 "通配符 "名称。"
这在下面的例子中得到了展示。
名称传播
在对张量进行操作后,您不需要再次输入维度名称,它们将被自动传播。PyTorch使用了两个运算符--匹配和统一来进行名称传播:
- match是与上面定义的相同的运算符,它检查两个命名的张量是否可以匹配。
- unify是一个运算符,用于确定两个输入张量的名称中哪一个应被传播到结果张量。引用PyTorch官方文档的内容。
unify(A, B)决定了哪一个名字是 A和 B 传播到输出。如果这两个名字匹配,它将返回这两个名字中更具体的那个。如果名称不匹配,则会出错。
下面的例子展示了名称传播的情况:
- 一元运算符。
- 二元运算符。
限制
在写这篇文章的时候,命名张量的功能还处于实验阶段,可能会有很多变化。然而,目前命名张量的最大限制之一是它们不完全支持Autograd引擎。尽管命名张量的梯度计算是完全相同的,但是autograd引擎完全忽略了名称,以及它们所提供的额外安全性。
量化
PyTorch 1.3现在支持张量的量化。这是Tensorflow已经支持的东西,也是PyTorch非常期待的。量化是一个相当简单而又复杂的概念。我将通过回答三个问题--"是什么"、"为什么 "和 "如何",来简要介绍一下量化。
什么是量化?
量化是一种以低精度格式进行操作或将高精度数据格式转换为低精度数据格式的技术。例如,这是通过将32位浮点格式视为8位定点格式来实现的。如果有兴趣,你可以阅读一下定点和浮点运算及其相关的复杂性,以便更好地理解量化的必要性。
为什么 量化?
从事研究和创建神经网络模型的全部目的是为了部署它们,并使它们为公众服务。虽然模型训练的需求只与研究人员和机器学习从业人员的数量成正比增长,但对模式推理的需求却与消费者的数量成正比增长。为了让最终用户能够更多更好地使用,为推理而部署的模型的表示需要比它们在训练时的表示更加紧凑。另一件要记住的事情是,反向传播需要高精度的模型权重和偏差的表示。然而,在推理过程中,模型要稳健得多,不需要高精度表示。因此,一个大小为113.9MB的32位浮点表示的模型可以被量化为int8,大小为76.8MB。
如何在PyTorch v1.3中使用量化技术?
引用PyTorch官方文档的内容:
PyTorch支持INT8量化,与典型的FP32模型相比,可以使模型大小减少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()来访问。
下面是量化张量上支持的所有操作的列表。
移动支持
允许量化的自然目的是将PyTorch模型运送到对性能有要求的手机(和其他设备)上。他们已经为Android和iOS实现了端到端的PyTorch API。这将对减少推理延迟和用户隐私有很大影响。然而,PyTorch移动端目前处于早期实验阶段,它有几个限制。例如,目前的版本只支持前向传播(推理),不支持后向操作。
你可以在PyTorch官方网站上访问iOS和Android的hello world教程。
更多更新
除了这三个主要的更新之外,PyTorch v1.3还实现了其他一些变化和错误修复。你可以在PyTorch的官方Github仓库中查看所有的变化列表。其中一些功能是:
- 谷歌云上的PyTorch支持TPU。这里有一个Github repo,展示了如何在PyTorch中使用TPU。
- 对TensorBoard的扩展支持。3D网格和超参数
- 对torchscript的重大更新(主要是针对手机)。
- 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)。现在它不再返回 0D 张量,而是返回 1D 张量。
- nn.functional.affine_grid:当 align_corners = True 时,改变了一维数据上的二维仿生变换和二维数据上的三维仿生变换的行为(即,当其中一个空间维度具有单位大小时)。以前,沿单位维度的所有网格点被任意认为是在-1处,现在它们被认为是在0处(输入图像的中心)。
- torch.gels:移除已废弃的操作符,使用torch.lstsq代替。
- utils.data.DataLoader 将一些迭代器的属性改为私有(例如 num_workers, pin_memory)。
- pyTorch中针对C++的其他变化。