5.3. 延后初始化

到目前为止,我们忽略了建立网络时需要做的以下这些事情:

  • 我们定义了网络架构,但没有指定输入维度。

  • 我们添加层时没有指定前一层的输出维度。

  • 我们在初始化参数时,甚至没有足够的信息来确定模型应该包含多少参数。

有些读者可能会对我们的代码能运行感到惊讶。 毕竟,深度学习框架无法判断网络的输入维度是什么。 这里的诀窍是框架的延后初始化(defers initialization), 即直到数据第一次通过模型传递时,框架才会动态地推断出每个层的大小。

在以后,当使用卷积神经网络时, 由于输入维度(即图像的分辨率)将影响每个后续层的维数, 有了该技术将更加方便。 现在我们在编写代码时无须知道维度是什么就可以设置参数, 这种能力可以大大简化定义和修改模型的任务。 接下来,我们将更深入地研究初始化机制。

MindSpore通常需要在构造层时显式给出输入维度,当前版本没有与PyTorch LazyLinear完全等价的示例。本节保留延后初始化概念说明,代码示例仅在PyTorch tab中执行。

5.3.1. 实例化网络

首先,让我们实例化一个多层感知机。

import torch
from torch import nn

"""延后初始化"""
net = nn.Sequential(nn.LazyLinear(256), nn.ReLU(), nn.LazyLinear(10))
print(net[0].weight)  # 尚未初始化
print(net)

X = torch.rand(2, 20)
net(X)
print(net)
<UninitializedParameter>
Sequential(
  (0): LazyLinear(in_features=0, out_features=256, bias=True)
  (1): ReLU()
  (2): LazyLinear(in_features=0, out_features=10, bias=True)
)
Sequential(
  (0): Linear(in_features=20, out_features=256, bias=True)
  (1): ReLU()
  (2): Linear(in_features=256, out_features=10, bias=True)
)

此时,因为输入维数是未知的,所以网络不可能知道输入层权重的维数。 因此,框架尚未初始化任何参数,我们通过尝试访问以下参数进行确认。

print(net[0].weight)  # 尚未初始化
Parameter containing:
tensor([[ 0.1091,  0.1422,  0.0520,  ..., -0.0399,  0.2190,  0.1429],
        [-0.0815,  0.0779,  0.0685,  ...,  0.2235,  0.0533,  0.0506],
        [ 0.0323,  0.0585,  0.0745,  ..., -0.0087, -0.0745, -0.1964],
        ...,
        [ 0.0542, -0.2099,  0.0712,  ..., -0.1067, -0.1409,  0.0215],
        [-0.1885, -0.1407,  0.1094,  ..., -0.0611, -0.1195,  0.1671],
        [ 0.0294, -0.1404, -0.1274,  ...,  0.2232, -0.0385,  0.1760]],
       requires_grad=True)

请注意,每个层对象都存在,但权重为空。 此时代码将抛出一个错误,因为权重尚未初始化。

接下来让我们将数据通过网络,最终使框架初始化参数。

X = torch.rand(2, 20)
net(X)
print(net)
Sequential(
  (0): Linear(in_features=20, out_features=256, bias=True)
  (1): ReLU()
  (2): Linear(in_features=256, out_features=10, bias=True)
)

5.3.2. 小结

  • 延后初始化使框架能够自动推断参数形状,使修改模型架构变得容易,避免了一些常见的错误。

  • 我们可以通过模型传递数据,使框架最终初始化参数。

5.3.3. 练习

  1. 如果指定了第一层的输入尺寸,但没有指定后续层的尺寸,会发生什么?是否立即进行初始化?

  2. 如果指定了不匹配的维度会发生什么?

  3. 如果输入具有不同的维度,需要做什么?提示:查看参数绑定的相关内容。