0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

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

jf_pJlTbmA9 来源:PyTorch 作者:PyTorch 2023-06-05 15:43 次阅读

多层感知器 (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 `__ 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 `__ 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在模型和数据上调用方法。

model = MLPScratch(num_inputs=784, num_outputs=10, num_hiddens=256, lr=0.1)
data = d2l.FashionMNIST(batch_size=256)
trainer = d2l.Trainer(max_epochs=10)
trainer.fit(model, data)

poYBAGR9NJeAcxmqAAGBExPEUqc353.svg

model = MLPScratch(num_inputs=784, num_outputs=10, num_hiddens=256, lr=0.1)
data = d2l.FashionMNIST(batch_size=256)
trainer = d2l.Trainer(max_epochs=10)
trainer.fit(model, data)

poYBAGR9NJmAGTC8AAGCCLiJXcw943.svg

model = MLPScratch(num_inputs=784, num_outputs=10, num_hiddens=256, lr=0.1)
data = d2l.FashionMNIST(batch_size=256)
trainer = d2l.Trainer(max_epochs=10)
trainer.fit(model, data)

pYYBAGR9NJyAM_ysAAGCybKjia0271.svg

model = MLPScratch(num_inputs=784, num_outputs=10, num_hiddens=256, lr=0.1)
data = d2l.FashionMNIST(batch_size=256)
trainer = d2l.Trainer(max_epochs=10)
trainer.fit(model, data)

pYYBAGR9NJ6AeFYhAAGBuQZFjtY204.svg

5.2.2. 简洁的实现

正如您所料,通过依赖高级 API,我们可以更简洁地实现 MLP。

5.2.2.1. 模型

与我们对 softmax 回归实现的简洁实现(第 4.5 节)相比,唯一的区别是我们添加了两个完全连接的层,而我们之前只添加了 一个。第一个是隐藏层,第二个是输出层。

class MLP(d2l.Classifier):
  def __init__(self, num_outputs, num_hiddens, lr):
    super().__init__()
    self.save_hyperparameters()
    self.net = nn.Sequential(nn.Flatten(), nn.LazyLinear(num_hiddens),
                 nn.ReLU(), nn.LazyLinear(num_outputs))

class MLP(d2l.Classifier):
  def __init__(self, num_outputs, num_hiddens, lr):
    super().__init__()
    self.save_hyperparameters()
    self.net = nn.Sequential()
    self.net.add(nn.Dense(num_hiddens, activation='relu'),
           nn.Dense(num_outputs))
    self.net.initialize()

class MLP(d2l.Classifier):
  num_outputs: int
  num_hiddens: int
  lr: float

  @nn.compact
  def __call__(self, X):
    X = X.reshape((X.shape[0], -1)) # Flatten
    X = nn.Dense(self.num_hiddens)(X)
    X = nn.relu(X)
    X = nn.Dense(self.num_outputs)(X)
    return X

class MLP(d2l.Classifier):
  def __init__(self, num_outputs, num_hiddens, lr):
    super().__init__()
    self.save_hyperparameters()
    self.net = tf.keras.models.Sequential([
      tf.keras.layers.Flatten(),
      tf.keras.layers.Dense(num_hiddens, activation='relu'),
      tf.keras.layers.Dense(num_outputs)])

以前,我们forward为模型定义了使用模型参数转换输入的方法。这些操作本质上是一个管道:您获取一个输入并应用一个转换(例如,矩阵与权重相乘,然后是偏差加法),然后重复使用当前转换的输出作为下一个转换的输入。但是,您可能已经注意到 forward这里没有定义任何方法。实际上,从类(第 3.2.2 节MLP)继承 方法以简单地调用 (是输入),现在定义为通过类进行的一系列转换。该类抽象了前向过程,使我们能够专注于转换。我们将进一步讨论如何forwardModuleself.net(X)XSequentialSequentialSequential类在第 6.1.2 节中起作用 。

5.2.2.2. 训练

训练循环与我们实现 softmax 回归时完全相同。这种模块化使我们能够将有关模型架构的问题与正交考虑分开。

model = MLP(num_outputs=10, num_hiddens=256, lr=0.1)
trainer.fit(model, data)

poYBAGR9NKGAMJGUAAF5pOY74F4213.svg

model = MLP(num_outputs=10, num_hiddens=256, lr=0.1)
trainer.fit(model, data)

pYYBAGR9NKSANquDAAF72nzDx0M343.svg

model = MLP(num_outputs=10, num_hiddens=256, lr=0.1)
trainer.fit(model, data)

pYYBAGR9NKeAEH6HAAF08_rOZ80451.svg

model = MLP(num_outputs=10, num_hiddens=256, lr=0.1)
trainer.fit(model, data)

poYBAGR9NKmAX8IxAAGKzgziMks047.svg

5.2.3. 概括

现在我们在设计深度网络方面有了更多的实践,从单层到多层深度网络的步骤不再构成如此重大的挑战。特别是,我们可以重用训练算法和数据加载器。但请注意,从头开始实施 MLP 仍然很麻烦:命名和跟踪模型参数使得扩展模型变得困难。例如,假设想要在第 42 层和第 43 层之间插入另一层。这可能是第 42b 层,除非我们愿意执行顺序重命名。此外,如果我们从头开始实施网络,框架就很难执行有意义的性能优化。

尽管如此,您现在已经达到了 1980 年代后期的最先进水平,当时完全连接的深度网络是神经网络建模的首选方法。我们的下一个概念性步骤将是考虑图像。在我们这样做之前,我们需要回顾一些关于如何有效计算模型的统计基础知识和细节。

5.2.4. 练习

更改隐藏单元的数量num_hiddens并绘制其数量如何影响模型的准确性。这个超参数的最佳值是多少?

尝试添加隐藏层以查看它如何影响结果。

为什么用单个神经元插入隐藏层是个坏主意?会出什么问题?

改变学习率如何改变你的结果?在所有其他参数固定的情况下,哪个学习率能给你最好的结果?这与纪元数有何关系?

让我们联合优化所有超参数,即学习率、时期数、隐藏层数和每层隐藏单元数。

通过对所有这些进行优化可以获得的最佳结果是什么?

为什么处理多个超参数更具挑战性?

描述联合优化多个参数的有效策略。

比较框架的速度和从头开始实施一个具有挑战性的问题。它如何随着网络的复杂性而变化?

测量对齐良好和未对齐矩阵的张量矩阵乘法的速度。例如,测试维度为 1024、1025、1026、1028 和 1032 的矩阵。

这在 GPU 和 CPU 之间有何变化?

确定 CPU 和 GPU 的内存总线宽度。

尝试不同的激活函数。哪一个效果最好?

网络的权重初始化之间是否存在差异?有关系吗?

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

    关注

    0

    文章

    32

    浏览量

    11793
  • pytorch
    +关注

    关注

    2

    文章

    763

    浏览量

    12836
收藏 人收藏

    评论

    相关推荐

    感知分类,BP,Hopfield等MATLAB代码

    感知器分类、BP网络函数逼近、Hopfield网络求逼近平衡点等神经网络实验用到的一些代码。附件:
    发表于 02-28 09:32

    DL:DL单层感知器Perceptron的原理及Perceptron Can not solve XOR problem

    DL:DL单层感知器Perceptron的原理及PerceptronCan not solveXOR problem
    发表于 12-21 10:35

    上海逻迅门磁感知器系统方案

    `上海逻迅门磁感知器方案`
    发表于 02-18 13:33

    如何使用Keras框架搭建一个小型的神经网络多层感知器

    本文介绍了如何使用Keras框架,搭建一个小型的神经网络-多层感知器,并通过给定数据进行计算训练,最好将训练得到的模型提取出参数,放在51单片机上进行运行。
    发表于 11-22 07:00

    多层感知器在提高软件可维护性上的应用

    预测分析软件质量可看作是一个以源代码度量作为属性标签、模块性能作为类标签的分类问题。首次提出将多层感知器应用于软件质量预测,并使用对称不定性分析来提高其分类性能。
    发表于 04-06 00:01 20次下载

    多层感知器和反向传播进行入门级的介绍

    本文对多层感知器和反向传播进行入门级的介绍。人工神经网络是一种计算模型,启发自人类大脑处理信息的生物神经网络。 人工神经网络是一种计算模型,启发自人类大脑处理信息的生物神经网络。人工神经网络在语音识别、计算机视觉和文本处理领域取得了一系列突破,让机器学习研究和产业感到了兴
    发表于 11-15 15:26 4157次阅读

    人工智能–多层感知器基础知识解读

    感知器(Perceptron)是ANN人工神经网络的一个概念,由Frank Rosenblatt于1950s第一次引入。 MLP多层感知器是一种前向结构的ANN人工神经网络, 多层
    发表于 07-05 14:45 5825次阅读

    利用人工神经网络感知器实现双足行走机器人的稳定性控制

    本文采用的神经网络感知器(Perception)是最简单的人工神经网络,它是FRosenblatt于1958年提出的具有自学习能力的感知器。在这种人工神经网络中,记忆的信息存储在连接权上,外部刺激
    的头像 发表于 09-20 07:55 1714次阅读
    利用人工神经网络<b class='flag-5'>感知器</b><b class='flag-5'>实现</b>双足行走机器人的稳定性控制

    使用MATLAB编写单层感知器的函数免费下载

    本文档的主要内容详细介绍的是使用MATLAB编写单层感知器的函数免费下载。
    发表于 08-13 16:55 4次下载

    关于门磁感知器SG6AD,它的特点有哪些

    门磁感知器SG6AD的特点有哪些? 门磁感知器SG6AD是逻迅公司研发生产的一种应用于物联网智能监测感知器。通过磁性感应、位移等多种传感器结合,实时监测门的开关闭合状况。可设定监测参数(如开启、闭合
    发表于 06-19 16:13 555次阅读

    上海逻迅官网资讯:门磁感知器SG6AD系统架构方案有哪些?

    上海逻迅官网资讯:门磁感知器SG6AD系统架构方案有哪些? 门磁感知器SG6AD是逻迅公司研发生产的一种应用于物联网智能监测感知器。通过磁性感应、位移等多种传感器结合,实时监测门的开关闭合状况。可设
    发表于 04-24 10:09 783次阅读

    关于机器人的五大感知器

    机器视觉和传感器的应用就使得机器人的发展迈出了关键一步,人的五大感知器官与机器人感知器官对应的就是传统的光学图像传感器,力传感器等,具有视觉和力传感器的机器人能够看见,能够以较慢速度和物体接触,能触碰更细微的表面,这使得其更加容易和人类进行交互。
    发表于 08-03 11:03 5006次阅读

    PyTorch教程5.2多层感知器实现

    电子发烧友网站提供《PyTorch教程5.2多层感知器实现.pdf》资料免费下载
    发表于 06-05 15:32 0次下载
    <b class='flag-5'>PyTorch</b>教程<b class='flag-5'>5.2</b>之<b class='flag-5'>多层</b><b class='flag-5'>感知器</b>的<b class='flag-5'>实现</b>

    PyTorch教程21.7之序列感知推荐系统

    电子发烧友网站提供《PyTorch教程21.7之序列感知推荐系统.pdf》资料免费下载
    发表于 06-06 09:31 0次下载
    <b class='flag-5'>PyTorch</b>教程21.7之序列<b class='flag-5'>感知</b>推荐系统

    使用多层感知器进行机器学习

    我们将使用一个极其复杂的微处理器来实现一个神经网络,该神经网络可以完成与由少数晶体管组成的电路相同的事情,这个想法有些幽默。但与此同时,以这种方式思考这个问题强调了单层感知器作为一般分类和函数逼近工具的不足——如果我们的感知器
    的头像 发表于 06-24 11:17 340次阅读
    使用<b class='flag-5'>多层</b><b class='flag-5'>感知器</b>进行机器学习