在过去的十年中,深度学习见证了某种形式的寒武纪大爆发。技术、应用和算法的绝对数量远远超过了前几十年的进步。这是由于多种因素的偶然组合,其中之一是许多开源深度学习框架提供的强大的免费工具。Theano (Bergstra等人,2010 年)、DistBelief (Dean等人,2012 年)和 Caffe (Jia等人,2014 年)可以说代表了被广泛采用的第一代此类模型。与 SN2 (Simulateur Neuristique) 等早期(开创性)作品相比 (Bottou 和 Le Cun,1988),它提供了类似 Lisp 的编程体验,现代框架提供了自动微分和 Python 的便利性。这些框架使我们能够自动化和模块化实现基于梯度的学习算法的重复性工作。
在3.4 节中,我们仅依靠 (i) 张量进行数据存储和线性代数;(ii) 计算梯度的自动微分。在实践中,由于数据迭代器、损失函数、优化器和神经网络层非常普遍,现代图书馆也为我们实现了这些组件。在本节中,我们将向您展示如何 使用深度学习框架的高级 API 简洁地实现3.4 节中的线性回归模型。
No GPU/TPU found, falling back to CPU. (Set TF_CPP_MIN_LOG_LEVEL=0 and rerun for more info.)
3.5.1. 定义模型
当我们在第 3.4 节中从头开始实现线性回归时 ,我们明确定义了我们的模型参数并编写了计算代码以使用基本线性代数运算生成输出。你应该知道如何做到这一点。但是一旦您的模型变得更加复杂,并且一旦您几乎每天都必须这样做,您就会很高兴获得帮助。这种情况类似于从头开始编写自己的博客。做一两次是有益和有益的,但如果你花一个月重新发明轮子,你将成为一个糟糕的 Web 开发人员。
对于标准操作,我们可以使用框架的预定义层,这使我们能够专注于用于构建模型的层,而不用担心它们的实现。回想一下图 3.1.2中描述的单层网络的架构。该层称为全连接层,因为它的每个输入都通过矩阵向量乘法连接到它的每个输出。
在 PyTorch 中,全连接层定义在Linear
和 LazyLinear
(自版本 1.8.0 起可用)类中。后者允许用户仅指定输出维度,而前者额外询问有多少输入进入该层。指定输入形状很不方便,这可能需要大量的计算(例如在卷积层中)。因此,为简单起见,我们将尽可能使用此类“惰性”层。
In Gluon, the fully connected layer is defined in the Dense
class. Since we only want to generate a single scalar output, we set that number to 1. It is worth noting that, for convenience, Gluon does not require us to specify the input shape for each layer. Hence we do not need to tell Gluon how many inputs go into this linear layer. When we first pass data through our model, e.g., when we execute net(X)
later, Gluon will automatically infer the number of inputs to each layer and thus instantiate the correct model. We will describe how this works in more detail later.
In Keras, the fully connected layer is defined in the Dense
class. Since we only want to generate a single scalar output, we set that number to 1. It is worth noting that, for convenience, Keras does not require us to specify the input shape for each layer. We do not need to tell Keras how many inputs go into this linear layer. When we first try to pass data through our model, e.g., when we execute net(X)
later, Keras will automatically infer the number of inputs to each layer. We will describe how this works in more detail later.
class LinearRegression(d2l.Module): #@save
"""The linear regression model implemented with high-level APIs."""
def __init__(self, lr):
super().__init__()
self.save_hyperparameters()
initializer = tf.initializers.RandomNormal(stddev=0.01)
self.net = tf.keras.layers.Dense(1, kernel_initializer=initializer)
在forward
方法中,我们只调用预定义层的内置__call__
方法来计算输出。
3.5.2. 定义损失函数
该类MSELoss
计算均方误差(没有 1/2(3.1.5)中的因素)。默认情况下,MSELoss
返回示例的平均损失。它比我们自己实现更快(也更容易使用)。
The loss
module defines many useful loss functions. For speed and convenience, we forgo implementing our own and choose the built-in loss.L2Loss
instead. Because the loss
that it returns is the squared error for each example, we use mean
to average the loss across over the minibatch.
The MeanSquaredError
class computes the mean squared error (without the 1/2 factor in (3.1.5)). By default, it returns the average loss over examples.
3.5.3. 定义优化算法
Minibatch SGD 是用于优化神经网络的标准工具,因此 PyTorch 支持它以及模块中该算法的许多变体optim
。当我们实例化一个SGD
实例时,我们指定要优化的参数,可通过 和我们的优化算法所需的self.parameters()
学习率 ( ) 从我们的模型中获得。self.lr