NYU-DLSP20 激活函数与损失函数指南:PyTorch 中从 ReLU 到 Softmax 的完整实践(第 11 周第 1 讲) 示例工程【免费下载链接】NYU-DLSP20NYU Deep Learning Spring 2020项目地址https://gitcode.com/gh_mirrors/pyt/pytorch-Deep-Learning点击查看免费下载本讲第 11 周第 1 部分由 Yann LeCun 主讲系统性梳理了 PyTorch 中最重要的激活函数与损失函数及其在torch.nn中的实现。文章以 ReLU 家族为主线对比带折点kink的激活与光滑激活在深层网络中的利弊随后详解回归与分类任务的损失函数选择MSE、L1、SmoothL1、NLL、CrossEntropy 等并延伸至类别不平衡处理与 softmax 温度退火等实战技巧。读完本文你将能够为具体任务挑选合适的激活与损失组合并理解其背后的梯度动力学原理。文中代码均可在仓库的 04-spiral_classification.ipynb、10-autoencoder.ipynb 等笔记本中复现。为什么激活函数决定网络的可学习性激活函数是神经网络中位于线性变换之后、提供非线性能力的逐元素映射。LeCun 在本讲开篇就强调激活函数的选择不仅影响表达能力更直接决定梯度能否有效回传。一个关键结论是对深层网络而言带单个折点的分段线性函数如 ReLU通常优于处处光滑的 S 形函数因为后者在大输入值处的梯度趋近于零会引发饱和梯度问题。本节内容与仓库第 2 周、第 3 周的铺垫一脉相承在 docs/it/week02/02-1.md 中已指出传统神经网络就是线性运算 逐元素非线性如 ReLU、tanh的交替堆叠而在 docs/it/week03/03-1.md 中通过可视化看到ReLU 会把负值折叠为零从而帮助网络逐步把数据变成线性可分——这正是折点发挥作用的直观体现。PyTorch 激活函数全家桶下面按原文档顺序逐一给出数学定义、torch.nn中的模块名、关键参数与使用注意事项。所有模块都可通过torch.nn.Module直接实例化并接入nn.Sequential。ReLU 及其带泄漏家族ReLU ——nn.ReLU()$$\text{ReLU}(x) (x)^{} \max(0,x)$$ReLU 是最基础的分段线性激活负半轴全部置零正半轴恒等。它的优势是计算简单、梯度在正半轴恒为 1且具有尺度不变性见下文折点与尺度讨论。它也是仓库中最常见的激活例如 04-spiral_classification.ipynb 中两层网络用nn.ReLU()夹在两层nn.Linear之间即实现了螺旋分类精度可达 95%06-convnet.ipynb 的卷积网络、11-VAE.ipynb 的编码器也都使用 ReLU。RReLU ——nn.RReLU()$$\text{RReLU}(x) \begin{cases} x, \text{if } x \geq 0\ ax, \text{otherwise} \end{cases}$$随机 ReLU在训练阶段负半轴的斜率 $a$ 是一个在给定区间内随机采样的变量测试阶段则固定。PyTorch 默认在(1/8, 1/3)内均匀采样对应参数lower、upper。随机性可看作一种隐式的正则化。LeakyReLU ——nn.LeakyReLU()$$\text{LeakyReLU}(x) \begin{cases} x, \text{if } x \geq 0\ a_\text{negative slope},x, \text{otherwise} \end{cases}$$这里 $a$PyTorch 参数名为negative_slope默认0.01是固定值。它的存在正是为了对抗dying ReLU问题当神经元陷入负区域时普通 ReLU 输出恒为 0、梯度恒为 0神经元死亡且再也无法更新而 LeakyReLU 在负半轴保留了非零梯度使得网络仍能反向传播学到东西。原文档特别指出LeakyReLU 对瘦网络skinny network几乎是必需的——因为普通 ReLU 在这类网络中几乎无法让梯度流动起来。PReLU ——nn.PReLU()$$\text{PReLU}(x) \begin{cases} x, \text{if } x \geq 0\ ax, \text{otherwise} \end{cases}$$PReLU 与 LeakyReLU 的唯一区别在于 $a$ 是一个可学习参数默认初始化0.25可设置num_parameters决定是逐通道共享还是每单元独立。LeCun 在问答环节对 PReLU 做了深入探讨见下文课堂问答。光滑激活Softplus、ELU 家族与 GELUSoftplus ——nn.Softplus()$$\text{Softplus}(x) \frac{1}{\beta} \log(1 \exp(\beta x))$$Softplus 是 ReLU 的光滑近似默认 $\beta1$输出恒为正因此常用于约束某个输出必须为正。当 $\beta$ 越来越大时Softplus 越来越接近 ReLU。ELU ——nn.ELU()$$\text{ELU}(x) \max(0,x) \min(0, \alpha(\exp(x)-1))$$ELU 在负半轴是指数形式默认 $\alpha1$因此可以输出负值使网络的平均输出更接近零从而可能加速收敛。其变体 CELU、SELU 本质上只是不同的参数化CELU ——nn.CELU()$$\text{CELU}(x) \max(0,x) \min(0, \alpha(\exp(x/\alpha)-1))$$SELU ——nn.SELU()$$\text{SELU}(x) \text{scale} \cdot \big(\max(0,x) \min(0, \alpha(\exp(x)-1))\big)$$SELU 在 ELU 基础上乘上scalePyTorch 默认scale 1.0507、$\alpha 1.6733$配合特定初始化可实现自归一化。GELU ——nn.GELU()$$\text{GELU}(x) x \cdot \Phi(x)$$其中 $\Phi(x)$ 是标准正态分布的累积分布函数CDF。GELU 以概率方式门控输入在 Transformer 等现代架构中被广泛使用。饱和型激活与裁剪族ReLU6 ——nn.ReLU6()$$\text{ReLU6}(x) \min(\max(0,x),6)$$即饱和值取 6 的 ReLU。原文档坦言选择 6 并没有特别理由纯粹是经验值该函数最初见于 MobileNet 系列并提示可以做得更好——例如使用下面的 Sigmoid。Sigmoid ——nn.Sigmoid()$$\text{Sigmoid}(x) \sigma(x) \frac{1}{1\exp(-x)}$$输出范围 $(0,1)$。问题在于当输入绝对值很大时梯度接近 0即饱和梯度问题saturating gradient problem。若多层堆叠 Sigmoid网络会难以学习且对初始化非常敏感因此深度网络更偏爱带单个折点的激活如 ReLU。这也是本讲的核心论点之一。Tanh ——nn.Tanh()$$\text{Tanh}(x) \frac{\exp(x)-\exp(-x)}{\exp(x)\exp(-x)}$$Tanh 与 Sigmoid 本质相同但中心化到 $(-1,1)$输出近似零均值因此收敛通常更快。原文档提示输入均值接近零时收敛更快这正是 Batch Normalization 等归一化手段的动机。仓库中 10-autoencoder.ipynb 的编码器/解码器、05-regression.ipynb 中 5 条nn.Tanh()网络都采用了 Tanh。Softsign ——nn.Softsign()$$\text{SoftSign}(x) \frac{x}{1|x|}$$与 Sigmoid 类似但更缓慢地逼近渐近线能在一定程度上缓解梯度消失问题。Hardtanh ——nn.Hardtanh()$$\text{HardTanh}(x) \begin{cases} 1, x 1\ -1, x -1\ x, \text{otherwise} \end{cases}$$线性区间 $[-1,1]$ 可通过min_val与max_val调整。当权重被约束在较小的取值范围内时Hardtanh 的表现出乎意料地好常用于权重裁剪类场景。稀疏化与收缩类激活Threshold ——nn.Threshold()$$y \begin{cases} x, x \text{threshold}\ v, \text{otherwise} \end{cases}$$阈值函数不可微无法回传梯度现已很少使用。原文档指出正是这类硬二值神经元在 1960—70 年代阻碍了反向传播的推广。Tanhshrink ——nn.Tanhshrink()$$\text{Tanhshrink}(x) x - \tanh(x)$$很少用作常规激活主要出现在稀疏编码中用于计算隐变量的值。Softshrink ——nn.Softshrink()$$\text{SoftShrinkage}(x) \begin{cases} x - \lambda, x \lambda\ x \lambda, x -\lambda\ 0, \text{otherwise} \end{cases}$$把变量向零收缩一个常数 $\lambda$默认0.5接近零则直接置零。它可看作 $\ell_1$ 准则下梯度步的一种形式也是ISTAIterative Shrinkage-Thresholding Algorithm的组成部分但很少作为标准网络激活使用。它同时与 L1 损失在零点不可导的问题密切相关见下文 SmoothL1 一节。Hardshrink ——nn.Hardshrink()$$\text{HardShrinkage}(x) \begin{cases} x, x \lambda\ x, x -\lambda\ 0, \text{otherwise} \end{cases}$$同样主要服务于稀疏编码场景很少用于常规网络。LogSigmoid ——nn.LogSigmoid()$$\text{LogSigmoid}(x) \log\left(\frac{1}{1\exp(-x)}\right)$$主要是 Sigmoid 的对数形式多用于损失函数构造如 NLL 风格的二分类而非作为普通激活。概率化映射Softmin、Softmax 与 LogSoftmaxSoftmin ——nn.Softmin()$$\text{Softmin}(x_i) \frac{\exp(-x_i)}{\sum_j \exp(-x_j)}$$将任意实数向量变为概率分布对最小值给最大概率。Soft(arg)max ——nn.Softmax()$$\text{Softmax}(x_i) \frac{\exp(x_i)}{\sum_j \exp(x_j)}$$将 logits 变为概率分布分类网络的最后一公里。LogSoft(arg)max ——nn.LogSoftmax()$$\text{LogSoftmax}(x_i) \log\left(\frac{\exp(x_i)}{\sum_j \exp(x_j)}\right)$$对 Softmax 取对数。原文档特别说明它主要作为损失函数的组成部分与 NLLLoss 组合成 CrossEntropy很少单独用作激活。课堂问答激活函数的深层设计哲学PReLU 的 $a$共享、学习与复杂度为什么所有通道共用同一个 $a$并非必须。可以为每个通道、每个单元单独设置 $a$也可以把 $a$ 作为整个特征图的共享参数——这取决于你希望引入多少自由度。$a$ 是学习出来的吗学习 $a$ 有好处吗两者皆可。固定 $a$的目的是保证非线性在负区域也能给出非零梯度让 $a$ 可学习则允许系统把非线性调成线性映射或完全整流full rectification例如可实现一个对边缘极性不敏感的边缘检测器。非线性函数应该多复杂理论上可用弹簧参数spring parameters、切比雪夫多项式等把整条非线性函数参数化得很复杂参数化本身也可纳入学习过程。参数化 vs 增加单元数取决于任务。低维回归中参数化可能有帮助高维任务如图像识别中单调的非线性通常就够用——参数化任何函数都可以但未必带来巨大收益。折点kink相关的尺度问题单折点 vs 双折点双折点函数如 Sigmoid内建了尺度感若输入信号幅度放大两倍输出行为会完全不同而单折点函数如 ReLU把输入放大两倍输出恰好也放大两倍——即尺度等变性scale equivariance。有折点 vs 光滑非线性何时偏好哪种本质是尺度问题。输入放大 100 倍时光滑过渡部分被压缩函数看起来像硬折点输入缩小 100 倍时折点又变成非常光滑的凸函数。因此改变输入尺度会改变激活行为。这对多层网络是个麻烦你无法控制相邻两层的权重相对大小若非线性在乎尺度第一层权重大小的选择会被完全束缚。解决办法是对每层权重施加硬性归一化如 Batch Normalization使进入每个单元的方差恒定。但固定尺度后双折点系统就失去了选择使用非线性哪一段的自由若被固定的部分太线性如 Sigmoid 在零点附近近似线性BatchNorm 输出接近 0 时可能根本没有被非线性激活。深层网络为何偏爱单折点函数至今没有完全定论很可能正是源于这种尺度等变性。仓库中关于 ReLU 在多层网络中的折叠效果可视化可参见 docs/it/week03/03-1.md。soft(arg)max 的温度系数何时用温度系数 $\beta$一定程度下$\beta$ 与输入权重是冗余的softmax 前有加权求和时$\beta$ 与权重尺度可互相吸收但若在 softmax 前有某种归一化调整 $\beta$ 就能独立控制输出的硬度$\beta\to\infty$ 时输出接近 one-hot退化为 argmax$\beta\to 0$ 时退化为平均。实用技巧退火annealing训练初期用较小的 $\beta$ 让梯度下降行为良好随着训练推进、想要在注意力机制中得到更硬的决策时再逐步增大 $\beta$。该技巧对 mixture-of-experts、自注意力等机制很有用。PyTorch 损失函数详解PyTorch 在torch.nn中实现了大量损失函数本节按原文档顺序逐一解析重点关注reduction归约模式mean/sum/none与使用场景。nn.MSELoss()—— L2 损失计算输入 $x$ 与目标 $y$ 逐元素的均方误差平方 L2 范数。对包含 $n$ 个样本的 minibatch未归约reductionnone时$$l(x,y) L {l_1,\dots,l_N}^\top,\quad l_n (x_n - y_n)^2$$其中 $N$ 为 batch 大小$x,y$ 为各含 $n$ 个元素的任意形状张量。归约选项默认reductionmean$$l(x,y) \begin{cases} \text{mean}(L), \text{if reductionmean}\ \text{sum}(L), \text{if reductionsum} \end{cases}$$注意mean模式先对所有元素求和再除以 $n$若希望避免除以 $n$应显式设置reductionsum。仓库中 05-regression.ipynb、10-autoencoder.ipynb自编码器重构损失、13-bayesian_nn.ipynb、14-truck_backer_upper.ipynb控制器训练均使用nn.MSELoss()。nn.L1Loss()—— 平均绝对误差$$l(x,y) L {l_1,\dots,l_N}^\top,\quad l_n |x_n - y_n|$$同样支持mean/sum/none三种归约。使用场景相比 L2L1 对离群点与噪声更鲁棒——L2 会对离群误差取平方使代价函数对离群点极度敏感。问题L1 在 0 点不可导处理其梯度如 Softshrink需格外小心这正催生了下面的 SmoothL1Loss。nn.SmoothL1Loss()—— 平滑 L1 / Huber 损失逐元素绝对误差小于 1 时使用 L2否则使用 L1$$\text{loss}(x,y) \frac{1}{n}\sum_i z_i,\qquad z_i \begin{cases} 0.5(x_i-y_i)^2, |x_i-y_i| 1\ |x_i-y_i| - 0.5, \text{otherwise} \end{cases}$$同样支持reduction选项。该损失由 Ross Girshick 在Fast R-CNN中推广也称Huber Loss用作目标函数时又被称作弹性网络Elastic Net。使用场景比MSELoss对离群点更不敏感且在低误差区域是光滑的常被用于计算机视觉任务以抵御离群点。问题函数内自带尺度上式中的 0.5即其对误差的绝对尺度有依赖。L1 vs L2计算机视觉中的选择预测时存在多个可能的 $y$用MSEL2会得到所有 $y$ 的平均在 CV 中意味着模糊图像用L1最小化 L1 距离的 $y$ 是中位数结果不模糊但注意高维空间中位数难以定义。因此 CV 中偏好 L1 以获得更锐利的预测图像。nn.NLLLoss()—— 负对数似然用于 $C$ 类分类问题。数学上输入应为对数似然但 PyTorch 并不强制效果是把正确类别对应的分量做得尽可能大。未归约reductionnone时$$\ell(x,y) L {l_1,\dots,l_N}^\top,\quad l_n -w_{y_n}x_{n,y_n},\quad w_c \text{weight}[c]\cdot \mathbb{1}{c \neq \text{ignore_index}}$$其中 $N$ 为 batch 大小。归约默认mean时$$\ell(x,y) \begin{cases} \sum_{n1}^N \frac{1}{\sum_{n1}^N w_{y_n}} l_n, \text{if reductionmean}\ \sum_{n1}^N l_n, \text{if reductionsum} \end{cases}$$可选参数weight为 1D 张量为每个类别分配权重对类别不平衡的训练集非常有用。权重与类别不平衡权重向量适用于各类别频率差异大的场景例如普通感冒远多于肺癌可直接给样本少的类别加大权重。但原文档强调与其调权重不如在训练中均衡各类别频率以更好地利用随机梯度。具体做法把每类的样本放入各自的桶buffer生成每个 minibatch 时从每个桶抽取相同数量的样本小桶抽完就循环从头再抽直到大桶样本全部用完——即循环缓冲circular buffer方案保证各类频率相等且绝不丢弃多数类的任何样本Dont leave data on the floor!。该方案的明显问题是网络学不到真实的类别频率。解决方法是在训练最后额外跑几个 epoch按真实类别频率采样做微调让输出层的偏置适应高频类别。LeCun 用医学院的比喻帮助理解医学生花在罕见病上的时间与常见病一样多甚至更多先学会所有疾病特征再纠正对罕见性的认知。nn.CrossEntropyLoss()—— 交叉熵组合版将nn.LogSoftmax与nn.NLLLoss合并为一个类目标是让正确类别的分数尽可能大。合并的原因在于梯度计算的数值稳定性softmax 值接近 1 或 0 时其对数接近 0 或 $-\infty$而对数在 0 附近的斜率接近 $\infty$会让反向传播的中间步骤出现数值问题合并后梯度被饱和处理最终得到合理数值。输入应为每类未归一化的分数logits$$\text{loss}(x,c) -\log\left(\frac{\exp(x[c])}{\sum_j \exp(x[j])}\right) -x[c] \log\left(\sum_j \exp(x[j])\right)$$指定weight时$$\text{loss}(x,c) w[c]\left(-x[c] \log\left(\sum_j \exp(x[j])\right)\right)$$各 minibatch 的观测损失取平均。物理上交叉熵与KL 散度相关衡量两个分布之间的差异这里的准分布是预测向量 $x$ 与目标分布one-hot错误类为 0、正确类为 1$$H(p,q) H(p) \mathcal{D}_{KL}(p \mid\mid q)$$其中 $H(p,q) -\sum_i p(x_i)\log q(x_i)$ 是交叉熵$H(p) -\sum_i p(x_i)\log p(x_i)$ 是熵$\mathcal{D}_{KL}(p\mid\mid q) \sum_i p(x_i)\log\frac{p(x_i)}{q(x_i)}$ 是 KL 散度。仓库中使用交叉熵的实例非常多04-spiral_classification.ipynb 的螺旋分类criterion torch.nn.CrossEntropyLoss()配合optimizer.zero_grad()→loss.backward()→optimizer.step()的标准训练循环、08-seq_classification.ipynb 的序列分类、16-gated_GCN.ipynb 的图分类均使用它。nn.AdaptiveLogSoftmaxWithLoss()—— 大规模 softmax 近似当类别数极大例如百万级时标准 softmax 的计算代价过高。该模块实现高效的 softmax 近似通过把类别组织成聚类层级、共享嵌入等技术加速计算。方法细节出自 Grave 等人的论文Efficient softmax approximation for GPUsarXiv:1609.04309特别适用于大规模语言模型输出层等场景。从原文档到可运行代码仓库中的实战印证原文档讲授的模块在本仓库的 notebook 中均有直接落地可对照运行文档主题仓库中的对应实现nn.ReLU() 多层感知04-spiral_classification.ipynbnn.Linear → nn.ReLU() → nn.Linear配合CrossEntropyLoss与 Adam 达到 95% 准确率nn.ReLU()/nn.Tanh()对比05-regression.ipynb10 条网络各 5 条用 ReLU分段线性与 Tanh光滑回归nn.Tanh()nn.MSELoss()10-autoencoder.ipynb编码器/解码器均用nn.Tanh()重构损失为nn.MSELoss()nn.ReLU()nn.Sigmoid()11-VAE.ipynb编码器 ReLU、输出层 Sigmoidnn.CrossEntropyLoss()08-seq_classification.ipynb、16-gated_GCN.ipynb 的分类任务nn.BCEWithLogitsLoss()第 11-2 讲续09-echo_data.ipynb回声数据二分类小结与选型建议深层分类网络默认从 ReLU 出发若遭遇 dying ReLU 或网络过瘦换成 LeakyReLU/PReLU追求平滑梯度时考虑 GELU 或 ELU 家族。数值稳定性优先分类首选nn.CrossEntropyLoss()内部融合 LogSoftmax NLLLoss二分类用nn.BCEWithLogitsLoss()融合 Sigmoid见 docs/it/week11/11-2.md回归首选nn.SmoothL1Loss()以兼顾鲁棒性与可导性。类别不平衡优先做训练期频率均衡循环缓冲最后微调真实频率也可用weight参数快速缓解。大规模类别输出考虑nn.AdaptiveLogSoftmaxWithLoss()。记忆尺度教训单折点激活的尺度等变性是深层网络稳定训练的隐性保障若使用双折点/光滑激活配合归一化如 BatchNorm时需警惕其线性区陷阱。本讲为第 11 周激活与损失函数的上半部分后半部分margin-based 损失、能量模型损失等请见 docs/it/week11/11-2.md 与 docs/it/week11/11-3.md。赞分享示例工程【免费下载链接】NYU-DLSP20NYU Deep Learning Spring 2020项目地址https://gitcode.com/gh_mirrors/pyt/pytorch-Deep-Learning点击查看免费下载相关推荐NYU-DLSP20 第 11 周上PyTorch 激活函数与损失函数完全指南NYU DLSP20 第 11 周上PyTorch 激活函数与损失函数完全指南 本指南对应 NYU Deep Learning Spring 2020 课示例工程NYU-DLSP20 第11周PyTorch 激活函数与损失函数全解析NYU DLSP20 第11周PyTorch 激活函数与损失函数全解析 本文基于 NYU DLSP20NYU Deep Learning Spring 20示例工程NYU 深度学习课程DLSP20PyTorch 激活函数与损失函数全解第 11 周讲义 Part 1NYU 深度学习课程DLSP20PyTorch 激活函数与损失函数全解第 11 周讲义 Part 1 本文基于 NYU Deep Learning Spr示例工程上一篇终极AdminSet运维平台指南如何实现企业级自动化运维管理下一篇10分钟上手pg_lake从安装到查询Iceberg数据的完整指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考