×

PyTorch教程5.2之多层感知器的实现

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

分享资料个

多层感知器 (MLP) 的实现并不比简单的线性模型复杂多少。关键的概念差异是我们现在连接多个层。

import torch
from torch import nn
from d2l import torch as d2l
from mxnet import np, npx
from mxnet.gluon import nn
from d2l import mxnet as d2l

npx.set_np()
import jax
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.)
import tensorflow as tf
from d2l import tensorflow as d2l

5.2.1. 从零开始实施

让我们从头开始实现这样一个网络。

5.2.1.1. 初始化模型参数

回想一下,Fashion-MNIST 包含 10 个类,并且每个图像由一个28×28=784灰度像素值网格。和以前一样,我们暂时忽略像素之间的空间结构,因此我们可以将其视为具有 784 个输入特征和 10 个类别的分类数据集。首先,我们将实现一个具有一个隐藏层和 256 个隐藏单元的 MLP。层数和宽度都是可调的(它们被认为是超参数)。通常,我们选择层宽度可以被 2 的较大次幂整除。由于内存在硬件中分配和寻址的方式,这在计算上是高效的。

同样,我们将用几个张量表示我们的参数。请注意, 对于每一层,我们必须跟踪一个权重矩阵和一个偏置向量。与往常一样,我们为这些参数的损失梯度分配内存。

在下面的代码中,我们使用 `nn.Parameter< https://pytorch.org/docs/stable/generated/torch.nn.parameter.Parameter.html >`__ 自动将类属性注册为要跟踪的参数autograd第 2.5 节) .

class MLPScratch(d2l.Classifier):
  def __init__(self, num_inputs, num_outputs, num_hiddens, lr, sigma=0.01):
    super().__init__()
    self.save_hyperparameters()
    self.W1 = nn.Parameter(torch.randn(num_inputs, num_hiddens) * sigma)
    self.b1 = nn.Parameter(torch.zeros(num_hiddens))
    self.W2 = nn.Parameter(torch.randn(num_hiddens, num_outputs) * sigma)
    self.b2 = nn.Parameter(torch.zeros(num_outputs))

In the code below, we first define and initialize the parameters and then enable gradient tracking.

class MLPScratch(d2l.Classifier):
  def __init__(self, num_inputs, num_outputs, num_hiddens, lr, sigma=0.01):
    super().__init__()
    self.save_hyperparameters()
    self.W1 = np.random.randn(num_inputs, num_hiddens) * sigma
    self.b1 = np.zeros(num_hiddens)
    self.W2 = np.random.randn(num_hiddens, num_outputs) * sigma
    self.b2 = np.zeros(num_outputs)
    for param in self.get_scratch_params():
      param.attach_grad()

In the code below we use `flax.linen.Module.param <https://flax.readthedocs.io/en/latest/api_reference/flax.linen.html#flax.linen.Module.param>`__ to define the model parameter.

class MLPScratch(d2l.Classifier):
  num_inputs: int
  num_outputs: int
  num_hiddens: int
  lr: float
  sigma: float = 0.01

  def setup(self):
    self.W1 = self.param('W1', nn.initializers.normal(self.sigma),
               (self.num_inputs, self.num_hiddens))
    self.b1 = self.param('b1', nn.initializers.zeros, self.num_hiddens)
    self.W2 = self.param('W2', nn.initializers.normal(self.sigma),
               (self.num_hiddens, self.num_outputs))
    self.b2 = self.param('b2', nn.initializers.zeros, self.num_outputs)

In the code below we use `tf.Variable <https://www.tensorflow.org/api_docs/python/tf/Variable>`__ to define the model parameter.

class MLPScratch(d2l.Classifier):
  def __init__(self, num_inputs, num_outputs, num_hiddens, lr, sigma=0.01):
    super().__init__()
    self.save_hyperparameters()
    self.W1 = tf.Variable(
      tf.random.normal((num_inputs, num_hiddens)) * sigma)
    self.b1 = tf.Variable(tf.zeros(num_hiddens))
    self.W2 = tf.Variable(
      tf.random.normal((num_hiddens, num_outputs)) * sigma)
    self.b2 = tf.Variable(tf.zeros(num_outputs))

5.2.1.2. 模型

为了确保我们知道一切是如何工作的,我们将自己实现 ReLU 激活,而不是直接调用内置relu函数。

def relu(X):
  a = torch.zeros_like(X)
  return torch.max(X, a)
def relu(X):
  return np.maximum(X, 0)
def relu(X):
  return jnp.maximum(X, 0)
def relu(X):
  return tf.math.maximum(X, 0)

由于我们忽略了空间结构,我们将reshape每个二维图像转换为长度为 的平面向量num_inputs最后,我们只用几行代码就实现了我们的模型。由于我们使用框架内置的 autograd,这就是它所需要的全部。

@d2l.add_to_class(MLPScratch)
def forward(self, X):
  X = X.reshape((-1, self.num_inputs))
  H = relu(torch.matmul(X, self.W1) + self.b1)
  return torch.matmul(H, self.W2) + self.b2
@d2l.add_to_class(MLPScratch)
def forward(self, X):
  X = X.reshape((-1, self.num_inputs))
  H = relu(np.dot(X, self.W1) + self.b1)
  return np.dot(H, self.W2) + self.b2
@d2l.add_to_class(MLPScratch)
def forward(self, X):
  X = X.reshape((-1, self.num_inputs))
  H = relu(jnp.matmul(X, self.W1) + self.b1)
  return jnp.matmul(H, self.W2) + self.b2
@d2l.add_to_class(MLPScratch)
def forward(self, X):
  X = tf.reshape(X, (-1, self.num_inputs))
  H = relu(tf.matmul(X, self.W1) + self.b1)
  return tf.matmul(H, self.W2) + self.b2

5.2.1.3. 训练

幸运的是,MLP 的训练循环与 softmax 回归完全相同。我们定义模型、数据、训练器,最后fit在模型和数据上调用方法。


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

评论(0)
发评论

下载排行榜

全部0条评论

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