CS224N Assignment 3

Bahdanau 注意力机制的思想就是在 Decoder 的每一个时刻,用当前 token 和 Encoder 的每一个 token 计算注意力分数,判断 Encoder 的哪一个 token 和当前 token 关系最大。

在早期的 seq2seq 结构中只包含最简单的 Encoder 和 Decoder 两部分。训练时如果让 Decoder 完全靠自己前一步的预测输出当下一步输入,容易出错 → 错误不断累积,训练非常难收敛。为了解决这个问题,Teacher-forcing 的解决办法是直接把答案告诉模型。

RNN

在 CS224N 的课程中学习了 RNN 的基本知识,为了深入了解背后的机制和代码实现,我让 GPT 设计了一个 RNN 相关的深度学习任务,通过 PyTorch 手搓一个 RNN 网络。

使用 RNN 实现英文字母序列预测任务(Character-Level Sequence Prediction)

CS224N Lecture 2: Word Vectors and Language Models

θjnew:=θjoldηθJ(θ) \theta^{new}_j := \theta^{old}_j - \eta \, \nabla_{\theta} J(\theta)

传统梯度下降算法的缺点在于:

  1. 计算成本大:$J(\theta) = \frac{1}{N} \sum_{i=1}^{N} L(x_i, y_i; \theta)$,这意味着每一次计算梯度都需要全部样本参与计算,开销很大
  2. 容易陷入局部最小值

仅仅在全部数据集中选取一个很小的子集,例如16或32个数据,用这些数据充当完整的数据集来计算损失函数和优化梯度

CS224N Lecture 3: Backpropagation, Neural Network

x(Wx+b)=W \frac{\partial}{\partial{\textbf{x}}}(\textbf{Wx+b})=\textbf{W} b(Wx+b)=I \frac{\partial}{\partial{\textbf{b}}}(\textbf{Wx+b})=\textbf{I} u(uTh)=hT \frac{\partial}{\partial{\textbf{u}}}(\textbf{u}^Th)=\textbf{h}^T \[ \textbf{h}=f(\textbf{z}) \\ h_i=f(z_i) 且 \textbf{h} ,\textbf{z} \in R^n \]

可以得到:

(hz)ij=hizj=f(zi)zj={f(zi),  if  i=j0,  if  otherwisehz=(f(z1)00f(zn))=diag(f(z)) (\frac{\partial{h}}{\partial{z}})_{ij}=\frac{\partial{h_i}}{\partial{z_j}}=\frac{\partial{f(z_i)}}{\partial{z_j}}= \begin{cases} f'(z_i),\;if\;i=j\\ 0,\;if\;otherwise \end{cases} \\ \frac{\partial h}{\partial z} = \begin{pmatrix} f'(z_1) & & 0 \\ & \ddots & \\ 0 & & f'(z_n) \end{pmatrix} = \operatorname{diag}(f'(z))

Python Tricks

场景:插件系统中,需要给插件的函数绑定on_message,当收到消息时候调用函数。

一切都是绑定方法未绑定方法的处理

方案1:

  1. @on_message装饰器给需要的插件添加metadata
  2. __init__中,遍历全部成员函数,如果有metadata,就从self上getattr下来这个绑定方法
  3. 在加载插件时候实例化插件类

方案2:

Python 异步编程

方法 适用场景 是否要求协程中运行 Python 3.10+ 行为
asyncio.get_running_loop() 在协程/任务中获取当前运行的事件循环 ✅ 必须在事件循环中调用 ✅ 推荐 抛错如果没有运行的 loop
asyncio.get_event_loop() 早期通用方式 ❌ 可在同步代码中用 ⚠️ 不推荐新项目用 自动创建事件循环(旧行为)

官方推荐(Python 3.10+)

估算模型需要的显存

到底需要多少算力才能部署一个模型,这是一个非常常见的问题。我们就从训练和推理两个场景,分析一下如何估计模型所需要的显存。

训练显存大致分为以下四部分:

  1. 模型权重:取决于存储的精度,常见的 BF16 和 FP16 占用大小为 2B
  2. 梯度:反向传播计算的梯度,和权重一样常见情况下占用 2B
  3. 优化器状态:常见的 Adam 会为每个参数都保存它的 Momentum、Variance 和 Master weights,精度为 FP32 所以总计 12B
  4. 中间激活值:简单来说就是为了计算反向传播的梯度,需要把前向计算的中间值存储起来,具体计算见下文。

因此使用 AdamW 优化器 + 混合精度训练的经验公式为: