欢迎光临
我们一直在努力

第7课:PyTorch|激活函数全品类详解与选型实战【神经网络的“火花塞”】

在这里插入图片描述

文章目录

    • 📖 课前导读
      • 为什么神经网络必须要有激活函数?
      • 学完这一课,你将能够:
    • 一、知识原理:激活函数的本质与作用
      • 1.1 激活函数在神经元中的位置
      • 1.2 一个优秀激活函数的特征
    • 二、环境搭建与准备
    • 三、代码实战:逐类解读主流激活函数
      • 3.1 Sigmoid:开拓者的荣光与桎梏
      • 3.2 Tanh(双曲正切):零中心的改进
      • 3.3 ReLU及其“死亡神经元”困境
      • 3.4 LeakyReLU / PReLU / RReLU:对抗死亡ReLU的三兄弟
      • 3.5 ELU与SELU:用指数函数让负值平滑过渡
      • 3.6 ReLU家族速查表
      • 3.7 SiLU / Swish:自门控平滑激活
      • 3.8 GELU:Transformer的首选激活函数
      • 3.9 Softmax:让输出变成“概率分布”
      • 3.10 Mish:2019年的“完美主义者”
      • 3.11 Gated Linear Unit(GLU)家族:大模型FFN的新标准
        • 核心变体对比
      • 3.12 激活函数选型终极决策树
      • 3.13 不同任务激活函数选型速查表
      • 3.14 梯度消失/死亡ReLU的预防与调试
    • 四、难点解析:高频问题与陷阱
        • 问题1:`RuntimeError: element 0 of tensors does not require grad`
        • 问题2:在`CrossEntropyLoss`之前又多加了`nn.Softmax`
        • 问题3:BN/Dropout和激活函数的顺序排错
        • 问题4:怎么判断“死亡ReLU”正在影响训练?
    • 五、课后总结
      • 核心知识点速查表
      • 检查清单
    • 六、课后作业
        • 作业1:激活函数绘图
        • 作业2:死亡ReLU实验
        • 作业3:任务选型判断题
        • 作业4:Softmax vs CrossEntropy对比
    • 七、下一课预告
  • 🔗《精讲25课|PyTorch 从入门到精通》系列课程导航

📖 课前导读

为什么神经网络必须要有激活函数?

相信很多初学者都有这个疑问:为什么神经元加权求和后不能直接输出,非要加一个“激活函数”?

答案是:线性变换的复合仍然是线性变换。如果你把多个线性层叠起来,无论网络多深,最终都等价于一个单层线性模型,根本学不了XOR这样的简单非线性问题。激活函数存在的意义就是给神经网络注入非线性,让它有能力去拟合现实世界那些复杂的、弯弯曲曲的规律。

💡 生活类比:深度神经网络是一台发动机,数据是燃料,计算单元是气缸,而激活函数就是那个 “火花塞” 。它负责在合适的时机“点燃”信号,让信息在层与层之间有效传递。一个太弱的火花塞(如Sigmoid深层的饱和区)会让发动机熄火(梯度消失),一个不稳定的火花塞会让发动机爆震(梯度爆炸),而一个高效精准的火花塞,则是发动机平稳高效运行的关键。

学完这一课,你将能够:

  • ✅ 理解9种主流激活函数的数学原理、图像和梯度特性
  • ✅ 在PyTorch中正确使用不同的激活函数
  • ✅ 解决死亡ReLU问题——知道什么时候该用LeakyReLU/PReLU
  • ✅ 明白为什么Transformer用GELU/SiLU而不是ReLU
  • ✅ 掌握不同任务(分类/回归/多模态)的激活函数选型策略
  • ✅ 避开梯度消失、梯度爆炸等常见激活函数陷阱

一、知识原理:激活函数的本质与作用

1.1 激活函数在神经元中的位置

在每个神经元中,流程是这样的:输入信号 → 加权求和(加上偏置)→ 激活函数 → 输出到下一层。

如果用数学语言表达:output = activation(∑(w_i * x_i) + b)

关键事实:如果没有激活函数,无论网络有多少层,都只是线性模型的组合。线性模型的组合仍然是一个线性模型,根本无法拟合异或(XOR)这种最简单的非线性可分问题。激活函数之所以是“激活”的,就是它赋予了网络“开关”和“放大”信号的能力——让网络不仅知道“要不要传递”,还能以非线性的方式对信号进行变换。

1.2 一个优秀激活函数的特征

特征为什么重要
非线性 如果不满足,多层网络≈单层线性模型,表达能力归零
可微性(几乎所有点) 反向传播需要计算梯度,不可微点需要用次梯度近似
梯度值适中 梯度过大(爆炸)或过小(消失)都会导致训练困难
计算效率高 在大型模型中被调用亿万次,开销影响巨大
零中心(可选但有价值) 有利于梯度更新路径更高效(避免锯齿形收敛)

二、环境搭建与准备

import torch
import torch.nn as nn
import torch.nn.functional as F
import matplotlib.pyplot as plt
import numpy as np

print(f"PyTorch版本: {torch.__version__}")

# 设置中文绘图(可选)
# plt.rcParams['font.sans-serif'] = ['SimHei']
# plt.rcParams['axes.unicode_minus'] = False

# 用于可视化的输入范围
x = torch.linspace(5, 5, 200)


三、代码实战:逐类解读主流激活函数

3.1 Sigmoid:开拓者的荣光与桎梏

Sigmoid是所有激活函数中最“经典”的一个,曾被广泛用于神经网络的隐藏层。它的核心公式是:

sigmoid(x) = 1 / (1 + exp(-x))

它将任意实数x平滑地映射到(0, 1)区间,函数图像是一条光滑的S形曲线。它的特点是:

  • 输出饱和:当x很大或很小时,输出被死死压在0或1的边界上
  • 输出均值非0:梯度公式中x恒为正,权重的更新路径呈锯齿状,降低收敛效率
  • 梯度消失风险高:两边饱和区的导数极小,反向传播时梯度层层衰减

def sigmoid(x):
return 1 / (1 + torch.exp(x))

def sigmoid_derivative(x):
s = sigmoid(x)
return s * (1 s)

y_sigmoid = sigmoid(x)
y_sigmoid_grad = sigmoid_derivative(x)

# 可视化
plt.figure(figsize=(12, 5))
plt.subplot(1, 2, 1)
plt.plot(x.numpy(), y_sigmoid.numpy(), 'b-', linewidth=2, label='Sigmoid')
plt.axhline(y=0, color='k', linestyle='-', alpha=0.3)
plt.axhline(y=1, color='k', linestyle='–', alpha=0.3)
plt.grid(True, alpha=0.3)
plt.legend()
plt.title('Sigmoid 函数')

plt.subplot(1, 2, 2)
plt.plot(x.numpy(), y_sigmoid_grad.numpy(), 'r-', linewidth=2, label='导数')
plt.axhline(y=0, color='k', linestyle='-', alpha=0.3)
plt.grid(True, alpha=0.3)
plt.legend()
plt.title('Sigmoid 导数')
plt.tight_layout()
plt.show()

何时使用:在现代深度学习中,Sigmoid几乎只在二分类输出层出现(配合交叉熵损失)。请不要在隐藏层使用Sigmoid,尤其是在网络层数较深的时候——它的饱和区会让深层网络的浅层梯度几乎消失,模型几乎无法训练。

# PyTorch中的使用方式
sigmoid_layer = nn.Sigmoid()
x_input = torch.randn(10)
print(sigmoid_layer(x_input)[:3])

# 函数式(推荐在forward中直接使用)
y = torch.sigmoid(x_input)

3.2 Tanh(双曲正切):零中心的改进

Tanh是Sigmoid经过平移和缩放后的“增强版”,把输出区间从(0,1)扩展到(-1,1),区间对称于原点。它的公式是:

tanh(x) = (exp(x) – exp(-x)) / (exp(x) + exp(-x))

  • 输出零中心:让梯度方向更合理,避免权重的“锯齿形”更新路径
  • 依然存在梯度饱和:当|x|很大时,导数依然压得很低,深层网络仍然存在梯度消失的风险

y_tanh = torch.tanh(x)
y_tanh_grad = 1 y_tanh ** 2

# Tanh的导数和Sigmoid不同,它的峰值在x=0处最高

何时使用:在LSTM/GRU等门控循环网络里,Tanh被内置在单元结构中作为候选状态的激活函数。在普通全连接网络中,如果想用比Sigmoid更好但暂时不换ReLU,Tanh是一个过渡选择。

# PyTorch中的使用
tanh_layer = nn.Tanh()
y = tanh_layer(x_input)

3.3 ReLU及其“死亡神经元”困境

ReLU彻底改变了深度学习的面貌——它简单、快速、有效,公式简单得令人发指:

ReLU(x) = max(0, x)

它在正半轴的梯度恒定是1,在负半轴的梯度是0。这种稀疏性(只有少部分神经元被激活)带来了以下好处:计算效率极高(只判断正负,不用算指数);正区梯度恒定是1,有效缓解了Sigmoid/Tanh的梯度消失问题;同时产生稀疏表征,有助于解耦特征。

但是,它的致命缺陷是 “死亡ReLU” 问题:如果某个神经元的所有输入都是负的,它的输出恒为0,在反向传播中它的梯度也为0,权重的更新就永远停了。这导致该神经元“不可逆死亡”,再也没法被激活。在深度超过20层的网络中,未经特殊处理的ReLU可能导致30%–50%的神经元死亡,严重降低模型的有效容量。

class ReLU(nn.Module):
def forward(self, x):
return torch.maximum(torch.zeros_like(x), x)

def relu_derivative(x):
return (x > 0).float()

relu = nn.ReLU()
y_relu = relu(x)
y_relu_grad = relu_derivative(x)

可以看到ReLU的导数在x<0的区域是一条贴着零轴的平直线——梯度为0,这就是死亡神经元的根源。

典型场景:在图像分类、目标检测等视觉任务中,ReLU依然是默认首选。权重初始化用Kaiming(He)初始化,可以有效降低早期死亡ReLU的风险。

# 标准用法
relu_layer = nn.ReLU()
y = relu_layer(x_input)

# 函数式写法(更简洁)
y = F.relu(x_input)

3.4 LeakyReLU / PReLU / RReLU:对抗死亡ReLU的三兄弟

LeakyReLU的思想很直接:把负半轴的梯度从0改成一个极小的正斜率α,通常取α=0.01。公式变为:

LeakyReLU(x) = x if x > 0 else α*x

这就确保了即便输入是负的,神经元也能获得微弱的梯度更新,不会永久死亡。实验表明,α=0.01时神经元死亡率可降至5%以下。

LeakyReLU有两个“加强版”变体:

  • PReLU(参数化ReLU):把负半轴的斜率α从固定的超参数变成一个可学习的参数,网络会在训练中自动学习这个斜率。在大规模图像分类任务中,PReLU较原始ReLU可提升约1.2%的Top-1准确率。
  • RReLU(随机化ReLU):在训练时负半轴的斜率α在指定范围内随机采样,测试时取均值,有助于提升模型的泛化能力。

# LeakyReLU(PyTorch内置)
leaky_relu = nn.LeakyReLU(negative_slope=0.01)
y_leaky = leaky_relu(x)

# PReLU(可学习的参数,通常初始化为0.25)
prelu = nn.PReLU(num_parameters=1, init=0.25)
y_prelu = prelu(x)

# 对比ReLU和LeakyReLU的输出差异
test_x = torch.tensor([2.0, 1.0, 0.0, 1.0, 2.0])
print(f"ReLU输出: {F.relu(test_x)}")
print(f"LeakyReLU输出: {F.leaky_relu(test_x, negative_slope=0.01)}")
print(f"PReLU输出: {prelu(test_x)}")

选型建议:不想引入额外参数时直接选LeakyReLU(默认α=0.01效果已经很不错了)。希望网络自动学习最优负斜率时用PReLU。RReLU在正则化要求较高的场景下是加分项。

3.5 ELU与SELU:用指数函数让负值平滑过渡

ELU(Exponential Linear Unit)用指数函数来替换负半轴的线性部分,使函数在x=0处保持光滑(连续且可导):

ELU(x) = x if x > 0 else α*(exp(x)-1)

它的最大特点是对噪声更鲁棒。SELU(Scaled ELU)是ELU的“缩放加强版”,关键在于它能让深层网络自动保持输出的均值为0、方差为1——在精心设计下,梯度既不会消失也不会爆炸,可以训练极深的网络,是一种“自归一化”的属性。

elu = nn.ELU(alpha=1.0)
y_elu = elu(x)

# SELU(alpha和scale参数已被预设,通常不必再改)
selu = nn.SELU()
y_selu = selu(x)

计算开销:ELU/SELU涉及指数运算,相比LeakyReLU开销高出约15%左右。如果你非常在意推理速度,可以优先考虑ReLU或LeakyReLU。

3.6 ReLU家族速查表

函数公式(x<0部分)α取值优点缺点
ReLU 0 固定=0 计算极快,稀疏性 死亡神经元
LeakyReLU α*x 固定小值(0.01) 解决死亡问题,计算快 需手动调α
PReLU α*x 可学习 更灵活,性能更佳 增加参数量
RReLU α*x(随机) 训练随机/测试均值 自带正则化 引入随机性
ELU α*(e^x-1) 固定(1.0) 负值平滑,抗噪声 计算更重
SELU 缩放版ELU 预设参数 自归一化 适用范围有限

3.7 SiLU / Swish:自门控平滑激活

SiLU(Sigmoid Linear Unit,也叫Swish)是一种非常现代的激活函数,来自Google的自动搜索发现,它在深层网络中往往能超过ReLU。

公式简洁优雅:SiLU(x) = x * σ(x),其中σ(x)是标准Sigmoid函数

它的核心机制是“自门控”:用一个与输入x相关的概率值(Sigmoid的输出)来调控原始信号的通过强度。它比ReLU更平滑,负半轴输出不为0,彻底从根源上解决了死亡神经元问题。同时,它在负区有一个小小的“凸起”,这种非单调性可能有助于网络捕捉更复杂的模式。

一个关键澄清:SiLU和Swish本质上是同一个函数。Google论文中曾带有一个可学习超参数β,但是大量实验表明β=1的效果最好,所以几乎所有深度学习框架实现的SiLU都直接固定为x * sigmoid(x)了。

# PyTorch中使用SiLU
silu = nn.SiLU()
y_silu = silu(x)

# 函数式写法
y_silu = F.silu(x)

何时使用:现代CNN架构(如EfficientNet)和大语言模型(如LLaMA)已经在广泛使用SiLU。如果你训练的模型深度在几十层以上,并且希望获得比ReLU更平滑的梯度传播,可以考虑SiLU。

3.8 GELU:Transformer的首选激活函数

GELU(Gaussian Error Linear Unit)的初衷很有意思——它来自随机正则化的数学期望形式。公式是:GELU(x) = x * Φ(x),这里Φ(x)是标准正态分布N(0,1)的累积分布函数(CDF)。它近似地起到了 “输入越大,越倾向于激活” 的概率门控效果。

GELU也是Transformer架构的前馈网络(FFN)中的标配。在BERT、GPT这些大语言模型和ViT视觉Transformer里,都是靠它来引入非线性的。

# PyTorch官方实现(自动处理近似精度)
gelu = nn.GELU()
y_gelu = gelu(x)

# 函数式用法
y_gelu = F.gelu(x)

# 如果你需要兼容旧版Transformer(如Hugging Face早期实现),可以用tanh近似
gelu_tanh = nn.GELU(approximate='tanh')
y_gelu_tanh = gelu_tanh(x)

性能优势:在NLP任务的GLUE基准上,GELU比ReLU普遍高出约0.5至1.2个百分点。在ViT的ImageNet任务上,GELU比Swish大概高出0.3的top-1准确率。这些平滑优势在处理连续的文本或语音数据时尤其明显。

3.9 Softmax:让输出变成“概率分布”

严格来说,Softmax不是激活函数,它是一种将向量映射成概率分布的归一化操作——在PyTorch的nn.CrossEntropyLoss内部,Softmax已经默认被包含了,所以你不必在最后一层手动加Softmax再接入损失函数。

公式是:Softmax(z_i) = exp(z_i) / Σ_j exp(z_j)

它的输出是一个和为1的概率分布:[p1, p2, …, pk],其中每个p_i>0,适合处理多分类问题。

# 多分类输出层(配合CrossEntropyLoss使用)
class Classifier(nn.Module):
def __init__(self, input_dim, num_classes):
super().__init__()
self.fc = nn.Linear(input_dim, num_classes)
# 注意:这里不加Softmax,因为CrossEntropyLoss内部包含它

def forward(self, x):
logits = self.fc(x) # 原始输出值(未归一化的“得分”)
return logits # 交给损失函数处理,不要手动加Softmax

Softmax和CE的内部关系:CrossEntropyLoss = LogSoftmax + NLLLoss。如果你在最后一层加了Softmax,又传给了CrossEntropyLoss,那就等于是重复做了一次指数归一化,模型会失去正确的数值稳定性。

3.10 Mish:2019年的“完美主义者”

Mish是2019年提出的,它结合了自门控机制和负半轴的平滑性,数学形式是:

Mish(x) = x * tanh(softplus(x)) = x * tanh(ln(1 + e^x))

它的优势是全区间光滑(处处可导)、允许负半轴有一个较小的非零输出、而且自带轻度的自正则化效果(输出被限制在一个比较温和的范围内)。在原始论文中,Mish在某些图像任务上比ReLU可以提升1-2个百分点。

主要代价:因为它要反复算指数、对数与tanh,计算开销是ReLU的几倍。在实际部署时,尤其在嵌入式设备上,这个计算负担是不可忽略的。

# PyTorch 1.9+ 已内置Mish
mish = nn.Mish()
y_mish = mish(x)

3.11 Gated Linear Unit(GLU)家族:大模型FFN的新标准

GLU(Gated Linear Unit)是一种门控线性单元,与普通激活函数最核心的区别在于:它不是简单地处理一个值,而是在FFN内并排设置两条线性变换路径,然后逐元素相乘。

其通用形式为:GLU(x) = (x * W1 + b1) * σ(x * W2 + b2),其中σ是Sigmoid门控。门控信号告诉网络哪些维度信息值得保留,哪些需要被削弱。

核心变体对比
变体公式代表模型
ReGLU x_a * ReLU(x_b) 较早期
GeGLU x_a * GELU(x_b) 某些研究
SwiGLU x_a * SiLU(x_b) PaLM、LLaMA、DeepSeek

SwiGLU是当前最主流的选择,在PaLM、LLaMA等主流大模型中已经完全取代了传统ReLU和GELU的FFN结构。虽然它的参数量比标准FFN更多,但换来的是更强的表达力和更优的训练效率。

3.12 激活函数选型终极决策树

"""
激活函数选型决策树(思维导图版)

1. 是任务的输出层吗?
├── 是 → 多分类 → Softmax(由CrossEntropyLoss间接处理)
├── 是 → 二分类 → Sigmoid(一维输出,配合BCE Loss)
└── 是 → 回归 → 不加激活函数(纯线性输出)

2. 是Transformer/LLM架构吗?
├── 是 → GELU(GPT/BERT等经典Transformer)
│ └── 或 → SiLU / SwiGLU(PaLM/LLaMA等大模型趋势)

3. 是常规CNN/MLP隐藏层吗?
├── 追求极简与速度 → ReLU
├── 担心神经元死亡/深层训练 → LeakyReLU(PReLU)
└── 需要平滑负半轴 → ELU/SELU/Mish(如果算力充足)
"""

3.13 不同任务激活函数选型速查表

任务领域推荐隐藏层激活推荐输出层激活理由
图像分类(CNN) ReLU / LeakyReLU / SiLU Softmax(多分类) ReLU速度快,SiLU深层更平滑
目标检测 ReLU / LeakyReLU Sigmoid / Softmax 检测头需独立输出类别+置信度
语义分割 ReLU / ELU Softmax(逐像素) ELU对分割边界的噪声更鲁棒
NLP(文本分类) GELU / ReLU Softmax Transformer标配GELU,浅层模型用ReLU
机器翻译/LM GELU / SwiGLU Softmax(词表大小) SwiGLU是大模型新标准
时序预测(RNN/LSTM) Tanh(内置) 线性(回归) / Sigmoid(分类) LSTM内部固定使用Tanh+Sigmoid
生成模型(GAN/VAE) LeakyReLU / Mish Sigmoid(GAN判别器) 防止死亡神经元,保持梯度稳定
强化学习 ReLU / Tanh 线性(连续动作)/ Softmax(离散动作) Policy网络常用Tanh约束动作范围

3.14 梯度消失/死亡ReLU的预防与调试

死亡ReLU不是玄学,你完全可以用以下方法主动调试和预防:

  • 监控神经元活动率:在训练过程中打印ReLU激活值的均值,如果均值长期接近于0,说明大量神经元失效了。可以中间穿插添加LeakyReLU来测试效果。
  • 用合适的初始化:ReLU网络必须使用Kaiming(He)初始化,设置mode='fan_out'和nonlinearity='relu'。
  • 梯度裁剪:如果训练初期Loss出现inf或nan,在反向传播后执行torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)。
  • 实验对比:同一组超参数下,用LeakyReLU/PReLU和ReLU分别跑一遍,若LeakyReLU的准确率明显更高,说明原始网络中死亡ReLU确实已经干扰了训练。

四、难点解析:高频问题与陷阱

问题1:RuntimeError: element 0 of tensors does not require grad

请检查输入数据是否被错误地转换成了整数类型(如torch.long)。SiLU/GELU等函数要求输入必须是浮点型(float32/float64)。改正方法:调用.float()把整数张量转成浮点。

问题2:在CrossEntropyLoss之前又多加了nn.Softmax

这是新手最常犯的错误之一。CrossEntropyLoss在内部其实做了LogSoftmax + NLLLoss的处理,如果你在外面手动又套了一个Softmax,梯度路径中就会连续叠加两次指数归一化,导致数值稳定性变差甚至退化到极低准确率。

问题3:BN/Dropout和激活函数的顺序排错

经典的最佳实践顺序是:Linear / Conv2d → BatchNorm → Activation → Dropout。

  • BatchNorm放在激活函数之前(Pre-activation)是目前的主流做法,能让激活函数的输入分布更加稳定。
  • Dropout放在激活函数之后,让它作用于被激活的特征,而不是原生的净输入。
问题4:怎么判断“死亡ReLU”正在影响训练?

如果你怀疑模型陷入了死亡ReLU的困境,可以定期打印各层权重梯度的标准差。如果中间层梯度出现大量接近于0的参数,而且训练损失几乎不再下降,说明ReLU死亡问题正在显现。换用LeakyReLU或PReLU再做一组对比实验,如果后者迅速开始收敛,验证了死亡ReLU的判断。


五、课后总结

核心知识点速查表

函数公式优点缺点适用场景
Sigmoid 1/(1+e^-x) 平滑、可微、值域(0,1) 梯度消失、非零中心 二分类输出层
Tanh (ex-e-x)/(ex+e-x) 零中心 仍有梯度消失 LSTM单元
ReLU max(0,x) 计算快、稀疏、缓解梯度消失 死亡神经元 CNN/MLP隐藏层(默认)
LeakyReLU x if x>0 else αx 解决死亡神经元 需调α 深层网络
PReLU x if x>0 else αx(α可学习) 最灵活 增加参数量 大型模型
ELU x if x>0 else α(e^x-1) 负值平滑、抗噪声 计算更重 对噪声敏感的任务
SiLU/Swish x*σ(x) 平滑、自门控、无死亡 比ReLU稍慢 深层网络、大模型
GELU x*Φ(x) Transformer首选、性能优 计算开销中等 Transformer/ViT
Softmax ez_i/Σez_j 概率分布 只能多分类输出 多分类输出层
Mish x*tanh(softplus(x)) 自正则化、平滑 计算极重 高端视觉任务
SwiGLU x_a*SiLU(x_b) 大模型新标准 参数量增加 PaLM/LLaMA等

检查清单

  • 能解释为什么神经网络必须使用非线性激活函数
  • 理解ReLU死亡问题的根源与解决方案
  • 知道Softmax应与CrossEntropyLoss配合使用,不在输出层重复添加
  • 能根据任务类型(分类/回归/Transformer)选择合适的激活函数
  • 会使用PyTorch的nn和F两种方式调用激活函数
  • 能识别梯度消失的征兆并尝试调整激活函数
  • 了解SwiGLU等门控激活函数的演进趋势

六、课后作业

作业1:激活函数绘图

使用torch.linspace(-10, 10, 200)绘制ReLU、LeakyReLU(α=0.01)、ELU(α=1)、SiLU、GELU在同一个坐标轴上的函数曲线,并标注其导数曲线(可用子图呈现)。

作业2:死亡ReLU实验

构建一个5层全连接网络(每层512个神经元,激活函数ReLU),在MNIST上训练10个epoch。在训练过程中hook住每一层ReLU层的激活值,统计每层激活值为0的比例。换用LeakyReLU(α=0.01)再训练一次,对比两组的测试准确率和神经元死亡率。

作业3:任务选型判断题

假设你接到以下任务,请选出一个最合适的隐藏层激活函数和输出层激活函数:

  • (A)电影评论情感二分类(用LSTM)
  • (B)CIFAR-10图像分类(用ResNet-18)
  • (C)房价预测(回归)
  • (D)自己实现一个迷你版GPT
作业4:Softmax vs CrossEntropy对比

写出两种错误的代码实现,解释它们为什么是错误的,以及正确的替代写法:

  • 在网络的forward中加了Softmax,但又把输出传给了CrossEntropyLoss。
  • 手动在最后一层做了Softmax,然后在优化循环里对输出直接用MSE Loss。

  • 七、下一课预告

    第8课我们将学习损失函数详解与深度学习损失选型,内容包括:

    • 回归任务损失(MSE、L1、SmoothL1)
    • 分类任务损失(交叉熵、NLLLoss、BCE)
    • 自定义损失函数编写
    • 多任务学习中的损失组合策略
    • 训练中损失异常的排查思路

    学完第8课,你将能根据不同任务精准选对损失函数,并解决训练中损失不下降、梯度消失/爆炸等常见难题。


    附录:本章PyTorch激活函数API速查

    PyTorch模块函数式版本说明
    nn.Sigmoid() torch.sigmoid() 输出(0,1),饱和易消失
    nn.Tanh() torch.tanh() 输出(-1,1),零中心
    nn.ReLU() F.relu() 正区梯度1,负区0
    nn.LeakyReLU(negative_slope) F.leaky_relu(x, negative_slope) 负区保留小梯度
    nn.PReLU(num_parameters) α可学习
    nn.ELU(alpha) F.elu(x, alpha) 负区指数过渡
    nn.SELU() F.selu() ELU的自归一化版本
    nn.SiLU() F.silu() 即Swish(β=1)
    nn.GELU(approximate) F.gelu(x, approximate) Transformer标配
    nn.Softmax(dim) F.softmax(x, dim) 多分类输出,慎用于损失前
    nn.LogSoftmax(dim) F.log_softmax(x, dim) 数值稳定的log概率
    nn.Mish() F.mish() PyTorch 1.9+

    🔗《精讲25课|PyTorch 从入门到精通》系列课程导航

    去订阅

    🌟 感谢您耐心阅读到这里! 💡 如果本文对您有所启发欢迎: 👍 点赞📌 收藏 📤 分享给更多需要的伙伴。 🗣️ 期待在评论区看到您的想法, 共同进步。 🔔 关注我,持续获取更多干货内容~ 🤗 我们下篇文章见~

    赞(0)
    未经允许不得转载:171主机测评 » 第7课:PyTorch|激活函数全品类详解与选型实战【神经网络的“火花塞”】
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址