×

PyTorch教程3.2之面向对象的设计实现

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

陈飞

分享资料个

在我们对线性回归的介绍中,我们介绍了各种组件,包括数据、模型、损失函数和优化算法。事实上,线性回归是最简单的机器学习模型之一。然而,训练它使用许多与本书中其他模型所需的组件相同的组件。因此,在深入了解实现细节之前,有必要设计一些贯穿本书的 API。将深度学习中的组件视为对象,我们可以从为这些对象及其交互定义类开始。这种面向对象的实现设计将极大地简化演示,您甚至可能想在您的项目中使用它。

受PyTorch Lightning等开源库的启发,在高层次上我们希望拥有三个类:(i)Module包含模型、损失和优化方法;(ii)DataModule提供用于训练和验证的数据加载器;(iii) 两个类结合使用该类 Trainer,这使我们能够在各种硬件平台上训练模型。本书中的大部分代码都改编自Moduleand DataModuleTrainer只有在讨论 GPU、CPU、并行训练和优化算法时,我们才会涉及该类。

import time
import numpy as np
import torch
from torch import nn
from d2l import torch as d2l
import time
import numpy as np
from mxnet.gluon import nn
from d2l import mxnet as d2l
import time
from dataclasses import field
from typing import Any
import jax
import numpy as np
from flax import linen as nn
from flax.training import train_state
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 time
import numpy as np
import tensorflow as tf
from d2l import torch as d2l

3.2.1. 公用事业

我们需要一些实用程序来简化 Jupyter 笔记本中的面向对象编程。挑战之一是类定义往往是相当长的代码块。笔记本电脑的可读性需要简短的代码片段,穿插着解释,这种要求与 Python 库常见的编程风格不相容。第一个实用函数允许我们在创建类后将函数注册为类中的方法。事实上,即使我们已经创建了类的实例,我们也可以这样做!它允许我们将一个类的实现拆分成多个代码块。

def add_to_class(Class): #@save
  """Register functions as methods in created class."""
  def wrapper(obj):
    setattr(Class, obj.__name__, obj)
  return wrapper

让我们快速浏览一下如何使用它。我们计划 A用一个方法来实现一个类do我们可以先声明类并创建一个实例,而不是在同一个代码块中A同时 拥有两者的代码doAa

class A:
  def __init__(self):
    self.b = 1

a = A()

do接下来我们像往常一样 定义方法,但不在 classA的范围内。相反,我们add_to_class用类A作为参数来装饰这个方法。这样做时,该方法能够访问 的成员变量,A正如我们所期望的那样,如果它已被定义为 的A定义的一部分。让我们看看当我们为实例调用它时会发生什么a

@add_to_class(A)
def do(self):
  print('Class attribute "b" is', self.b)

a.do()
Class attribute "b" is 1
@add_to_class(A)
def do(self):
  print('Class attribute "b" is', self.b)

a.do()
Class attribute "b" is 1
@add_to_class(A)
def do(self):
  print('Class attribute "b" is', self.b)

a.do()
Class attribute "b" is 1
@add_to_class(A)
def do(self):
  print('Class attribute "b" is', self.b)

a.do()
Class attribute "b" is 1

第二个是实用程序类,它将类 __init__方法中的所有参数保存为类属性。这使我们无需额外代码即可隐式扩展构造函数调用签名。

class HyperParameters: #@save
  """The base class of hyperparameters."""
  def save_hyperparameters(self, ignore=[]):
    raise NotImplemented

我们将其实施推迟到第 23.7 节HyperParameters要使用它,我们定义继承自该方法并调用 save_hyperparameters该方法的类__init__

# Call the fully implemented HyperParameters class saved in d2l
class B(d2l.HyperParameters):
  def __init__(self, a, b, c):
    self.save_hyperparameters(ignore=['c'])
    print('self.a =', self.a, 'self.b =', self.b)
    print('There is no self.c =', not hasattr(self, 'c'))

b = B(a=1, b=2, c=3)
self.a = 1 self.b = 2
There is no self.c = True
# Call the fully implemented HyperParameters class saved in d2l
class B(d2l.HyperParameters):
  def __init__(self, a, b, c):
    self.save_hyperparameters(ignore=['c'])
    print('self.a =', self.a, 'self.b =', self.b)
    print('There is no self.c =', not hasattr(self, 'c'))

b = B(a=1, b=2, c=3)
self.a = 1 self.b = 2
There is no self.c = True
# Call the fully implemented HyperParameters class saved in d2l
class B(d2l.HyperParameters):
  def __init__(self, a, b, c):
    self.save_hyperparameters(ignore=['c'])
    print('self.a =', self.a, 'self.b =', self.b)
    print('There is no self.c =', not hasattr(self, 'c'))

b = B(a=1, b=2, c=3)
self.a = 1 self.b = 2
There is no self.c = True
# Call the fully implemented HyperParameters class saved in d2l
class B(d2l.HyperParameters):
  def __init__(self, a, b, c):
    self.save_hyperparameters(ignore=['c'])
    print('self.a =', self.a, 'self.b =', self.b)
    print('There is no self.c =', not hasattr(self, 'c'))

b = B(a=1, b=2, c=3)
self.a = 1 self.b = 2
There is no self.c = True

最后一个实用程序允许我们在实验进行时以交互方式绘制实验进度。为了尊重更强大(和复杂)的TensorBoard,我们将其命名为ProgressBoard实现推迟到 第 23.7 节现在,让我们简单地看看它的实际效果。

该方法在图中 draw绘制一个点,并在图例中指定。可选的仅通过显示来平滑线条(x, y)labelevery_n1/n图中的点。他们的价值是从平均n原始图中的邻居点。

class ProgressBoard(d2l.HyperParameters): #@save
  """The board that plots data points in animation."""
  def __init__(self, xlabel=None, ylabel=None, xlim=None,
         ylim=None, xscale='linear', yscale='linear',
         ls=['-', '--', '-.', ':'], colors=['C0', 'C1', 'C2', 'C3'],
         fig=None, axes=None, figsize=(3.5, 2.5), display=True):
    self.save_hyperparameters()

  def draw(self, x, y, label, every_n=1):
    raise NotImpleme

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

评论(0)
发评论

下载排行榜

全部0条评论

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