AIGC原理与实践:零基础学大语言模型、扩散模型和多模态模型
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

2.1.2 构建神经网络的主要工具

使用PyTorch构建神经网络的主要工具(或类)及相互关系如图2-2所示。

图2-2 PyTorch实现神经网络的主要工具及相互关系

从图2-2可知,可以基于Module类或函数(nn.functional)构建网络层。nn中的大多数层(layer)在functional中都有与之对应的函数。nn.functional中的函数与nn.Module中的layer的主要区别是后者继承自Module类,可自动提取可学习的参数,而nn.functional更像是纯函数。

(1)nn.Module

前面我们使用autograd及Tensor实现机器学习实例时,需要做不少设置,如对叶子节点的参数requires_grad设置为True,然后调用backward,再从grad属性中提取梯度。对于大规模的网络,autograd过于底层和烦琐。为了简单、有效地解决这个问题,nn是一个有效工具。它是专门为深度学习设计的一个模块,而nn.Module是nn的一个核心数据结构。nn.Module可以是神经网络的某个层,也可以是包含多层的神经网络。在实际使用中,最常见的做法是继承nn.Module,生成自己的网络或层。nn中已实现了绝大多数层,包括全连接层、损失层、激活层、卷积层、循环层等。这些层都是nn.Module的子类,能够自动检测到自己的参数,并将其作为学习参数,且针对GPU运行进行了CuDNN优化。

(2)nn.functional

nn中的层,一类是继承了nn.Module,其命名一般为nn.Xxx(第一个字母是大写),如nn.Linear、nn.Conv2d、nn.CrossEntropyLoss等。另一类是nn.functional中的函数,其名称一般为nn.functional.xxx,如nn.functional.linear、nn.functional.conv2d、nn.functional.cross_entropy等。从功能来说,两者相当,基于nn.Module能实现的层也可以基于nn.functional实现,反之亦然,而且两者性能方面也没有太大差异。

不过在具体使用时,两者还是有区别的,具体如下。

1)nn.Xxx继承于nn.Module, nn.Xxx需要先实例化并传入参数,然后以函数调用的方式调用实例化的对象并传入输入数据。它能够很好地与nn.Sequential结合使用,而nn.functional.xxx无法与nn.Sequential结合使用。

2)nn.Xxx不需要自己定义和管理weight、bias参数;而nn.functional.xxx需要自己定义weight、bias参数,每次调用的时候都需要手动传入weight、bias等参数,不利于代码复用。

3)dropout操作在训练和测试阶段是有区别的,使用nn.Xxx方式定义dropout,在调用model.eval()之后,自动实现状态的转换,而使用nn.functional.xxx却无此功能。

总的来说,两种功能都是相同的,但PyTorch官方推荐:有学习参数的(如conv2d、linear、batch_norm、dropout等)情况采用nn.Xxx方式;没有学习参数的(如maxpool、loss func、activation func等)情况采用nn.functional.xxx或者nn.Xxx方式。对于激活函数,我们采用无学习参数的F.relu方式来实现,即nn.functional.xxx方式。