×

PyTorch教程3.4之从头开始执行线性回归

消耗积分:0 | 格式:pdf | 大小:0.26 MB | 2023-06-05

李红

分享资料个

我们现在准备好通过线性回归的全功能实现来工作。在本节中,我们将从头开始实现整个方法,包括(i)模型;(ii) 损失函数;(iii) 小批量随机梯度下降优化器;(iv) 将所有这些部分拼接在一起的训练功能。最后,我们将运行3.3 节中的合成数据生成器 并将我们的模型应用于生成的数据集。虽然现代深度学习框架几乎可以自动执行所有这些工作,但从头开始实施是确保您真正了解自己在做什么的唯一方法。此外,当需要自定义模型、定义我们自己的层或损失函数时,了解引擎盖下的工作原理将很方便。在本节中,我们将仅依赖张量和自动微分。稍后,我们将介绍一个更简洁的实现,利用深度学习框架的花哨功能,同时保留以下结构。

%matplotlib inline
import torch
from d2l import torch as d2l
%matplotlib inline
from mxnet import autograd, np, npx
from d2l import mxnet as d2l

npx.set_np()
%matplotlib inline
import jax
import optax
from flax import linen as nn
from jax import numpy as jnp
from d2l import jax as d2l
No GPU/TPU found, falling back to CPU. (Set TF_CPP_MIN_LOG_LEVEL=0 and rerun for more info.)
%matplotlib inline
import tensorflow as tf
from d2l import tensorflow as d2l

3.4.1. 定义模型

在我们开始通过小批量 SGD 优化模型参数之前,我们首先需要有一些参数。在下文中,我们通过从均值为 0 且标准差为 0.01 的正态分布中抽取随机数来初始化权重。幻数 0.01 在实践中通常效果很好,但您可以通过参数指定不同的值sigma此外,我们将偏差设置为 0。注意,对于面向对象的设计,我们将代码添加到__init__子类的方法中(在3.2.2 节d2l.Module中介绍 )。

class LinearRegressionScratch(d2l.Module): #@save
  """The linear regression model implemented from scratch."""
  def __init__(self, num_inputs, lr, sigma=0.01):
    super().__init__()
    self.save_hyperparameters()
    self.w = torch.normal(0, sigma, (num_inputs, 1), requires_grad=True)
    self.b = torch.zeros(1, requires_grad=True)
class LinearRegressionScratch(d2l.Module): #@save
  """The linear regression model implemented from scratch."""
  def __init__(self, num_inputs, lr, sigma=0.01):
    super().__init__()
    self.save_hyperparameters()
    self.w = np.random.normal(0, sigma, (num_inputs, 1))
    self.b = np.zeros(1)
    self.w.attach_grad()
    self.b.attach_grad()
class LinearRegressionScratch(d2l.Module): #@save
  """The linear regression model implemented from scratch."""
  num_inputs: int
  lr: float
  sigma: float = 0.01

  def setup(self):
    self.w = self.param('w', nn.initializers.normal(self.sigma),
              (self.num_inputs, 1))
    self.b = self.param('b', nn.initializers.zeros, (1))
class LinearRegressionScratch(d2l.Module): #@save
  """The linear regression model implemented from scratch."""
  def __init__(self, num_inputs, lr, sigma=0.01):
    super().__init__()
    self.save_hyperparameters()
    w = tf.random.normal((num_inputs, 1), mean=0, stddev=0.01)
    b = tf.zeros(1)
    self.w = tf.Variable(w, trainable=True)
    self.b = tf.Variable(b, trainable=True)

接下来,我们必须定义我们的模型,将其输入和参数与其输出相关联。在(3.1.4)中使用相同的符号,对于我们的线性模型,我们简单地采用输入特征的矩阵向量乘积X和模型权重w,并加上偏移量b每个例子。Xw是一个向量并且b是一个标量。由于广播机制(参见 第 2.1.4 节),当我们添加一个向量和一个标量时,标量将添加到向量的每个分量。生成的 方法 通过(在第 3.2.1 节中介绍 )forward在类中注册LinearRegressionScratchadd_to_class

@d2l.add_to_class(LinearRegressionScratch) #@save
def forward(self, X):
  return torch.matmul(X, self.w) + self.b
@d2l.add_to_class(LinearRegressionScratch) #@save
def forward(self, X):
  return np.dot(X, self.w) + self.b
@d2l.add_to_class(LinearRegressionScratch) #@save
def forward(self, X):
  return jnp.matmul(X, self.w) + self.b
@d2l.add_to_class(LinearRegressionScratch) #@save
def forward(self, X):
  return tf.matmul(X, self.w) + self.b

3.4.2. 定义损失函数

由于更新我们的模型需要采用损失函数的梯度,因此我们应该首先定义损失函数。这里我们使用(3.1.5)中的平方损失函数在实现中,我们需要将真实值转换y为预测值的形状 y_hat以下方法返回的结果也将具有与y_hat. 我们还返回小批量中所有示例的平均损失值。

@d2l.add_to_class(LinearRegressionScratch) #@save
def loss(self, y_hat, y):
  l = (y_hat - y) ** 2 / 2
  return l.mean()
@d2l.add_to_class(LinearRegressionScratch) #@save
def loss(self, y_hat, y):
  l = (y_hat - y) ** 2 / 2
  return l.mean()
@d2l.add_to_class(LinearRegressionScratch) #@save
def loss(self, params, X, y, state):
  y_hat = state.apply_fn({'params': params}, *X) # X unpacked from a tuple
  l = (y_hat - y.reshape(y_hat.shape)) ** 2 / 2
  return l.mean()
@d2l.add_to_class(LinearRegressionScratch) #@save
def loss(self, y_hat, y):
  l = (y_hat - y) ** 2 / 2
  return tf.reduce_mean(l)

3.4.3. 定义优化算法

正如第 3.1 节中所讨论的,线性回归有一个封闭形式的解决方案。然而,我们这里的目标是说明如何训练更通用的神经网络,这需要我们教您如何使用小批量 SGD。因此,我们将借此机会介绍您的第一个 SGD 工作示例。在每一步,使用从我们的数据集中随机抽取的小批量,我们估计损失相对于参数的梯度。接下来,我们朝着可能减少损失的方向更新参数。

以下代码应用更新,给定一组参数,一个学习率lr由于我们的损失是按小批量的平均值计算的,因此我们不需要根据批量大小调整学习率。在后面的章节中,我们将研究如何为分布式大规模学习中出现的非常大的小批量调整学习率。现在,我们可以忽略这种依赖性。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

评论(0)
发评论

下载排行榜

全部0条评论

快来发表一下你的评论吧 !