Tanh (Hyperbolic Tangent)
Tanh 将输入映射到以零为中心的 S 形曲线上,输出范围为 −1 到 1。内容涵盖其公式、梯度、在 RNN、GAN 和控制中的用途,以及 PyTorch 代码。
双曲正切函数 tanh(x) = (eˣ − e^(−x)) / (eˣ + e^(−x)) 是一种激活函数,它沿着以零为中心的 S 形曲线,将任意实数映射到 −1 到 1 之间的值。它是经过缩放的Sigmoid 函数,tanh(x) = 2σ(2x) − 1,因此形状与 Sigmoid 相同,但负输入会得到负值,并且在原点处的斜率为 1。Tanh 在 20 世纪 90 年代和 21 世纪初一直是神经网络隐藏层的标准激活函数。如今,它用于生成循环神经网络(RNNs)的隐藏状态、限制图像生成器和控制策略的输出,并将更大型模型中的数值限制在一定范围内。
公式与性质#
Tanh 是奇函数,tanh(−x) = −tanh(x),且 tanh(0) = 0。在零附近,它近似线性,即 tanh(x) ≈ x;当输入超过约 ±3 时,曲线会逐渐趋近 ±1。它的导数为 1 − tanh²(x),在原点处等于 1,是 Sigmoid 最大值 0.25 的四倍,并且会在曲线饱和时趋近于零。下面的 PyTorch 代码片段会计算 tanh 及其梯度,然后比较零均值输入下 tanh 和 Sigmoid 的平均输出:
import torch
x = torch.tensor([-3.0, -1.0, 0.0, 1.0, 3.0], requires_grad=True)
y = torch.tanh(x)
# The derivative of tanh is 1 - tanh(x)^2, which peaks at 1 when x = 0
y.sum().backward()
print(f"Tanh: {[round(v, 3) for v in y.tolist()]}")
print(f"Gradient: {[round(v, 3) for v in x.grad.tolist()]}")
# For zero-mean inputs, tanh outputs average near 0 and sigmoid outputs near 0.5
torch.manual_seed(0)
z = torch.randn(100_000)
print(f"Mean output, tanh: {torch.tanh(z).mean():.3f}, sigmoid: {torch.sigmoid(z).mean():.3f}")它会输出 [-0.995, -0.762, 0.0, 0.762, 0.995] 的 tanh 值和 [0.01, 0.42, 1.0, 0.42, 0.01] 的梯度,因此 ±3 处的梯度只有零点处的百分之一。对于 100,000 个标准正态输入,tanh 输出的平均值约为 0.0,Sigmoid 输出的平均值约为 0.5。
零中心输出为何有帮助#
神经元的权重梯度与其输入成正比。当所有输入都为正时(Sigmoid 输出始终如此),神经元的所有权重梯度在每次更新中符号相同,因此权重只能一同增大或一同减小,只能通过来回摆动逐步达到最优值。Tanh 输出的正值和负值大致相等,因此每个权重都能独立调整,并使下一层的输入保持在零均值附近,从而让梯度下降更快收敛。因此,Yann LeCun 及其同事在 1998 年的指南《高效反向传播》(“Efficient BackProp”)中建议,隐藏层应使用对称函数而不是逻辑 Sigmoid,具体推荐了缩放形式 1.7159 · tanh(2x/3)。不过,Tanh 仍会饱和,而且堆叠许多 Tanh 层会在反向传播过程中使梯度变小,这就是梯度消失问题。
Tanh 的应用场景#
- 循环网络: 简单 RNN 的状态更新公式为 hₜ = tanh(Wxₜ + Uhₜ₋₁ + b),而 tanh 是 PyTorch
nn.RNN的默认非线性函数。在 LSTM 和 GRU 单元中,tanh 用于生成候选内容;在 LSTM 中,它还会在输出前压缩单元状态,而 Sigmoid 门则决定使用其中多少内容。这个有界范围可以防止逐步反馈的状态无限增长。 - GAN 生成器: DCGAN 会在生成器末端使用 tanh,使生成像素落在 −1 到 1 之间,也就是训练图像缩放后的范围;许多后来的生成对抗网络(GANs)也沿用了这种做法。
- 有界动作: 强化学习中的连续控制策略会将输出通过 tanh,以确保每个指令都不超出执行器的限制。软演员-评论家(Soft Actor-Critic)也会以这种方式压缩高斯策略的采样结果。
- Logit 软上限: Google 的 Gemma 2 语言模型会计算 cap · tanh(logits / cap),其中注意力 logits 的 cap 为 50,最终 logits 的 cap 为 30。较小的 logits 几乎不受影响,而较大的 logits 绝不会超过上限。
- GELU近似: 0.5x(1 + tanh(√(2/π)(x + 0.044715x³))) 能很好地近似 GELU,原始 GPT-2 和 BERT 代码就是这样计算 GELU 的。
- 归一化流: RealNVP 风格的流通常在每个尺度网络的末端使用 tanh,因此每个耦合层都会将输入缩放为 e⁻¹ 到 e 之间的因子,从而保持训练过程的数值稳定。YOLO26姿态估计模型使用残差对数似然估计损失进行训练;其六层 RealNVP 流在每个尺度网络末端都使用 tanh,用于建模预测关键点与真实标注之间的偏差。
Tanh 与相关函数的比较#
- Sigmoid: Tanh 是将 Sigmoid 的范围拉伸到 −1 至 1,并在水平方向压缩两倍后的函数,因此最大斜率从 0.25 提高到 1。Sigmoid 的范围是 0 到 1,因此适合用于概率和门控。
- Hardtanh: 分段线性函数,会将输入裁剪到 [−1, 1]。它的计算开销更低,并且在该范围之外的梯度恰好为 0。
- ReLU: max(0, x) 对正数输入永不饱和,且只需一次比较,因此 ReLU 及 SiLU 等平滑的后继激活函数取代了深层卷积神经网络 (CNNs)和 Transformer 隐藏层中的 tanh。在 AlexNet 论文中,使用 ReLU 的四层 CNN 在 CIFAR-10 上达到 25% 训练误差的速度,比使用 tanh 单元的同一网络快六倍。










