【Pytorch】激活函数 Loss 梯度 超详细文本笔记
一、先讲个故事:投篮训练
-
你投篮球 → 这叫前向传播
-
看球离筐多远 → 这叫算 Loss(误差)
-
告诉手臂“下次多用力/少用力” → 这叫反向传播(梯度)
-
手臂关节里有个“开关”决定要不要听 → 这叫激活函数
二、激活函数:把“直线”掰弯的开关
表格
复制
名字 | 前向(输入→输出) | 反向(局部梯度) | 一句话记忆 |
---|---|---|---|
Sigmoid | σ(x)=1/(1+e^(-x)) | σ′=σ(1−σ) | 用输出自己算,越极端越没信号 |
Tanh | tanh(x) | 1−tanh²(x) | 同样用输出,0附近斜率最大 |
ReLU | max(0,x) | x>0→1, x≤0→0 | 正区域全开,负区域全关 |
LeakyReLU | max(αx,x) (α=0.01) | x>0→1, x≤0→α | 负区留个小缝,避免“死亡” |
代码看一眼(不用背):
Python
复制
import torch, torch.nn.functional as F
x = torch.tensor([-2., 0., 2.], requires_grad=True)
y = torch.sigmoid(x) # 换成 torch.tanh(x) / F.relu(x)
loss = y.sum() # 随便造个标量
loss.backward()
print(x.grad) # 局部梯度值
三、Loss 函数:量“差多少”的尺子
1. 回归任务(预测连续值)
-
MSE(L2): loss = (ŷ−y)² → 梯度 = ŷ − y
例:预测房价 100 万,真值 103 万 → 梯度 3 万(告诉模型再涨 3 万)
2. 分类任务(预测类别)
-
Cross-Entropy(多类):
-
先 softmax 把 logits→概率 prob
-
梯度 = prob − label(one-hot 形式)
例:真实类别 [0,1,0],prob=[0.2,0.7,0.1] → 梯度=[0.2,−0.3,0.1](负的往下压,正的往上抬)
-
-
BCEWithLogits(多标签):
梯度 = σ(z) − y(sigmoid 输出减标签)
代码模板(分类必背):
Python
复制
logits = model(images) # [batch, n_class]
loss = F.cross_entropy(logits, labels) # 内部已含 softmax
loss.backward() # 反向
# logits.grad 就是 prob − label
四、Softmax 梯度矩阵(自定义时才用)
定义:p_i = e^{a_i} / Σ_k e^{a_k}
雅可比矩阵:
复制
∂p_i / ∂a_j =i=j : p_i(1−p_i) ← 对角i≠j : −p_i p_j ← 非对角
记忆:
-
自己:p(1−p)(正数,随自信度减小)
-
别人:−p_i p_j(负数,互相抢概率)
五、常见翻车点
表格
复制
翻车现象 | 原因 | 正确打开 |
---|---|---|
loss.backward() 报错“no grad” | 忘了 requires_grad=True | 创建张量时加参数或 x.requires_grad_() |
分类 loss 爆炸 | 先手动 softmax 再送 CE | 给原始 logits,CrossEntropyLoss 自带 softmax |
二次 backward 报错 | 第一次没留图 | 第一次加 retain_graph=True 或重构计算图 |
ReLU 神经元全死 | 学习率太大+负输入 | 换 LeakyReLU / 调小学习率 / 批量归一化 |
六、一口诀背走
“激活局部三样板:sig 自身乘补,tanh 一减平方,ReLU 台阶;分类全局一句话:prob 减 label!”
七、30 秒复盘
-
激活只产生局部开关(0/1 或 p(1−p))
-
Loss 产生全局误差信号(ŷ−y 或 prob−label)
-
PyTorch 自动链式相乘 → 每个参数得到
.grad
-
你只做三件事:选激活 → 选 Loss → 调
loss.backward()