动手学人工智能-深度学习计算3-延后初始化

88 阅读4分钟

在深度学习中,我们通常需要指定模型各层的输入和输出维度,以及初始化模型的参数。对于初学者来说,这些细节可能会导致困惑,尤其是当输入数据的维度无法提前确定时。PyTorch 提供了 torch.nn.LazyLinear 类,允许我们在模型定义时 延迟初始化参数,直到输入数据流过网络时,框架才会自动推断出每层的参数形状。

1. 延后初始化的概念

在传统的网络定义中,必须显式地指定每一层的输入维度。例如,在使用 nn.Linear 时,我们通常需要提前指定输入特征的数量。这些输入维度通常在模型构建时是不确定的,尤其是在处理变动数据形状时。为了解决这个问题,PyTorch 提供了 LazyLinear 层,它延迟对层参数的初始化,直到第一次通过数据进行前向传播时。

在使用 LazyLinear 时,我们不需要在定义时提供输入维度,只需要指定每一层的输出维度。PyTorch 会在第一次将数据传入网络时,自动推断输入维度并初始化参数。

2. 实例化网络

为了更好地理解延后初始化,我们来使用 torch.nn.LazyLinear 构建一个简单的多层感知机(MLP)网络。这个网络的输入维度会在数据通过网络时自动推断出来。

首先,我们定义一个简单的两层网络,使用 LazyLinear 来代替传统的 Linear 层:

import torch
from torch import nn

# 使用 LazyLinear 定义一个两层的网络
net = nn.Sequential(
    nn.LazyLinear(256),  # 第一层:输出维度256,输入维度将延后初始化
    nn.ReLU(),  # 激活函数:ReLU
    nn.LazyLinear(10)  # 第二层:输出维度10
)

在这段代码中,LazyLinear(256) 表示第一层有 256256 个神经元,但我们并未指定输入维度。第二层输出 1010 个值,依然没有指定输入维度。此时,LazyLinear 层将等待输入数据流过网络之后,自动推断出输入维度并进行初始化。

接下来,我们查看网络每层的权重矩阵形状:

# 查看每一层(注意:此时权重还未初始化)
for i, layer in enumerate(net):
    if isinstance(layer, nn.LazyLinear):
        print(f"第 {i + 1} 层(在前向传播之前): {layer}")

由于 LazyLinear 尚未接收到任何输入数据,权重矩阵的形状此时未被初始化,输出应该类似于:

第 1 层(在前向传播之前): LazyLinear(in_features=0, out_features=256, bias=True)
第 3 层(在前向传播之前): LazyLinear(in_features=0, out_features=10, bias=True)

3. 通过数据触发初始化

接下来,我们生成一个随机的输入数据,并将其传入网络。通过这个操作,LazyLinear 层会自动推断输入数据的维度,并初始化每层的权重矩阵。

# 生成一个随机输入数据
X = torch.randn(2, 20)  # 随机生成一个2x20的输入数据

# 将数据通过网络进行一次前向传播,触发参数初始化
output = net(X)

# 查看每一层的权重形状
for i, layer in enumerate(net):
    if isinstance(layer, nn.Linear):
        print(f"第 {i + 1}{layer} 的权重形状(在前向传播之后): {layer.weight.shape}")

此时,PyTorch 会根据输入数据的形状(2×202 \times 20)来推断出每层的权重矩阵形状,并初始化这些参数。输出结果应该类似于:

第 1 层 Linear(in_features=20, out_features=256, bias=True) 的权重形状(在前向传播之后): torch.Size([256, 20])
第 3 层 Linear(in_features=256, out_features=10, bias=True) 的权重形状(在前向传播之后): torch.Size([10, 256])
  • 第一层的权重矩阵形状为 20×25620 \times 256,表示输入数据的特征数是 20,而第一层有 256 个神经元。
  • 第二层的权重矩阵形状为 256×10256 \times 10,表示第一层的输出(256)与第二层神经元的数量(10)之间的映射关系。

4. 小结

延后初始化技术(如 LazyLinear)使得我们在定义神经网络时不需要事先指定每一层的输入维度。PyTorch 会在数据第一次流经网络时,根据数据的实际形状自动推断每层的输入输出维度,并初始化权重矩阵。这样,我们可以更加灵活地设计网络,避免在不知道输入数据形状的情况下硬编码维度,简化了模型定义和修改的过程。

通过延后初始化,模型结构可以更加灵活,并且减少了因维度错误导致的常见问题。尤其是在处理复杂或动态数据时,LazyLinear 是一个非常有用的工具,它提高了网络设计的可扩展性和灵活性。