news 2026/10/10 12:16:24

梯度下降与反向传播算法:NYU-DLSP20 第二周课程笔记的数学原理与 PyTorch 实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
梯度下降与反向传播算法:NYU-DLSP20 第二周课程笔记的数学原理与 PyTorch 实现
  • 示例工程

【免费下载链接】NYU-DLSP20

NYU Deep Learning Spring 2020

项目地址:https://gitcode.com/gh_mirrors/pyt/pytorch-Deep-Learning
点击查看免费下载

本文基于 NYU-DLSP20(NYU Deep Learning Spring 2020)课程第二周第一节讲义(意大利语版,主讲人 Yann LeCun)整理撰写。文章以参数化模型、损失函数、梯度下降、反向传播的数学推导为主线,并结合本仓库的 PyTorch 实践代码与优化器实现,帮助读者建立从「线性层 + 非线性激活」到「自动求导」的完整认知,最终能够在 PyTorch 中独立搭建可训练的多层神经网络并理解其梯度更新过程。

目录

  • 参数化模型(Parametrised Models)
  • 计算图的框图记法(Block Diagram Notations)
  • 损失函数(Loss Functions)
  • 梯度下降(Gradient Descent)
  • 随机梯度下降的优势(Advantages of SGD)
  • 传统神经网络的结构
  • 通过非线性函数的反向传播
  • 通过加权求和的反向传播
  • PyTorch 实现神经网络
  • 广义反向传播:通过功能模块与雅可比矩阵
  • 多级图(Multi-Stage Graph)中的反向传播

参数化模型(Parametrised Models)

课程首先引入参数化模型的概念。所谓参数化模型,本质上就是一组依赖于**输入(input)与可训练参数(trainable parameters)**的函数:

$$ \bar{y} = G(x,w) $$

其中 $x$ 是输入,$w$ 是参数向量,$\bar{y}$ 是模型输出(预测值)。

从课程原义看,输入与参数之间并没有本质区别——两者都只是函数的自变量。唯一的差异在于参数的共享方式:可训练参数在全部训练样本之间共享,而输入则随样本不同而变化。

在大多数深度学习框架(如 PyTorch)中,参数是**隐式(implicit)**的:调用模型函数时并不显式传入参数,参数被「保存」在函数对象内部——这正是面向对象(object-oriented)建模方式的体现。

在监督学习范式下,模型输出 $\bar{y}$ 会进入损失函数(代价函数)$C(y, \bar{y})$,与真实输出 $y$ 进行比较。参数化模型的计算图如下图所示:

图 1:参数化模型的计算图表示(来源:docs/it/week02/02-1.md)

参数化函数的经典例子

  • 线性模型(Linear Model):输入向量各分量的加权求和:

$$ \bar{y} = \sum_i w_i x_i, \quad C(y,\bar{y}) = \Vert y - \bar{y}\Vert^2 $$

  • 最近邻(Nearest Neighbour):给定输入向量 $\mathbf{x}$ 与权重矩阵 $\mathbf{W}$(矩阵的每一行由 $k$ 索引),输出是距离输入 $\mathbf{x}$ 最近的矩阵行所对应的 $k$ 值:

$$ \bar{y} = \underset{k}{\arg\min} \Vert x - w_{k,.} \Vert^2 $$

值得注意的是,参数化模型也可以包含非常复杂的函数——线性模型只是最简单的一种特例。

从源码看参数化模型的对象化封装

在 PyTorch 中,参数被封装在nn.Module子类的对象内部,而非每次调用时显式传入。本仓库的螺旋分类实践 04-spiral_classification.ipynb 正是这一思想的直接体现:

# nn package to create our linear model # each Linear module has a weight and bias model = nn.Sequential( nn.Linear(D, H), nn.Linear(H, C) )

nn.Linear内部持有权重矩阵与偏置向量,调用model(X)时并不需要把参数作为函数参数传入——参数是「保存」在模块内部的。


计算图的框图记法

课程给出了一套用于绘制计算图(computation graph)的框图符号,这些符号贯穿后续所有章节:

变量(Variables)

  • 输入变量(observed input):表示系统观测到的输入,例如训练数据 $x$;
  • 计算变量(computed variable):表示由某个确定性函数计算得到的变量。

确定性函数(Deterministic Functions)

  • 接受多个输入,可产生多个输出;
  • 含有隐式参数变量 $w$;
  • 圆角一侧表示「容易计算」的方向:在图中,由 $x$ 计算 $\bar{y}$ 比反向更容易(这正是前向传播的方向)。

标量值函数(Scalar-Valued Function)

  • 用于表示代价(成本)函数;
  • 隐含标量输出;
  • 接受多个输入,输出单个值(通常为输入之间的距离度量)。

损失函数

损失函数(loss function)是训练过程中需要最小化的目标函数。课程将其分为两类:

1. 单样本损失(Per Sample Loss)

$$ L(x,y,w) = C(y, G(x,w)) $$

即对单个样本 $(x, y)$,损失等于代价函数在模型输出上的取值。

2. 平均损失(Average Loss)

给定一组样本集合:

$$S = \lbrace (x[p],y[p]) \mid p \in \lbrace 0, \cdots, P-1 \rbrace \rbrace$$

集合 $S$ 上的平均损失为:

$$ L(S,w) = \frac{1}{P} \sum_{(x,y) \in S} L(x,y,w) $$

图 2:带平均损失模型的计算图(来源:docs/it/week02/02-1.md)

在标准监督学习范式下,单样本损失就是代价函数的输出。机器学习本质上是在做函数优化(通常是求最小值);它也可能涉及在两个函数之间寻找纳什均衡(Nash Equilibrium),例如 GAN(生成对抗网络)。这些优化通常通过基于梯度的方法完成,但不一定是梯度下降本身。


梯度下降

基于梯度的方法(Gradient-Based Method)是一类假设可以方便计算函数梯度、从而寻找函数极小值的方法。其前提是目标函数连续且几乎处处可微(并不要求处处可微)。

直觉描述

课程给出一个非常直观的比喻:想象你身处浓雾深夜的山中,想要下山回到村庄,但视线受限——你只能在紧邻的周围寻找最陡的下降方向,然后朝那个方向迈出一步。梯度下降正是「每一步都沿着当前点的负梯度方向前进」的迭代过程。

两种更新规则

  • 全量(batch)梯度下降更新规则:

$$ w \leftarrow w - \eta \frac{\partial L(S,w)}{\partial w} $$

  • 随机梯度下降(SGD, Stochastic Gradient Descent):先随机挑选一个样本 $p \in \lbrace 0, \cdots, P-1 \rbrace$,再更新:

$$ w \leftarrow w - \eta \frac{\partial L(x[p], y[p],w)}{\partial w} $$

其中 $w$ 表示待优化的参数,$\eta$ 是学习率(步长)。

学习率的深层含义

课程特别指出:这里的 $\eta$ 是常数,但在更复杂的算法中,它可以是矩阵:

  • 若 $\eta$ 是半正定矩阵,我们仍然会「向下走」,但不一定沿着最陡下降方向;
  • 事实上,最陡下降方向未必是我们想要移动的方向——这是二阶优化方法(如牛顿法及其变体)的核心动机之一。

不可微函数与零阶方法

如果函数不可微——例如存在「洞」、呈阶梯状或平坦区域,梯度不提供任何信息——则需要求助于其他方法,称为零阶方法(0-th Order Methods)或无梯度方法(Gradient-Free Methods)。深度学习几乎完全依赖基于梯度的方法。

强化学习中的梯度估计

强化学习(RL)则涉及梯度估计(Gradient Estimation),因为目标函数通常没有显式的梯度形式。课程以「机器人学骑自行车」为例:机器人会不时摔倒,目标函数衡量自行车保持不倒的时间——但这个目标函数没有梯度。机器人只能不断尝试不同的行为。

关键区别在于:

  • 监督学习中,代价函数 $C$ 通常是可微的,且网络基于梯度训练;
  • 强化学习中,代价函数 $C$通常不可微,甚至是完全未知的——它像黑盒一样,输入进去、返回一个输出。这使得 RL 效率很低,尤其在参数向量维数很高时(解空间巨大,难以找到移动方向)。

课程进一步介绍 RL 中非常流行的Actor-Critic(演员-评论家)方法:评论家(critic)本质上是一个已知且可训练的模块 $C$,我们可以训练这个可微的 $C$ 模块去近似代价/奖励函数(奖励是负代价,更像惩罚)。这就把代价函数变得可微(至少可用可微函数近似),从而可以对它做反向传播。

仓库中的优化器实现佐证

本仓库 extra/utils/optim.py 定义了一个基于torch.optim.Optimizer的基类Optim,其step()方法遍历所有参数组:

for group in self.param_groups: for p in group['params']: if p.grad is None: continue self.my_step(p, self.state[p], group)

子类只需实现my_step()即可定义自己的更新规则。例如 extra/optimization.ipynb 中手写的 SGD:

class SGDOptimizer(Optim): def __init__(self, params, lr): defaults = dict(lr=lr) super(SGDOptimizer, self).__init__(params, defaults) def my_step(self, p, state, group): lr = group['lr'] d_p = p.grad.data p.data.add_(-group['lr'], d_p)

这里的p.data.add_(-lr, d_p)正是课程公式 $w \leftarrow w - \eta \frac{\partial L}{\partial w}$ 的直接翻译。


随机梯度下降的优势

实际训练中,我们用随机梯度来计算目标函数关于参数的梯度:不再计算所有样本的平均全量梯度,而是只取一个样本,计算其损失 $L$ 与梯度,然后沿负梯度方向前进一步:

$$ w \leftarrow w - \eta \frac{\partial L(x[p], y[p],w)}{\partial w} $$

即:$w$ 更新为 $w$ 减去「步长 × 该样本损失关于参数的梯度」。

噪声轨迹与平均行为

如果对单个样本做更新,会得到非常嘈杂的轨迹,如下图所示:损失并不是直接「下山」,而是随机的——每个样本都会把损失拉向不同方向,只是平均值最终把我们带向平均损失的极小值。

图 3:单样本更新下的随机梯度下降轨迹(来源:docs/it/week02/02-1.md)

课程强调:虽然看起来低效,但在机器学习语境下,当样本之间存在冗余(redundancy)时,SGD 比全量批量梯度下降快得多。

实际中的批处理(Batching)

在实践中,我们并不会真的在单个样本上做 SGD,而是使用小批量(mini-batch):对一批随机样本的梯度求平均,然后沿负梯度方向前进一步。这样做的唯一理由是更高效地利用现有硬件(GPU、多核 CPU)——批量计算更容易并行化,批处理是最简单的并行化方式。

仓库中的完整训练循环

04-spiral_classification.ipynb 给出了一个标准训练循环,完整体现了「前向 → 计算损失 → 清零梯度 → 反向传播 → 更新参数」的流程:

learning_rate = 1e-3 lambda_l2 = 1e-5 model = nn.Sequential( nn.Linear(D, H), nn.Linear(H, C) ) model.to(device) criterion = torch.nn.CrossEntropyLoss() # we use the optim package to apply # stochastic gradient descent for our parameter updates optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate, weight_decay=lambda_l2) # built-in L2 # Training for t in range(1000): # Feed forward to get the logits y_pred = model(X) # Compute the loss and accuracy loss = criterion(y_pred, y) score, predicted = torch.max(y_pred, 1) acc = (y == predicted).sum().float() / len(y) # zero the gradients before running the backward pass optimizer.zero_grad() # Backward pass to compute the gradient of loss w.r.t our learnable params loss.backward() # Update params optimizer.step()

这里可以看到 PyTorch 的批处理更新是隐式的:torch.optim.SGD默认按参数组整体更新(等价于在全量/批量梯度上更新),weight_decay提供了内置的 L2 正则化。而loss.backward()正是课程所讲的自动反向传播——用户无需手写任何梯度公式。


传统神经网络的结构

传统神经网络本质上是线性运算层与逐点非线性运算层交替堆叠:

  • 线性运算:概念上就是矩阵-向量乘法——输入向量乘以权重矩阵;
  • 非线性运算:将加权和向量的每个分量通过一个简单的非线性函数(如 $\texttt{ReLU}(\cdot)$、$\tanh(\cdot)$ 等)。

图 4:传统神经网络结构(来源:docs/it/week02/02-1.md)

关于「几层网络」的约定

图 4 所示是一个2 层网络,因为计数的是「线性 + 非线性」的成对组合(pairs)。有些人称之为 3 层网络,是因为他们在数变量(层间向量)。

课程特别强调一个关键观察:如果中间没有非线性,那么整个网络可以合并为单层(使用不同的权重)——因为两个线性函数的复合仍然是线性函数。这解释了为什么现代神经网络必须依赖非线性激活函数。

线性块与非线性块的内部结构

下图展示了网络的线性与非线性功能块如何堆叠:

图 5:线性与非线性块的内部结构(来源:docs/it/week02/02-1.md)

在图中,$s[i]$ 是第 $i$ 个单元的加权和:

$$ s[i]=\sum_{j \in UP(i)}w[i,j]\cdot z[j] $$

其中 $UP(i)$ 表示 $i$ 的前驱节点集合,$z[j]$ 是上一层第 $j$ 个输出。而单元输出:

$$ z[i]=f(s[i]) $$

其中 $f$ 是非线性函数。


通过非线性函数的反向传播

反向传播的第一种方式是穿过一个非线性函数。我们把网络中的某个特定非线性函数 $h$ 单独拿出来,其余部分视为「黑盒」。

图 6:通过非线性函数进行反向传播(来源:docs/it/week02/02-1.md)

链式法则(Chain Rule)

使用复合函数求导的链式法则计算梯度:

$$ g(h(s))' = g'(h(s))\cdot h'(s) $$

其中 $h'(s)$ 是 $z$ 关于 $s$ 的导数,即 $\frac{\mathrm{d}z}{\mathrm{d}s}$。把导数之间的连接写清楚,上式可改写为:

$$ \frac{\mathrm{d}C}{\mathrm{d}s} = \frac{\mathrm{d}C}{\mathrm{d}z}\cdot \frac{\mathrm{d}z}{\mathrm{d}s} = \frac{\mathrm{d}C}{\mathrm{d}z}\cdot h'(s) $$

因此,如果网络中存在一连串这样的函数,我们就可以逐个相乘所有 $h$ 函数的导数,一路链式乘法回传到最底层——这就是反向传播的朴素形态。

扰动视角的理解

用「扰动」来思考更直观:

  • 将 $s$ 扰动 $\mathrm{d}s$,$z$ 将被扰动:

$$\mathrm{d}z = \mathrm{d}s \cdot h'(s)$$

  • 这进而扰动 $C$:

$$ \mathrm{d}C = \mathrm{d}z\cdot\frac{\mathrm{d}C}{\mathrm{d}z} = \mathrm{d}s\cdot h'(s)\cdot\frac{\mathrm{d}C}{\mathrm{d}z} $$

再次得到与链式法则相同的公式。扰动语言把抽象的求导变成了「误差如何逐层传播」的直觉。


通过加权求和的反向传播

对于线性模块,反向传播发生在加权求和上。这里我们把整个网络视为黑盒,只关注从变量 $z$ 连向一组变量 $s$ 的 3 条连接:

图 7:通过加权求和进行反向传播(来源:docs/it/week02/02-1.md)

这次扰动是加权和:$Z$ 影响多个变量。将 $z$ 扰动 $\mathrm{d}z$,$s[0]$、$s[1]$、$s[2]$ 分别被扰动:

$$ \mathrm{d}s[0]=w[0]\cdot \mathrm{d}z $$

$$ \mathrm{d}s[1]=w[1]\cdot \mathrm{d}z $$

$$ \mathrm{d}s[2]=w[2]\cdot\mathrm{d}z $$

这会通过如下方式扰动 $C$:

$$ \mathrm{d}C = \mathrm{d}s[0]\cdot \frac{\mathrm{d}C}{\mathrm{d}s[0]}+\mathrm{d}s[1]\cdot \frac{\mathrm{d}C}{\mathrm{d}s[1]}+\mathrm{d}s[2]\cdot\frac{\mathrm{d}C}{\mathrm{d}s[2]} $$

于是 $C$ 的变化是这 3 个变化的总和:

$$ \frac{\mathrm{d}C}{\mathrm{d}z} = \frac{\mathrm{d}C}{\mathrm{d}s[0]}\cdot w[0]+\frac{\mathrm{d}C}{\mathrm{d}s[1]}\cdot w[1]+\frac{\mathrm{d}C}{\mathrm{d}s[2]}\cdot w[2] $$

这就是线性层反向传播的本质:上游梯度乘以对应权重后求和,即「梯度沿边的权重回传」。它对应了 PyTorch 中nn.Linear在反向传播时,将梯度按权重矩阵转置回传的操作。


PyTorch 实现神经网络

传统神经网络的框图

  • 线性块:$s_{k+1}=w_k z_k$
  • 非线性块:$z_k=h(s_k)$

![传统神经网络的框图(线性块与非线性块交替)](https://raw.gitcode.com/gh_mirrors/pyt/pytorch-Deep-Learning/raw/3049c83260ba05700e2ab9b7ed13cdbe5ddba0fd/docs/images/week02/02-1/Figure 7.png?utm_source=gitcode_repo_files)

其中 $w_k$ 是矩阵,$z_k$ 是向量,$h$ 是对每个分量应用标量函数 $h$。这是一个3 层网络(按线性-非线性成对计数为 3 对),不过大多数现代神经网络并不具有如此清晰的线性/非线性分界,结构要复杂得多。

面向对象的 PyTorch 实现

课程给出了用 PyTorch 以面向对象方式实现神经网络的完整代码:

import torch from torch import nn image = torch.randn(3, 10, 20) d0 = image.nelement() class mynet(nn.Module): def __init__(self, d0, d1, d2, d3): super().__init__() self.m0 = nn.Linear(d0, d1) self.m1 = nn.Linear(d1, d2) self.m2 = nn.Linear(d2, d3) def forward(self, x): z0 = x.view(-1) # appiattimento del vettore di input (flatten input tensor) s1 = self.m0(z0) z1 = torch.relu(s1) s2 = self.m1(z1) z2 = torch.relu(s2) s3 = self.m2(z2) return s3 model = mynet(d0, 60, 40, 10) out = model(image)
代码要点解析
  • 类定义与参数持有:先为网络定义类,并在构造函数中使用预定义的nn.Linear类初始化线性层。线性层必须是独立对象,因为每个层都包含自己的参数向量;nn.Linear还会隐式添加偏置向量(bias)。
  • 前向函数:定义forward函数描述如何计算输出,使用torch.relu作为非线性激活。不需要为 relu 单独初始化对象,因为它没有参数。
  • 自动求导:我们不需要自己计算梯度——只要给出forward函数,PyTorch 就知道如何反向传播并计算梯度(这正是 03-autograd_tutorial.ipynb 中详细介绍的 autograd 机制)。
维度流转

以本代码为例:输入image形状为(3, 10, 20),nelement()得到 $d0 = 3\times10\times20 = 600$。forward中先x.view(-1)展平为 600 维向量,随后依次经过m0(600→60)、ReLU、m1(60→40)、ReLU、m2(40→10),最终输出 10 维的 logits(对应 10 个类别)。


广义反向传播:通过功能模块与雅可比矩阵

前面两节是反向传播的特例,课程进一步给出更一般化的形式——通过任意「功能模块(functional module)」的反向传播:

图 8:通过功能模块进行反向传播(来源:docs/it/week02/02-1.md)

向量函数的链式法则

设模块输入为 $z_f$(维度 $[d_f\times 1]$),输出为 $z_g$(维度 $[d_g\times 1]$):

$$ \frac{\partial c}{\partial z_f}=\frac{\partial c}{\partial z_g}\cdot \frac{\partial z_g}{\partial z_f} $$

对应维度关系:

$$ [1\times d_f] = [1\times d_g]\times[d_g\times d_f] $$

这是用链式法则计算 $\frac{\partial c}{\partial z_f}$ 的基本公式。课程特别提醒一个约定:标量函数关于向量的梯度,是与被求导向量同维的向量;为保持记号一致,这里将其写作行向量而非列向量。

雅可比矩阵(Jacobian Matrix)

矩阵 $\frac{\partial z_g}{\partial z_f}$ 的每个元素为:

$$ \left(\frac{\partial z_g}{\partial z_f}\right)_{ij}=\frac{\partial (z_g)_i}{\partial (z_f)_j} $$

也就是说,第 $ij$ 个元素等于输出向量第 $i$ 个分量对输入向量第 $j$ 个分量的偏导。给定损失关于 $z_g$ 的梯度,我们需要这个雅可比矩阵来计算损失关于 $z_f$ 的梯度。

级联(cascade)的关键结论:如果有一串模块,我们只需逐个相乘所有模块的雅可比矩阵,就能得到损失关于所有内部变量的梯度。

从源码看雅可比思想的落地

PyTorch 的 autograd 引擎正是以「反向图」的方式逐节点累积梯度(链式相乘雅可比),03-autograd_tutorial.ipynb 对此有专门讲解;而 extra/b-custom_grads.ipynb 则演示了如何自定义梯度函数——即用户手动提供模块的「雅可比乘积」来参与反向传播。


多级图中的反向传播

考虑神经网络中堆叠的多个模块(多级图,multi-stage graph):

图 9:多级图中的反向传播(来源:docs/it/week02/02-1.md)

两类梯度

反向传播算法需要两组梯度:

  1. 关于**状态(states)**的梯度——网络中每个模块;
  2. 关于**权重(weights)**的梯度——特定模块内的所有参数。

因此每个模块关联两个雅可比矩阵,都可以用链式法则进行反向传播。

向量函数的链式法则

对第 $k$ 个模块 $z_{k+1} = f_k(z_k, w_k)$:

关于状态的梯度:

$$ \frac{\partial c}{\partial z_k}=\frac{\partial c}{\partial z_{k+1}}\cdot \frac{\partial z_{k+1}}{\partial z_k}=\frac{\partial c}{\partial z_{k+1}}\cdot \frac{\partial f_k(z_k,w_k)}{\partial z_k} $$

关于权重的梯度:

$$ \frac{\partial c}{\partial w_k}=\frac{\partial c}{\partial z_{k+1}}\cdot \frac{\partial z_{k+1}}{\partial w_k}=\frac{\partial c}{\partial z_{k+1}}\cdot \frac{\partial f_k(z_k,w_k)}{\partial w_k} $$

每个模块的两个雅可比矩阵:

  • 一个关于 $z[k]$(状态);
  • 一个关于 $w[k]$(权重)。

与训练循环的对应

这条公式链与 PyTorch 的训练流程一一对应:

  • loss.backward()执行从损失开始、沿多级图逐模块回传的链式求导,计算出每个nn.Linear参数(权重与偏置)的.grad;
  • optimizer.step()则用这些梯度执行更新规则。

以本仓库 extra/optimization.ipynb 中的带动量 SGD 为例,可以看到「梯度累积状态 + 更新参数」的实现:

class SGDMomentumOptimizer(Optim): def __init__(self, params, lr, momentum): defaults = dict(lr=lr, momentum=momentum) super(SGDMomentumOptimizer, self).__init__(params, defaults) def my_step(self, p, state, group): lr = group['lr'] momentum = group['momentum'] d_p = p.grad.data if 'v' not in state: state['v'] = torch.clone(d_p).detach() else: state['v'] = d_p + momentum * state['v'] d_p = state['v'] p.data.add_(-group['lr'] * d_p)

其中速度项v的更新v = d_p + momentum * v是带动量 SGD 的标准形式(动量参数momentum通常取 0.9 左右),而p.data.add_(-lr * d_p)仍是课程更新公式的落地。


总结与延伸阅读

  • 核心公式链:参数化模型 $\bar{y}=G(x,w)$ → 损失 $L(S,w)=\frac{1}{P}\sum L(x,y,w)$ → 更新规则 $w \leftarrow w - \eta \frac{\partial L}{\partial w}$(SGD 取单个样本或小批量)。
  • 反向传播本质:沿计算图反向应用链式法则——非线性块回传乘 $h'(s)$,线性块(加权和)回传按权重加权求和,一般模块则用雅可比矩阵连乘。
  • 工程落地:PyTorch 中只需定义nn.Module子类与forward,autograd 自动完成全部梯度计算;训练循环 =zero_grad()→backward()→step()。

与本主题直接相关的仓库资源:

  • docs/it/week02/02-1.md:本文依据的意大利语课程笔记(英文原版);
  • 04-spiral_classification.ipynb:含 SGD 优化器与完整训练循环的螺旋分类实践;
  • extra/utils/optim.py:Optim优化器基类;
  • extra/optimization.ipynb:手写 SGD / 带动量 SGD / RMSProp / Adam 优化器对比;
  • 03-autograd_tutorial.ipynb:PyTorch autograd 自动求导教程;
  • extra/b-custom_grads.ipynb:自定义梯度(雅可比乘积)的实现示例。
  • 示例工程

【免费下载链接】NYU-DLSP20

NYU Deep Learning Spring 2020

项目地址:https://gitcode.com/gh_mirrors/pyt/pytorch-Deep-Learning
点击查看免费下载
上一篇:如何为深度学习项目做贡献?Awesome Deep Learning Resources 社区终极指南
下一篇:SQLAlchemy 版本计数器(Version Counter)配置完全指南:从整数计数到服务端版本控制

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/10 12:13:37

IPEmotion 曲线平滑计算:精准去除测试数据中的突起噪声

在实际车辆测试或其它实验室测试中,可能存在外界干扰,例如:工作环境温度发生突变,从而引起设备或系统内部元件参数发生了短暂的改变;外部使用了大功率设备产生了强磁场,从而干扰了测试系统等。特别当采样频…

作者头像 李华
网站建设 2026/10/10 12:12:07

Codeforces入门需要多少英语词汇

Codeforces入门阶段(700-1000分),四年级零基础孩子只需要掌握100个以内的核心高频词汇,就能轻松读懂所有入门题面,完全不用额外背海量英语单词,和校内四年级英语学习进度高度适配。 🔢 核心词汇…

作者头像 李华
网站建设 2026/10/10 12:09:31

Python基础练习:注释与标识符的规范与避坑指南

我见过太多初学者学Python,第一个星期就开始啃列表、字典、函数,结果一写项目就乱套:变量名叫a、b、c,代码里一句注释都没有,过两周自己都看不懂自己写的什么。最后跑回来问我怎么回事,其实根子不在"知…

作者头像 李华
网站建设 2026/10/10 12:06:36

从x²=2到伽罗瓦群:域扩张、极小多项式与正规扩张完全梳理

如果你正在学抽象代数,或者备战考研,一定绕不开一个问题:方程 x2 在有理数世界里无解。教材上会写“引入 Q(√2)”,但很少有人把这一步背后的逻辑讲透。有理数域上的扩域,就是把 Q 不包含的数,通过某种受控…

作者头像 李华
网站建设 2026/10/10 12:04:57

长沙艺都装饰工程有限公司口碑怎么样,客户评价如何

在长沙这座城市,家从来不只是居所,更是生活的容器。近年来,家装行业经历了从粗放扩张到精耕细作的深刻变迁,业主对装修的要求,也从能住升级为住得舒心、装得放心。在这样的大背景下,长沙艺都装饰工程有限公…

作者头像 李华
网站建设 2026/10/10 12:03:37

Playwright定位器详解:从基础到自动等待、iframe与调试实战

1. 为什么Playwright的定位方式和以前不一样我记得第一次在项目里用Playwright跑通一个测试用例时,最大的感受不是执行速度快,而是locator这套API给我带来的思维冲击。如果之前主力工具是Selenium,你大概率习惯了find_element_by_id、find_el…

作者头像 李华