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

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

3天内不再提示

PyTorch教程-6.1. 层和模块

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

当我们第一次引入神经网络时,我们专注于具有单一输出的线性模型。在这里,整个模型只包含一个神经元。请注意,单个神经元 (i) 接受一组输入;(ii) 生成相应的标量输出;(iii) 有一组相关参数,可以更新这些参数以优化一些感兴趣的目标函数。然后,一旦我们开始考虑具有多个输出的网络,我们就利用矢量化算法来表征整个神经元层。就像单个神经元一样,层 (i) 采用一组输入,(ii) 生成相应的输出,并且 (iii) 由一组可调参数描述。当我们进行 softmax 回归时,单层本身就是模型。然而,即使我们随后引入了 MLP,

有趣的是,对于 MLP,整个模型及其组成层都共享这种结构。整个模型接受原始输入(特征),生成输出(预测),并拥有参数(来自所有构成层的组合参数)。同样,每个单独的层摄取输入(由前一层提供)生成输出(后续层的输入),并拥有一组可调参数,这些参数根据从后续层向后流动的信号进行更新。

虽然您可能认为神经元、层和模型为我们提供了足够的抽象来开展我们的业务,但事实证明,我们经常发现谈论比单个层大但比整个模型小的组件很方便。例如,在计算机视觉领域广受欢迎的 ResNet-152 架构拥有数百层。这些层由层组的重复图案组成。一次一层地实现这样的网络会变得乏味。这种担忧不仅仅是假设——这样的设计模式在实践中很常见。上面提到的 ResNet 架构赢得了 2015 年 ImageNet 和 COCO 计算机视觉识别和检测竞赛(He et al. , 2016)并且仍然是许多视觉任务的首选架构。层以各种重复模式排列的类似架构现在在其他领域无处不在,包括自然语言处理和语音。

为了实现这些复杂的网络,我们引入了神经网络模块的概念。模块可以描述单个层、由多个层组成的组件或整个模型本身!使用模块抽象的一个好处是它们可以组合成更大的工件,通常是递归的。如图 6.1.1所示。通过定义代码以按需生成任意复杂度的模块,我们可以编写出奇紧凑的代码并仍然实现复杂的神经网络。

poYBAGR9NP2AcRNaAAJd7roQfBs959.svg

图 6.1.1多层组合成模块,形成更大模型的重复模式。

编程的角度来看,模块由类表示。它的任何子类都必须定义一个前向传播方法,将其输入转换为输出,并且必须存储任何必要的参数。请注意,某些模块根本不需要任何参数。最后,为了计算梯度,模块必须具有反向传播方法。幸运的是,由于自动微分(在2.5 节中介绍)在定义我们自己的模块时提供了一些幕后魔法,我们只需要担心参数和前向传播方法。

import torch
from torch import nn
from torch.nn import functional as F

from mxnet import np, npx
from mxnet.gluon import nn

npx.set_np()

from typing import List
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

首先,我们重新审视用于实现 MLP 的代码(第 5.1 节)。以下代码生成一个网络,该网络具有一个具有 256 个单元和 ReLU 激活的全连接隐藏层,后跟一个具有 10 个单元的全连接输出层(无激活函数)。

net = nn.Sequential(nn.LazyLinear(256), nn.ReLU(), nn.LazyLinear(10))

X = torch.rand(2, 20)
net(X).shape

torch.Size([2, 10])

在这个例子中,我们通过实例化一个 来构造我们的模型 nn.Sequential,层按照它们应该被执行的顺序作为参数传递。简而言之,nn.Sequential定义了一种特殊的Module,在 PyTorch 中呈现模块的类。它维护一个有序的 constituent 列表Module。请注意,两个完全连接的层中的每一个都是该类的一个实例,Linear该类本身是 的子类Module。前向传播 ( forward) 方法也非常简单:它将列表中的每个模块链接在一起,将每个模块的输出作为输入传递给下一个模块。请注意,到目前为止,我们一直在通过构造调用我们的模型 net(X)以获得它们的输出。这实际上只是 net.__call__(X).

net = nn.Sequential()
net.add(nn.Dense(256, activation='relu'))
net.add(nn.Dense(10))
net.initialize()

X = np.random.uniform(size=(2, 20))
net(X).shape

(2, 10)

In this example, we constructed our model by instantiating an nn.Sequential, assigning the returned object to the net variable. Next, we repeatedly call its add method, appending layers in the order that they should be executed. In short, nn.Sequential defines a special kind of Block, the class that presents a module in Gluon. It maintains an ordered list of constituent Blocks. The add method simply facilitates the addition of each successive Block to the list. Note that each layer is an instance of the Dense class which is itself a subclass of Block. The forward propagation (forward) method is also remarkably simple: it chains each Block in the list together, passing the output of each as input to the next. Note that until now, we have been invoking our models via the construction net(X) to obtain their outputs. This is actually just shorthand for net.forward(X), a slick Python trick achieved via the Block class’s __call__ method.

net = nn.Sequential([nn.Dense(256), nn.relu, nn.Dense(10)])

# get_key is a d2l saved function returning jax.random.PRNGKey(random_seed)
X = jax.random.uniform(d2l.get_key(), (2, 20))
params = net.init(d2l.get_key(), X)
net.apply(params, X).shape

(2, 10)

net = tf.keras.models.Sequential([
  tf.keras.layers.Dense(256, activation=tf.nn.relu),
  tf.keras.layers.Dense(10),
])

X = tf.random.uniform((2, 20))
net(X).shape

TensorShape([2, 10])

In this example, we constructed our model by instantiating an keras.models.Sequential, with layers in the order that they should be executed passed as arguments. In short, Sequential defines a special kind of keras.Model, the class that presents a module in Keras. It maintains an ordered list of constituent Models. Note that each of the two fully connected layers is an instance of the Dense class which is itself a subclass of Model. The forward propagation (call) method is also remarkably simple: it chains each module in the list together, passing the output of each as input to the next. Note that until now, we have been invoking our models via the construction net(X) to obtain their outputs. This is actually just shorthand for net.call(X), a slick Python trick achieved via the module class’s __call__ method.

6.1.1. 自定义模块

也许培养关于模块如何工作的直觉的最简单方法是我们自己实现一个。在我们实现自己的自定义模块之前,我们先简单总结一下每个模块必须提供的基本功能:

摄取输入数据作为其前向传播方法的参数。

通过让前向传播方法返回一个值来生成输出。请注意,输出可能具有与输入不同的形状。例如,我们上面模型中的第一个全连接层接收任意维度的输入,但返回 256 维度的输出。

计算其输出相对于其输入的梯度,可以通过其反向传播方法访问。通常这会自动发生。

存储并提供对执行前向传播计算所需的那些参数的访问。

根据需要初始化模型参数。

在下面的代码片段中,我们从头开始编写一个模块,对应于一个包含 256 个隐藏单元的隐藏层和一个 10 维输出层的 MLP。请注意,MLP下面的类继承了代表模块的类。我们将严重依赖父类的方法,仅提供我们自己的构造函数(__init__ Python 中的方法)和前向传播方法。

class MLP(nn.Module):
  def __init__(self):
    # Call the constructor of the parent class nn.Module to perform
    # the necessary initialization
    super().__init__()
    self.hidden = nn.LazyLinear(256)
    self.out = nn.LazyLinear(10)

  # Define the forward propagation of the model, that is, how to return the
  # required model output based on the input X
  def forward(self, X):
    return self.out(F.relu(self.hidden(X)))

class MLP(nn.Block):
  def __init__(self):
    # Call the constructor of the MLP parent class nn.Block to perform
    # the necessary initialization
    super().__init__()
    self.hidden = nn.Dense(256, activation='relu')
    self.out = nn.Dense(10)

  # Define the forward propagation of the model, that is, how to return the
  # required model output based on the input X
  def forward(self, X):
    return self.out(self.hidden(X))

class MLP(nn.Module):
  def setup(self):
    # Define the layers
    self.hidden = nn.Dense(256)
    self.out = nn.Dense(10)

  # Define the forward propagation of the model, that is, how to return the
  # required model output based on the input X
  def __call__(self, X):
    return self.out(nn.relu(self.hidden(X)))

class MLP(tf.keras.Model):
  def __init__(self):
    # Call the constructor of the parent class tf.keras.Model to perform
    # the necessary initialization
    super().__init__()
    self.hidden = tf.keras.layers.Dense(units=256, activation=tf.nn.relu)
    self.out = tf.keras.layers.Dense(units=10)

  # Define the forward propagation of the model, that is, how to return the
  # required model output based on the input X
  def call(self, X):
    return self.out(self.hidden((X)))

让我们首先关注前向传播方法。请注意,它以 X输入为输入,应用激活函数计算隐藏表示,并输出其对数。在这个MLP 实现中,两层都是实例变量。要了解为什么这是合理的,想象一下实例化两个 MLPnet1和net2,并在不同的数据上训练它们。自然地,我们希望它们代表两种不同的学习模型。

我们在构造函数中实例化 MLP 的层,随后在每次调用前向传播方法时调用这些层。注意几个关键细节。首先,我们的自定义方法通过让我们免于重述适用于大多数模块的样板代码的痛苦来__init__调用父类的方法。然后我们实例化我们的两个完全连接的层,将它们分配给 和。请注意,除非我们实现一个新层,否则我们不必担心反向传播方法或参数初始化。系统会自动生成这些方法。让我们试试这个。__init__super().__init__()self.hiddenself.out

net = MLP()
net(X).shape

torch.Size([2, 10])

net = MLP()
net.initialize()
net(X).shape

(2, 10)

net = MLP()
params = net.init(d2l.get_key(), X)
net.apply(params, X).shape

(2, 10)

net = MLP()
net(X).shape

TensorShape([2, 10])

模块抽象的一个关键优点是它的多功能性。我们可以对模块进行子类化以创建层(例如全连接层类)、整个模型(例如MLP上面的类)或中等复杂度的各种组件。我们将在接下来的章节中利用这种多功能性,例如在处理卷积神经网络时。

6.1.2. 顺序模块

我们现在可以仔细看看这个Sequential类是如何工作的。回想一下,它Sequential的设计目的是将其他模块菊花链在一起。要构建我们自己的简化版MySequential,我们只需要定义两个关键方法:

一种将模块逐个附加到列表的方法。

一种前向传播方法,通过模块链传递输入,顺序与附加顺序相同。

以下MySequential类提供与默认Sequential类相同的功能。

class MySequential(nn.Module):
  def __init__(self, *args):
    super().__init__()
    for idx, module in enumerate(args):
      self.add_module(str(idx), module)

  def forward(self, X):
    for module in self.children():
      X = module(X)
    return X

在__init__方法中,我们通过调用方法来添加每个模块 add_modules。稍后可以通过该方法访问这些模块 children。这样系统就知道添加的模块,并且会正确地初始化每个模块的参数。

class MySequential(nn.Block):
  def add(self, block):
    # Here, block is an instance of a Block subclass, and we assume that
    # it has a unique name. We save it in the member variable _children of
    # the Block class, and its type is OrderedDict. When the MySequential
    # instance calls the initialize method, the system automatically
    # initializes all members of _children
    self._children[block.name] = block

  def forward(self, X):
    # OrderedDict guarantees that members will be traversed in the order
    # they were added
    for block in self._children.values():
      X = block(X)
    return X

The add method adds a single block to the ordered dictionary _children. You might wonder why every Gluon Block possesses a _children attribute and why we used it rather than just define a Python list ourselves. In short the chief advantage of _children is that during our block’s parameter initialization, Gluon knows to look inside the _children dictionary to find sub-blocks whose parameters also need to be initialized.

class MySequential(nn.Module):
  modules: List

  def __call__(self, X):
    for module in self.modules:
      X = module(X)
    return X

class MySequential(tf.keras.Model):
  def __init__(self, *args):
    super().__init__()
    self.modules = args

  def call(self, X):
    for module in self.modules:
      X = module(X)
    return X

当MySequential调用我们的前向传播方法时,每个添加的模块都按照添加的顺序执行。我们现在可以使用我们的类重新实现 MLP MySequential。

net = MySequential(nn.LazyLinear(256), nn.ReLU(), nn.LazyLinear(10))
net(X).shape

torch.Size([2, 10])

net = MySequential()
net.add(nn.Dense(256, activation='relu'))
net.add(nn.Dense(10))
net.initialize()
net(X).shape

(2, 10)

net = MySequential([nn.Dense(256), nn.relu, nn.Dense(10)])
params = net.init(d2l.get_key(), X)
net.apply(params, X).shape

(2, 10)

net = MySequential(
  tf.keras.layers.Dense(units=256, activation=tf.nn.relu),
  tf.keras.layers.Dense(10))
net(X).shape

TensorShape([2, 10])

请注意,此用法MySequential与我们之前为该类编写的代码相同(如第 5.1 节Sequential所述 )。

6.1.3. 在前向传播方法中执行代码

该类Sequential使模型构建变得容易,使我们无需定义自己的类就可以组装新的体系结构。然而,并非所有架构都是简单的菊花链。当需要更大的灵活性时,我们会想要定义我们自己的块。例如,我们可能希望在前向传播方法中执行 Python 的控制流。此外,我们可能想要执行任意数学运算,而不是简单地依赖于预定义的神经网络层。

您可能已经注意到,直到现在,我们网络中的所有操作都对我们网络的激活及其参数起作用。然而,有时我们可能想要合并既不是前几层结果也不是可更新参数的术语。我们称这些 为常量参数。比如说我们想要一个计算函数的层 f(x,w)=c⋅w⊤x, 在哪里x是输入,w是我们的参数,并且c是一些指定的常量,在优化期间不会更新。所以我们实现一个FixedHiddenMLP类如下。

class FixedHiddenMLP(nn.Module):
  def __init__(self):
    super().__init__()
    # Random weight parameters that will not compute gradients and
    # therefore keep constant during training
    self.rand_weight = torch.rand((20, 20))
    self.linear = nn.LazyLinear(20)

  def forward(self, X):
    X = self.linear(X)
    X = F.relu(X @ self.rand_weight + 1)
    # Reuse the fully connected layer. This is equivalent to sharing
    # parameters with two fully connected layers
    X = self.linear(X)
    # Control flow
    while X.abs().sum() > 1:
      X /= 2
    return X.sum()

class FixedHiddenMLP(nn.Block):
  def __init__(self):
    super().__init__()
    # Random weight parameters created with the get_constant method
    # are not updated during training (i.e., constant parameters)
    self.rand_weight = self.params.get_constant(
      'rand_weight', np.random.uniform(size=(20, 20)))
    self.dense = nn.Dense(20, activation='relu')

  def forward(self, X):
    X = self.dense(X)
    # Use the created constant parameters, as well as the relu and dot
    # functions
    X = npx.relu(np.dot(X, self.rand_weight.data()) + 1)
    # Reuse the fully connected layer. This is equivalent to sharing
    # parameters with two fully connected layers
    X = self.dense(X)
    # Control flow
    while np.abs(X).sum() > 1:
      X /= 2
    return X.sum()

class FixedHiddenMLP(nn.Module):
  # Random weight parameters that will not compute gradients and
  # therefore keep constant during training
  rand_weight: jnp.array = jax.random.uniform(d2l.get_key(), (20, 20))

  def setup(self):
    self.dense = nn.Dense(20)

  def __call__(self, X):
    X = self.dense(X)
    X = nn.relu(X @ self.rand_weight + 1)
    # Reuse the fully connected layer. This is equivalent to sharing
    # parameters with two fully connected layers
    X = self.dense(X)
    # Control flow
    while jnp.abs(X).sum() > 1:
      X /= 2
    return X.sum()

class FixedHiddenMLP(tf.keras.Model):
  def __init__(self):
    super().__init__()
    self.flatten = tf.keras.layers.Flatten()
    # Random weight parameters created with tf.constant are not updated
    # during training (i.e., constant parameters)
    self.rand_weight = tf.constant(tf.random.uniform((20, 20)))
    self.dense = tf.keras.layers.Dense(20, activation=tf.nn.relu)

  def call(self, inputs):
    X = self.flatten(inputs)
    # Use the created constant parameters, as well as the relu and
    # matmul functions
    X = tf.nn.relu(tf.matmul(X, self.rand_weight) + 1)
    # Reuse the fully connected layer. This is equivalent to sharing
    # parameters with two fully connected layers
    X = self.dense(X)
    # Control flow
    while tf.reduce_sum(tf.math.abs(X)) > 1:
      X /= 2
    return tf.reduce_sum(X)

在这个FixedHiddenMLP模型中,我们实现了一个隐藏层,其权重 ( self.rand_weight) 在实例化时随机初始化,此后保持不变。该权重不是模型参数,因此永远不会通过反向传播更新。然后网络将这个“固定”层的输出传递给一个全连接层。

请注意,在返回输出之前,我们的模型做了一些不寻常的事情。我们运行了一个 while 循环,测试它的条件ℓ1范数大于1,并将我们的输出向量除以2直到满足条件。最后,我们返回了 中条目的总和X。据我们所知,没有标准的神经网络执行此操作。请注意,此特定操作可能对任何实际任务都没有用。我们的目的只是向您展示如何将任意代码集成到您的神经网络计算流程中。

net = FixedHiddenMLP()
net(X)

tensor(-0.1058, grad_fn=)

net = FixedHiddenMLP()
net.initialize()
net(X)

array(0.52637565)

net = FixedHiddenMLP()
params = net.init(d2l.get_key(), X)
net.apply(params, X)

Array(-0.00932113, dtype=float32)

net = FixedHiddenMLP()
net(X)


我们可以混合搭配各种方式将模块组装在一起。在下面的示例中,我们以一些创造性的方式嵌套模块。

class NestMLP(nn.Module):
  def __init__(self):
    super().__init__()
    self.net = nn.Sequential(nn.LazyLinear(64), nn.ReLU(),
                 nn.LazyLinear(32), nn.ReLU())
    self.linear = nn.LazyLinear(16)

  def forward(self, X):
    return self.linear(self.net(X))

chimera = nn.Sequential(NestMLP(), nn.LazyLinear(20), FixedHiddenMLP())
chimera(X)

tensor(0.0964, grad_fn=)

class NestMLP(nn.Block):
  def __init__(self, **kwargs):
    super().__init__(**kwargs)
    self.net = nn.Sequential()
    self.net.add(nn.Dense(64, activation='relu'),
           nn.Dense(32, activation='relu'))
    self.dense = nn.Dense(16, activation='relu')

  def forward(self, X):
    return self.dense(self.net(X))

chimera = nn.Sequential()
chimera.add(NestMLP(), nn.Dense(20), FixedHiddenMLP())
chimera.initialize()
chimera(X)

array(0.9772054)

class NestMLP(nn.Module):
  def setup(self):
    self.net = nn.Sequential([nn.Dense(64), nn.relu,
                 nn.Dense(32), nn.relu])
    self.dense = nn.Dense(16)

  def __call__(self, X):
    return self.dense(self.net(X))


chimera = nn.Sequential([NestMLP(), nn.Dense(20), FixedHiddenMLP()])
params = chimera.init(d2l.get_key(), X)
chimera.apply(params, X)

Array(0.20007098, dtype=float32)

class NestMLP(tf.keras.Model):
  def __init__(self):
    super().__init__()
    self.net = tf.keras.Sequential()
    self.net.add(tf.keras.layers.Dense(64, activation=tf.nn.relu))
    self.net.add(tf.keras.layers.Dense(32, activation=tf.nn.relu))
    self.dense = tf.keras.layers.Dense(16, activation=tf.nn.relu)

  def call(self, inputs):
    return self.dense(self.net(inputs))

chimera = tf.keras.Sequential()
chimera.add(NestMLP())
chimera.add(tf.keras.layers.Dense(20))
chimera.add(FixedHiddenMLP())
chimera(X)


6.1.4. 概括

层是模块。许多层可以组成一个模块。许多模块可以组成一个模块。

模块可以包含代码。模块负责很多内部事务,包括参数初始化和反向传播。层和模块的顺序连接由模块处理Sequential 。

6.1.5. 练习

如果改用MySequentialPython列表存储模块会出现什么样的问题?

实现一个将两个模块作为参数的模块,比如 net1和net2并在前向传播中返回两个网络的串联输出。这也称为并行模块。

假设您想要连接同一网络的多个实例。实现一个工厂函数,生成同一模块的多个实例,并从中构建一个更大的网络。

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

    关注

    2

    文章

    808

    浏览量

    13216
收藏 人收藏

    评论

    相关推荐

    PyTorch如何入门

    PyTorch 入门实战(一)——Tensor
    发表于 06-01 09:58

    Pytorch AI语音助手

    想做一个Pytorch AI语音助手,有没有好的思路呀?
    发表于 03-06 13:00

    怎样使用PyTorch Hub去加载YOLOv5模型

    在Python>=3.7.0环境中安装requirements.txt,包括PyTorch>=1.7。模型和数据集从最新的 YOLOv5版本自动下载。简单示例此示例从
    发表于 07-22 16:02

    如何往星光2板子里装pytorch

    如题,想先gpu版本的pytorch只安装cpu版本的pytorch,pytorch官网提供了基于conda和pip两种安装方式。因为咱是risc架构没对应的conda,而使用pip安装提示也没有
    发表于 09-12 06:30

    SRWF-1(V6.1)无线模块使用说明书

    SRWF-1(V6.1)无线模块,很好的无线模块资料,快来下载学习吧
    发表于 03-29 10:58 0次下载

    Caffe2 和 PyTorch 代码合并旨为提高开发效率

    按照贾扬清的说法,Facebook 去年启动 ONNX 项目并组建团队时,就已经开始推动 Caffe2 和 PyTorch 在代码的合并。
    的头像 发表于 04-30 09:16 3490次阅读

    基于PyTorch的深度学习入门教程之PyTorch简单知识

    本文参考PyTorch官网的教程,分为五个基本模块来介绍PyTorch。为了避免文章过长,这五个模块分别在五篇博文中介绍。 Part1:PyTorc
    的头像 发表于 02-16 15:20 2256次阅读

    基于PyTorch的深度学习入门教程之PyTorch的自动梯度计算

    本文参考PyTorch官网的教程,分为五个基本模块来介绍PyTorch。为了避免文章过长,这五个模块分别在五篇博文中介绍。 Part1:PyTorc
    的头像 发表于 02-16 15:26 2026次阅读

    基于PyTorch的深度学习入门教程之使用PyTorch构建一个神经网络

            前言 本文参考PyTorch官网的教程,分为五个基本模块来介绍PyTorch。为了避免文章过长,这五个模块分别在五篇博文中介绍。 Part1:
    的头像 发表于 02-15 09:40 2098次阅读

    基于PyTorch的深度学习入门教程之PyTorch重点综合实践

    实例。该网络有一个隐含,使用梯度下降来训练,目标是最小化网络输出和真实输出之间的欧氏距离。 目录 Tensors(张量) Warm-up:numpy PyTorch:Tensors Autograd
    的头像 发表于 02-15 10:01 1782次阅读

    PyTorch中使用ReLU激活函数的例子

    PyTorch已为我们实现了大多数常用的非线性激活函数,我们可以像使用任何其他的那样使用它们。让我们快速看一个在PyTorch中使用ReLU激活函数的例子:
    的头像 发表于 07-06 15:27 2541次阅读

    PyTorch教程6.1模块

    电子发烧友网站提供《PyTorch教程6.1模块.pdf》资料免费下载
    发表于 06-05 15:23 0次下载
    <b class='flag-5'>PyTorch</b>教程<b class='flag-5'>6.1</b>之<b class='flag-5'>层</b>和<b class='flag-5'>模块</b>

    PyTorch教程7.1之从全连接到卷积

    电子发烧友网站提供《PyTorch教程7.1之从全连接到卷积.pdf》资料免费下载
    发表于 06-05 11:50 0次下载
    <b class='flag-5'>PyTorch</b>教程7.1之从全连接<b class='flag-5'>层</b>到卷积

    PyTorch神经网络模型构建过程

    PyTorch,作为一个广泛使用的开源深度学习库,提供了丰富的工具和模块,帮助开发者构建、训练和部署神经网络模型。在神经网络模型中,输出是尤为关键的部分,它负责将模型的预测结果以合适的形式输出。以下将详细解析
    的头像 发表于 07-10 14:57 495次阅读

    PyTorch 数据加载与处理方法

    ,数据加载主要依赖于 torch.utils.data 模块,该模块提供了 Dataset 和 DataLoader 两个核心类。 1.1 Dataset 类 Dataset 类是 PyTorch 中所
    的头像 发表于 11-05 17:37 393次阅读