动手学深度学习4.7 no Video /chapter_multilayer-perceptrons/backprop.ipynb.ipynb

小结

  • 前向传播在神经网络定义的计算图中按顺序计算和存储中间变量,它的顺序是从输入层到输出层。
  • 反向传播按相反的顺序(从输出层到输入层)计算和存储神经网络的中间变量和参数的梯度。
  • 在训练深度学习模型时,前向传播和反向传播是相互依赖的。
  • 训练比预测需要更多的内存。

练习

  1. 向本节中描述的模型的隐藏层添加偏置项(不需要在正则化项中包含偏置项)。

    1. 画出相应的计算图。
    2. 推导正向和反向传播方程。

    正向传播方程及各变量维度

    1. 输入数据 X \mathbf{X} X:

      • 维度: n × m n \times m n×m
    2. 隐藏层线性变换:
      Z = X W + b \mathbf{Z} = \mathbf{X} \mathbf{W} + \mathbf{b} Z=XW+b

      • W \mathbf{W} W: 权重矩阵, 维度 m × h m \times h m×h
      • b \mathbf{b} b: 偏置向量, 维度 1 × h 1 \times h 1×h
      • Z \mathbf{Z} Z: 隐藏层输入, 维度 n × h n \times h n×h
    3. 隐藏层激活:
      A = σ ( Z ) \mathbf{A} = \sigma(\mathbf{Z}) A=σ(Z)

      • A \mathbf{A} A: 激活值, 维度 n × h n \times h n×h
    4. 输出层线性变换:
      Y = A V + c \mathbf{Y} = \mathbf{A} \mathbf{V} + \mathbf{c} Y=AV+c

      • V \mathbf{V} V: 权重矩阵, 维度 h × o h \times o h×o
      • c \mathbf{c} c: 偏置向量, 维度 1 × o 1 \times o 1×o
      • Y \mathbf{Y} Y: 输出, 维度 n × o n \times o n×o

    反向传播方程及各变量维度

    假设损失函数为 L ( Y , T ) L(\mathbf{Y}, \mathbf{T}) L(Y,T),其中 T \mathbf{T} T 是真实标签,维度为 n × o n \times o n×o。我们通过链式法则计算各参数的梯度。

    1. 输出层反向传播:

      • 输出层损失梯度:
        ∂ L ∂ Y = ∂ L ∂ Y \frac{\partial L}{\partial \mathbf{Y}} = \frac{\partial L}{\partial \mathbf{Y}} YL=YL

      • 维度: n × o n \times o n×o

      • 输出层权重梯度:
        ∂ L ∂ V = A T ∂ L ∂ Y \frac{\partial L}{\partial \mathbf{V}} = \mathbf{A}^T \frac{\partial L}{\partial \mathbf{Y}} VL=ATYL

      • ∂ L ∂ V \frac{\partial L}{\partial \mathbf{V}} VL: 维度 h × o h \times o h×o

      • A T \mathbf{A}^T AT: 维度 h × n h \times n h×n

      • ∂ L ∂ Y \frac{\partial L}{\partial \mathbf{Y}} YL: 维度 n × o n \times o n×o

      • 输出层偏置梯度:
        ∂ L ∂ c = ∑ i = 1 n ∂ L ∂ Y i \frac{\partial L}{\partial \mathbf{c}} = \sum_{i=1}^{n} \frac{\partial L}{\partial \mathbf{Y}_i} cL=i=1nYiL

      • ∂ L ∂ c \frac{\partial L}{\partial \mathbf{c}} cL: 维度 1 × o 1 \times o 1×o

      • 激活值梯度:
        ∂ L ∂ A = ∂ L ∂ Y V T \frac{\partial L}{\partial \mathbf{A}} = \frac{\partial L}{\partial \mathbf{Y}} \mathbf{V}^T AL=YLVT

      • ∂ L ∂ A \frac{\partial L}{\partial \mathbf{A}} AL: 维度 n × h n \times h n×h

      • ∂ L ∂ Y \frac{\partial L}{\partial \mathbf{Y}} YL: 维度 n × o n \times o n×o

      • V T \mathbf{V}^T VT: 维度 o × h o \times h o×h

    2. 隐藏层反向传播:

      • 激活函数梯度:
        ∂ L ∂ Z = ∂ L ∂ A ⊙ σ ′ ( Z ) \frac{\partial L}{\partial \mathbf{Z}} = \frac{\partial L}{\partial \mathbf{A}} \odot \sigma'(\mathbf{Z}) ZL=ALσ(Z)

      • ∂ L ∂ Z \frac{\partial L}{\partial \mathbf{Z}} ZL: 维度 n × h n \times h n×h

      • ∂ L ∂ A \frac{\partial L}{\partial \mathbf{A}} AL: 维度 n × h n \times h n×h

      • σ ′ ( Z ) \sigma'(\mathbf{Z}) σ(Z): 维度 n × h n \times h n×h

      • 隐藏层权重梯度:
        ∂ L ∂ W = X T ∂ L ∂ Z \frac{\partial L}{\partial \mathbf{W}} = \mathbf{X}^T \frac{\partial L}{\partial \mathbf{Z}} WL=XTZL

      • ∂ L ∂ W \frac{\partial L}{\partial \mathbf{W}} WL: 维度 m × h m \times h m×h

      • X T \mathbf{X}^T XT: 维度 m × n m \times n m×n

      • ∂ L ∂ Z \frac{\partial L}{\partial \mathbf{Z}} ZL: 维度 n × h n \times h n×h

      • 隐藏层偏置梯度:
        ∂ L ∂ b = ∑ i = 1 n ∂ L ∂ Z i \frac{\partial L}{\partial \mathbf{b}} = \sum_{i=1}^{n} \frac{\partial L}{\partial \mathbf{Z}_i} bL=i=1nZiL

      • ∂ L ∂ b \frac{\partial L}{\partial \mathbf{b}} bL: 维度 1 × h 1 \times h 1×h

  2. 假设想计算二阶导数。计算图发生了什么?预计计算需要多长时间?
    计算过程
    正向传播:计算损失 𝐿(𝑥)

    反向传播:计算一阶导数 ∇𝐿(𝑥)

    二阶反向传播:对每个一阶导数分量再计算一次反向传播,得到 Hessian 矩阵 𝐻𝐿(𝑥)
    应该是o(n方)的复杂度,时间大大增加

  3. 假设计算图对当前拥有的GPU来说太大了。

    1. 请试着把它划分到多个GPU上。
    2. 与小批量训练相比,有哪些优点和缺点?

划分模型层:
将模型的不同层或部分分配到不同的GPU上。例如,如果有两个GPU,可以将前半部分的层放在GPU 0上,后半部分的层放在GPU 1上。

import torch
import torch.nn as nn

class SplitNN(nn.Module):
    def __init__(self):
        super(SplitNN, self).__init__()
        self.fc1 = nn.Linear(1000, 500).cuda(0)  # First part on GPU 0
        self.fc2 = nn.Linear(500, 10).cuda(1)   # Second part on GPU 1

    def forward(self, x):
        x = x.cuda(0)
        x = torch.relu(self.fc1(x))
        x = x.cuda(1)
        x = self.fc2(x)
        return x

model = SplitNN()

划分数据和计算:
在前向传播和反向传播过程中,数据需要在不同GPU之间传递。可以利用PyTorch的torch.cuda模块来实现。

input_data = torch.randn(32, 1000).cuda(0)  # Input data on GPU 0
output = model(input_data)
loss = torch.nn.functional.mse_loss(output, torch.randn(32, 10).cuda(1))  # Loss computed on GPU 1
loss.backward()

同步计算:
确保各GPU之间的计算同步,可以利用torch.cuda.synchronize()来实现。

python
torch.cuda.synchronize()

3.2 优点和缺点
优点
更大模型的训练:
模型并行可以使得训练更大规模的模型成为可能,因为单个GPU可能无法容纳整个模型的计算图和参数。

充分利用GPU资源:
在拥有多个GPU的环境下,可以充分利用所有GPU的计算能力,从而提高计算效率。

更高效的内存使用:
通过将模型划分到多个GPU上,可以更加高效地利用每个GPU的内存,避免单个GPU因内存不足而导致的计算瓶颈。

缺点
通信开销:
在多个GPU之间传递数据会产生通信开销,特别是在前向传播和反向传播过程中频繁的数据传递,这会影响整体的计算效率。

实现复杂性:
需要对模型进行拆分和调整,这增加了实现和维护的复杂性。需要特别注意不同GPU之间的数据同步和传递。

负载不均衡:
如果模型的不同部分计算量差异较大,可能会导致GPU负载不均衡,从而无法充分利用所有GPU的计算能力。

与小批量训练比较
小批量训练的优点
减少内存占用:
小批量训练可以减少每次训练过程中所需的内存,从而能够在单个GPU上训练更大的模型。

更稳定的梯度估计:
小批量训练通过累积多个样本的梯度,可以得到更稳定和准确的梯度估计,从而有助于训练过程的收敛。

实现简单:
实现和维护小批量训练相对简单,不需要在多个GPU之间进行复杂的数据传递和同步。

小批量训练的缺点
训练速度较慢:
与模型并行相比,小批量训练在单个GPU上的训练速度可能较慢,特别是在数据量较大时。

无法训练超大模型:
对于超大规模的模型,即使使用小批量训练也可能无法在单个GPU上进行训练。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值