激活函数:Sigmoid、Tanh、ReLU、Leaky ReLU、Swish、GELU
一句话概述
激活函数是神经网络中引入非线性的关键组件,如果没有激活函数,无论堆叠多少层,整个网络都等价于一个线性变换。从早期广泛使用的Sigmoid和Tanh,到解决梯度消失问题的ReLU及其变体(Leaky ReLU),再到近年提出的自门控激活函数Swish和基于高斯误差函数的GELU,每一种激活函数都有其独特的数学性质和适用场景。理解激活函数的特性是设计和训练深度神经网络的基础。
💡 核心要点:①激活函数的核心作用是引入非线性,使网络能拟合任意复杂函数 ②Sigmoid和Tanh是早期常用的S型激活函数,但存在梯度饱和问题 ③ReLU及其变体(Leaky ReLU)是目前最广泛使用的激活函数,有效缓解梯度消失 ④Swish和GELU是新一代激活函数,在Transformer等现代架构中表现优异
教学与演示
一、激活函数的作用与非线性的必要性
是什么(定义):激活函数(Activation Function)是作用于神经元线性输出 z = w·x + b 之上的非线性函数 f(z),最终输出 a = f(z)。它将线性变换的结果映射到一个非线性空间,赋予神经网络表达非线性关系的能力。
大白话 激活函数就像翻译官——把神经元算出来的"线性分数"翻译成真正有区分力的"语义信号"。没有翻译官,再多神经元也只能说同一种"线性"语言,表达能力大打折扣。
为什么(原理):线性函数的复合仍然是线性的。如果没有激活函数,一个 N 层的全连接网络等价于一个单层线性变换:W_N(W_{N-1}(...(W_1 x)...)) = W_effective · x。这意味着深层网络退化为浅层网络,完全失去了"深度"的意义。激活函数通过引入非线性,打破了这种退化,使得网络能够逼近任意复杂的函数。这是万能近似定理(Universal Approximation Theorem)的基础。
大白话 想象你在和面:不加激活函数等于永远只用一只手揉——再怎么揉都是一层面。加上激活函数等于两只手配合,能揉出各种形状的面团。线性变换给出"形状",激活函数给出"花样"。
什么用(AI关联):激活函数的选择直接影响网络的训练速度、收敛性能和最终准确率。在深度学习中,ReLU已经成为隐藏层的默认选择,Sigmoid通常只用于二分类输出层,Softmax用于多分类输出层,GELU在Transformer(如BERT、GPT)中广泛使用。
哪些坑(缺点):没有一种激活函数是万能的。Sigmoid和Tanh容易导致梯度消失,ReLU可能造成神经元"死亡",Leaky ReLU引入了需要调参的斜率,Swish和GELU计算开销较大。选择激活函数需要根据具体场景权衡。
二、Sigmoid 激活函数
是什么(定义):Sigmoid函数(也称为Logistic函数)将任意实数输入映射到(0, 1)区间,其数学形式为 σ(x) = 1/(1 + e^{-x})。它是早期神经网络中最广泛使用的激活函数,也是逻辑回归中使用的函数。
大白话 Sigmoid就像一个"概率翻译器"——不管输入多大或多小,它都给压缩到0到1之间,输出可以解读为"这件事发生的概率"。
怎么做(实现):
import numpy as np
# ========================================
# Sigmoid 激活函数 —— 最早的平滑激活函数
# 将任意实数映射到 (0, 1) 区间
# ========================================
def sigmoid(x):
"""
Sigmoid 激活函数: σ(x) = 1 / (1 + e^(-x))
参数:
x: 输入值(标量或numpy数组)
返回:
(0, 1) 之间的输出值
性质:
输出范围:(0, 1),呈S型曲线
中心对称:关于 (0, 0.5) 中心对称
饱和区:|x| 较大时梯度趋近于 0
"""
# 使用 numpy 的 exp 函数,支持向量化计算
# 注意:对于很大的负值,exp(-x) 可能溢出
# 实际框架中使用 safe_sigmoid 避免数值问题
return 1.0 / (1.0 + np.exp(-x))
def sigmoid_derivative(x):
"""
Sigmoid 导数: σ'(x) = σ(x) * (1 - σ(x))
这是反向传播中计算梯度时需要的
导数在 x=0 处最大,为 0.25;在 |x| 增大时迅速趋近于 0
"""
s = sigmoid(x)
return s * (1.0 - s)
# --- 演示 Sigmoid 在不同输入值下的输出 ---
print("Sigmoid 函数演示:")
test_inputs = np.array([-5.0, -2.0, -1.0, 0.0, 1.0, 2.0, 5.0])
for x_val in test_inputs:
y_val = sigmoid(x_val)
dy_val = sigmoid_derivative(x_val)
print(f" σ({x_val:+.1f}) = {y_val:.4f}, 导数 = {dy_val:.4f}")
# --- 展示 Sigmoid 的饱和特性 ---
print("\n饱和特性分析:")
big_neg = -10.0 # 很大的负数
big_pos = 10.0 # 很大的正数
print(f" σ({big_neg}) = {sigmoid(big_neg):.6f} ← 趋近于 0")
print(f" σ({big_pos}) = {sigmoid(big_pos):.6f} ← 趋近于 1")
print(f" 导数在 ±10 处: {sigmoid_derivative(big_pos):.10f} ← 几乎为 0,梯度消失!")
大白话 Sigmoid的公式:分母1+e^{-x},当x特别大时e^{-x}≈0,分母≈1,结果≈1;当x特别小时e^{-x}巨大,分母巨大,结果≈0。这就是它把一切压到0和1之间的奥秘。
什么用(AI关联):Sigmoid主要用于二分类问题的输出层,将输出解释为属于正类的概率。在早期浅层网络中也被用作隐藏层激活函数。逻辑回归本质上就是Sigmoid+线性组合。
哪些坑(缺点):①梯度饱和:当|x|较大时,导数趋近于0,导致反向传播中梯度消失,深层网络几乎无法更新前面层的参数。②输出不是零均值的(输出中心约0.5),导致后层神经元接收到非零均值的输入,影响梯度下降效率。③涉及指数运算,计算开销较大。
三、Tanh(双曲正切)激活函数
是什么(定义):Tanh(Hyperbolic Tangent,双曲正切)函数将输入映射到(-1, 1)区间,数学形式为 tanh(x) = (e^x - e^{-x})/(e^x + e^{-x})。它是Sigmoid的线性变换:tanh(x) = 2σ(2x) - 1。
大白话 Tanh可以看作Sigmoid的"升级版"——输出范围从(0,1)变成了(-1,1),零均值输出了,但饱和问题依然存在。
怎么做(实现):
import numpy as np
# ========================================
# Tanh 激活函数 —— 零中心化的 S 型函数
# 将任意实数映射到 (-1, 1) 区间
# ========================================
def tanh(x):
"""
Tanh 双曲正切激活函数
数学定义: tanh(x) = (e^x - e^(-x)) / (e^x + e^(-x))
numpy 内置了 tanh 函数,效率更高
参数:
x: 输入值
返回:
(-1, 1) 之间的输出值
"""
return np.tanh(x)
def tanh_derivative(x):
"""
Tanh 导数: tanh'(x) = 1 - tanh^2(x)
导数在 x=0 时达到最大值 1.0(比 Sigmoid 的最大 0.25 大 4 倍)
在 |x| 增大时同样趋近于 0
"""
return 1.0 - np.tanh(x) ** 2
# --- 对比 Sigmoid 和 Tanh ---
print("Sigmoid vs Tanh 对比:")
test_vals = np.array([-3.0, -1.0, 0.0, 1.0, 3.0])
for x_val in test_vals:
s_val = 1.0 / (1.0 + np.exp(-x_val)) # Sigmoid
t_val = np.tanh(x_val) # Tanh
s_grad = s_val * (1.0 - s_val) # Sigmoid导数
t_grad = 1.0 - t_val ** 2 # Tanh导数
print(f" x={x_val:+.1f}: Sigmoid={s_val:+.4f}, Tanh={t_val:+.4f}")
print(f" Sigmoid'={s_grad:.4f}, Tanh'={t_grad:.4f}")
# --- 验证 Sigmoid 和 Tanh 的关系 ---
print("\n验证关系:tanh(x) = 2σ(2x) - 1")
x_test = 1.5
tanh_val = np.tanh(x_test)
sigmoid_based = 2.0 / (1.0 + np.exp(-2.0 * x_test)) - 1.0
print(f" tanh({x_test}) = {tanh_val:.6f}")
print(f" 2σ(2*{x_test})-1 = {sigmoid_based:.6f}")
print(f" 差值: {abs(tanh_val - sigmoid_based):.2e}")
# --- 均值分析 ---
many_vals = np.random.randn(1000) # 标准正态分布采样1000个点
sigmoid_outputs = 1.0 / (1.0 + np.exp(-many_vals))
tanh_outputs = np.tanh(many_vals)
print(f"\n输出均值(理想应为0):")
print(f" Sigmoid 输出均值: {np.mean(sigmoid_outputs):.4f} — 偏向正值")
print(f" Tanh 输出均值: {np.mean(tanh_outputs):.4f} — 接近零均值")
大白话 Tanh就是Sigmoid的"拉偏和放大"版:先把输入放大2倍过Sigmoid,再乘以2减1。结果是输出以0为中学,梯度最大值1.0(比Sigmoid的0.25好很多),但两端饱和的毛病依然在。
什么用(AI关联):Tanh在RNN和LSTM中经常用作隐藏状态的激活函数,因为其零均值特性有助于稳定训练。在一些生成模型中也常用。不过在现代CNN和Transformer中,Tanh基本被ReLU和GELU取代。
哪些坑(缺点):虽然比Sigmoid好(零均值、梯度更大),但饱和问题同样存在。在深层网络中,经过多层Tanh后梯度依然会趋近于零。
四、ReLU(修正线性单元)
是什么(定义):ReLU(Rectified Linear Unit,修正线性单元)是目前深度学习中最广泛使用的激活函数。其数学形式极其简单:f(x) = max(0, x)。当输入为负时输出0,输入为正时输出等于输入本身。
大白话 ReLU就是"有则照搬,无则闭嘴"——正数直接通过,负数全部挡掉。简单粗暴但出奇有效,是深度学习复兴的"幕后功臣"。
为什么(原理):ReLU的设计有两个核心优势:①正半轴梯度恒为1,完美避免了Sigmoid/Tanh的梯度饱和问题,使得深层网络的梯度可以畅通无阻地传播。②计算极其简单(只需要比较和判断),比指数运算快得多。③输出具有稀疏性——大约50%的神经元输出为0,这种稀疏激活在一定程度上模仿了生物神经元的特性。
怎么做(实现):
import numpy as np
# ========================================
# ReLU 激活函数 —— 深度学习的"国标"激活函数
# 简单、高效、解决了梯度消失问题
# ========================================
def relu(x):
"""
ReLU 激活函数: f(x) = max(0, x)
参数:
x: 输入值(标量或numpy数组)
返回:
max(0, x),所有负值被置为 0
关键性质:
- 正半轴导数恒为 1(无梯度饱和)
- 负半轴导数为 0(可能导致神经元"死亡")
- 计算量极小(仅需比较操作)
"""
return np.maximum(0, x)
def relu_derivative(x):
"""
ReLU 导数: f'(x) = 1 if x > 0 else 0
注意: 在 x=0 处数学上不可导,实际中通常取 0 或 0.5
"""
return np.where(x > 0, 1.0, 0.0)
def leaky_relu(x, alpha=0.01):
"""
Leaky ReLU: f(x) = max(αx, x)
给负半轴一个很小的斜率 α,避免神经元彻底"死亡"
参数:
x: 输入值
alpha: 负半轴斜率,通常取 0.01
"""
return np.where(x > 0, x, alpha * x)
# --- ReLU 基本演示 ---
print("ReLU 函数演示:")
test_vals = np.array([-5.0, -2.0, -0.5, 0.0, 0.5, 2.0, 5.0])
for x_val in test_vals:
y_val = relu(x_val)
dy_val = relu_derivative(x_val)
print(f" ReLU({x_val:+.1f}) = {y_val:+.1f}, 导数 = {dy_val:.1f}")
# --- Leaky ReLU vs ReLU ---
print("\nReLU vs Leaky ReLU(α=0.01)负值区对比:")
neg_vals = np.array([-3.0, -1.0, -0.1])
for x_val in neg_vals:
r_val = relu(x_val)
lr_val = leaky_relu(x_val, alpha=0.01)
print(f" x={x_val:+.1f}: ReLU={r_val:.3f}, Leaky ReLU={lr_val:.3f}")
# --- 神经元死亡演示 ---
print("\n'死神经元'模拟:")
# 假设一个神经元权重更新后,对所有样本都输出负值
np.random.seed(42)
weights = np.array([-1.0, -1.0]) # 全部负权重
samples = np.random.randn(10, 2) # 10个样本
for i, sample in enumerate(samples):
z = np.dot(weights, sample)
a = relu(z)
grad = relu_derivative(z)
print(f" 样本{i+1}: z={z:+.2f}, ReLU={a:.2f}, 梯度={grad:.1f}")
print(" → 所有梯度都为 0,这个神经元已经'死'了,再也不会更新!")
大白话 ReLU就是一个"选择性过滤器":好消息(正信号)放大通过,坏消息(负信号)直接屏蔽。正半轴的梯度永远是1,没有Sigmoid那种"传着传着就没了"的问题。
什么用(AI关联):ReLU是CNN中的默认激活函数,几乎所有经典CNN架构(VGG、ResNet、Inception等)都使用ReLU。在MLP中也广泛使用。它的发明是深度学习复兴的标志性事件之一。
哪些坑(缺点):主要问题是"死神经元"(Dying ReLU)——如果权重更新导致某个神经元的输出恒为负,该神经元梯度永远为0,再也无法恢复。这在高学习率或不合理的权重初始化时尤其容易发生。Leaky ReLU、PReLU等变体正是为了解决这个问题。
五、Swish 与 GELU:新一代激活函数
是什么(定义):Swish(由Google Brain于2017年提出)定义为 f(x) = x · σ(βx),其中σ是Sigmoid函数,β是可学习的参数(或固定为1)。GELU(Gaussian Error Linear Unit,高斯误差线性单元)定义为 f(x) = x · Φ(x),其中Φ(x)是标准正态分布的累积分布函数。两者都采用了"自门控"(self-gating)机制——输入x既作为信号又控制自己的通过程度。
大白话 Swish和GELU都是"聪明的ReLU"——它们不粗暴地把负数全砍掉,而是根据输入的大小"平滑地决定"该放行多少。就像一个有经验的审核员,不会简单地"通过"或"拒绝",而是根据情况给出一个柔和的评分。
怎么做(实现):
import numpy as np
# ========================================
# Swish 和 GELU —— 新一代自门控激活函数
# 在 Transformer 等现代架构中表现优异
# ========================================
def swish(x, beta=1.0):
"""
Swish 激活函数: f(x) = x * σ(βx)
其中 σ 是 Sigmoid 函数,β 是缩放参数
参数:
x: 输入值
beta: 可选缩放参数(默认1.0),控制门控的"软硬"程度
性质:
- 当 β→0 时,Swish → 线性函数 x/2
- 当 β→∞ 时,Swish → ReLU
- 平滑可导,无死区
"""
return x * (1.0 / (1.0 + np.exp(-beta * x)))
def gelu(x):
"""
GELU 激活函数(精确版): f(x) = x * Φ(x)
其中 Φ(x) 是标准正态分布的累积分布函数(CDF)
实际中常用近似公式以提高计算效率
参数:
x: 输入值
性质:
- 比 Swish 更加平滑
- 在 Transformer(BERT、GPT)中广泛使用
- 期望激活率约为 50%
"""
# 精确版:x * Φ(x),其中 Φ(x) = 0.5 * (1 + erf(x/√2))
# erf 是误差函数
return 0.5 * x * (1.0 + np.tanh(
np.sqrt(2.0 / np.pi) * (x + 0.044715 * x ** 3)
))
def gelu_approx(x):
"""
GELU 近似公式(常用,更快)
GELU(x) ≈ 0.5 * x * (1 + tanh(√(2/π) * (x + 0.044715 * x³)))
"""
sqrt_2_over_pi = np.sqrt(2.0 / np.pi)
return 0.5 * x * (1.0 + np.tanh(sqrt_2_over_pi * (x + 0.044715 * x ** 3)))
# --- 四种激活函数对比 ---
print("ReLU vs Leaky ReLU vs Swish vs GELU 对比:")
test_vals = np.array([-3.0, -1.0, -0.1, 0.0, 0.1, 1.0, 3.0])
for x_val in test_vals:
r = np.maximum(0, x_val) # ReLU
lr = np.where(x_val > 0, x_val, 0.01 * x_val) # Leaky ReLU
sw = x_val / (1.0 + np.exp(-x_val)) # Swish(β=1)
gl = 0.5 * x_val * (1.0 + np.tanh( # GELU
np.sqrt(2.0/np.pi) * (x_val + 0.044715 * x_val**3)))
print(f" x={x_val:+.1f}: ReLU={r:+.4f}, LReLU={lr:+.4f}, Swish={sw:+.4f}, GELU={gl:+.4f}")
# --- Swish 的 β 参数效应 ---
print("\nSwish 的 β 参数效应:")
x_test = np.array([-2.0, -0.5, 0.0, 0.5, 2.0])
for beta in [0.1, 1.0, 10.0]:
print(f" β={beta:.1f}: ", end="")
for x_val in x_test:
out = x_val / (1.0 + np.exp(-beta * x_val))
print(f"{out:+.4f} ", end="")
print()
# --- 可视化对比:输出值的平滑性 ---
print("\n负值区域的平滑性对比(Refined对比):")
fine_neg = np.array([-2.0, -1.5, -1.0, -0.5, -0.1, -0.01])
for x_val in fine_neg:
r = np.maximum(0, x_val)
sw = x_val / (1.0 + np.exp(-x_val))
gl = gelu_approx(x_val)
print(f" x={x_val:+.2f}: ReLU={r:.5f}(硬截断), Swish={sw:.5f}(平滑), GELU={gl:.5f}(平滑)")
大白话 Swish = x · Sigmoid(x),可以看作ReLU的"软化版"——负值不会被粗暴地砍为0,而是逐渐趋近于0。GELU更进一步,用正态分布的累积概率来门控,比Swish还要平滑。两者的共同思想是"让数据自己决定该通过多少"。
什么用(AI关联):Swish在EfficientNet等现代CNN中表现出色。GELU是目前Transformer架构的标准激活函数——BERT、GPT系列、ViT等都使用GELU。选择GELU的核心原因是它在保持非线性的同时,比ReLU的梯度传播更加平滑,这对基于自注意力的架构尤为重要。
哪些坑(缺点):两者计算开销大于ReLU(需要指数/tanh运算),在推理阶段可能成为瓶颈。GELU的精确计算需要误差函数erf,实践中都用近似公式。另外,这些新激活函数主要在大模型和深层网络中才有明显优势,小网络上ReLU通常就够用了。
六、激活函数的选择策略
是什么(定义):激活函数选择是在特定任务和网络架构下,根据数学特性和实践经验做出决策的过程。没有一种激活函数在所有场景下都是最优的,需要根据网络深度、任务类型和计算资源权衡。
大白话 选激活函数就像选工具——不同的活需要不同的工具。ReLU是瑞士军刀(万能但不够精细),GELU是精密仪器(效果好但贵),Sigmoid是专用工具(只适合做概率输出)。
| 激活函数 | 输出范围 | 适用场景 | 主要优势 | 主要劣势 |
|---|---|---|---|---|
| Sigmoid | (0, 1) | 二分类输出层、门控机制 | 输出可解释为概率 | 梯度消失、非零均值 |
| Tanh | (-1, 1) | RNN隐藏状态 | 零均值、梯度比Sigmoid大 | 仍有饱和问题 |
| ReLU | [0, +∞) | CNN/MLP隐藏层(默认) | 无饱和、计算快、稀疏激活 | 死神经元 |
| Leaky ReLU | (-∞, +∞) | 替代ReLU防死亡 | 解决死神经元问题 | 额外超参数α |
| Swish | (-∞, +∞) | EfficientNet等现代CNN | 平滑、自门控、无死区 | 计算量较大 |
| GELU | (-∞, +∞) | Transformer(BERT/GPT) | 最平滑、与Dropout配合好 | 计算量最大 |
概念关系图谱
| 概念 | 核心含义 | 与AI的关系 | 关联概念 |
|---|---|---|---|
| 非线性 | 激活函数引入的非直线关系,使网络能拟合复杂函数 | 没有非线性就没有深度学习 | 万能近似定理、复合函数 |
| 梯度饱和 | 激活函数导数趋近于0的现象,阻碍反向传播 | 导致深层网络训练困难 | 梯度消失、Sigmoid饱和区 |
| 死神经元 | ReLU神经元输出恒为0,永远无法更新 | 降低模型容量,影响性能 | Leaky ReLU、PReLU |
| 自门控 | 输入信号同时控制自身通过程度 | Swish和GELU的核心机制 | 门控网络、LSTM门控 |
| 零均值输出 | 激活函数输出以0为中心 | 加速收敛,避免zigzag优化 | 批归一化、Tanh |
| Softmax | 多分类输出层专用激活函数 | 将输出转换为概率分布 | 交叉熵损失、多分类 |
重点答疑
Q1: 为什么ReLU比Sigmoid在深层网络中效果好那么多?
ReLU在深层网络中占据主导地位主要有三个原因:①梯度流通性——正半轴梯度恒为1,反向传播时梯度可以无衰减地穿过数十层,而Sigmoid每传一层梯度至少衰减到原来的25%(最理想情况),实际中衰减更严重。②计算效率——max(0,x)只需一次比较操作,而Sigmoid需要指数运算和除法。③稀疏激活——负半轴输出为0,网络中的神经元平均只有约50%被激活,这种稀疏性带来了类似Dropout的正则化效果,同时计算量也更小。
大白话 把深层网络想象成传话游戏:Sigmoid每传一个人声音就小一圈,传完20个人基本没声了。ReLU则是传正的话原封不动,传负的话自动闭嘴——至少好消息能传到终点。
Q2: GELU和Swish看起来差不多,为什么Transformer选GELU?
两者确实非常相似——都是"x乘以某个门控值"的形式。但GELU的门控是标准正态分布的累积分布函数Φ(x),而Swish的门控是Sigmoid。Φ(x)的尾部比Sigmoid更"重"(即负值区的输出比Sigmoid稍大),这意味着GELU对负值的处理更平滑、梯度衰减更渐进。在Transformer中,自注意力机制对梯度的平滑性要求更高(因为注意力权重涉及大量的softmax和乘法),GELU的平滑性带来了更稳定的训练过程。
Q3: 激活函数和损失函数有什么关系?可以随便搭配吗?
不能随便搭配。激活函数和损失函数的搭配是神经网络设计中的关键决策:①Sigmoid输出层 + 交叉熵损失——这不是随意搭配,而是有深层原因的。交叉熵损失的导数会抵消Sigmoid的导数中的σ(1-σ)因子,最终得到一个简洁的梯度形式(y_pred - y_true),从而完美避免输出层Sigmoid饱和导致的梯度消失。②Softmax + 交叉熵——多分类的黄金组合,同理导数得到简洁形式。③MSE + Sigmoid输出层——不推荐,因为MSE的导数中保留了Sigmoid的饱和因子,容易产生梯度消失。
大白话 Sigmoid配交叉熵是一对"天生一对"——交叉熵的数学形式恰好能把Sigmoid导数里的"减速因子"给消掉。如果硬把Sigmoid配MSE,就像跑车配了牛车轮胎,快不起来。
章节单词汇总
| 英文 | 音标 | 术语/释义 |
|---|---|---|
| Activation Function | /ˌæktɪˈveɪʃən ˈfʌŋkʃən/ | 激活函数,引入非线性的函数 |
| Sigmoid | /ˈsɪɡmɔɪd/ | S型激活函数,输出(0,1)之间 |
| Tanh | /tænʃ/ | 双曲正切激活函数,输出(-1,1)之间 |
| ReLU | /ˈrɛluː/ | 修正线性单元,max(0,x) |
| Leaky ReLU | /ˈliːki ˈrɛluː/ | 带泄漏的ReLU,负半轴有小斜率 |
| Swish | /swɪʃ/ | 自门控激活函数,x·σ(x) |
| GELU | /ˈdʒiːluː/ | 高斯误差线性单元,用于Transformer |
| Gradient Saturation | /ˈɡreɪdiənt ˌsætʃəˈreɪʃən/ | 梯度饱和,导数趋近于零 |
| Dying ReLU | /ˈdaɪɪŋ ˈrɛluː/ | 死神经元,ReLU输出恒为0 |
| Self-gating | /sɛlf ˈɡeɪtɪŋ/ | 自门控,输入信号控制自身通过 |
| Universal Approximation | /ˌjuːnɪˈvɜːrsəl əˌprɒksɪˈmeɪʃən/ | 万能近似定理,网络可逼近任意函数 |
| Zero-centered | /ˈzɪroʊ ˈsɛntərd/ | 零均值,输出以0为中心 |
面试练习
Q1 [单选] 以下关于激活函数的说法,哪项是正确的?
- A. 激活函数的作用是加快计算速度
- B. 如果没有激活函数,多层网络等价于单层线性变换
- C. Sigmoid是深层网络的首选激活函数
- D. 激活函数必须在每层都不同
解答:激活函数的核心作用是引入非线性。没有激活函数时,多层线性变换的复合仍然是线性的,等价于单层。
Q2 [单选] ReLU函数的导数在x>0时的值是多少?
- A. 恒为1
- B. 随x增大而减小
- C. 等于x
- D. 恒为0.25
解答:ReLU在正半轴f(x)=x,导数f'(x)=1,恒定不变。这是ReLU避免梯度消失的关键。
Q3 [多选] 以下哪些是Sigmoid函数的缺点?
- A. 当|x|较大时梯度趋近于0
- B. 输出不是零均值的
- C. 计算速度比ReLU快
- D. 涉及指数运算,计算开销较大
解答:Sigmoid在饱和区梯度消失(A对),输出均值约0.5非零均值(B对),计算涉及exp相对较慢(D对)。ReLU计算比Sigmoid更快。
Q4 [单选] 什么是"Dying ReLU"问题?
- A. ReLU函数输出太大导致溢出
- B. 神经元对任何输入都输出0,梯度永远为0
- C. ReLU函数计算速度变慢
- D. ReLU导致网络过拟合
解答:当权重更新使神经元对所有输入都产生非正值时,ReLU输出恒为0,梯度也为0,该神经元再也无法更新,称为"死亡"。
Q5 [单选] 在Transformer(如BERT)中,通常使用哪种激活函数?
- A. Sigmoid
- B. ReLU
- C. GELU
- D. Tanh
解答:GELU是Transformer架构的标准激活函数,BERT、GPT、ViT等都使用GELU。
Q6 [多选] 以下关于Leaky ReLU的说法,哪些是正确的?
- A. 在负半轴有一个固定的小斜率,如0.01
- B. 可以缓解Dying ReLU问题
- C. 负半轴的输出和ReLU完全相同
- D. 它比ReLU计算更简单
解答:Leaky ReLU在x<0时输出αx(α为小正数如0.01),给负值区一个非零梯度,避免神经元完全死亡。它略微增加了计算复杂度(需要乘法)。
Q7 [单选] Swish激活函数的表达式是?
- A. f(x) = x · σ(x)
- B. f(x) = max(0, x)
- C. f(x) = tanh(x)
- D. f(x) = x · tanh(x)
解答:Swish定义为f(x)=x·σ(x),其中σ是Sigmoid函数。这是一种自门控机制。
Q8 [多选] 以下哪些激活函数具有"自门控"特性?
- A. Swish
- B. GELU
- C. ReLU
- D. Tanh
解答:Swish(x·σ(x))和GELU(x·Φ(x))都是输入x乘以自身的门控值,属于自门控激活函数。ReLU和Tanh不是。
Q9 [单选] 在二分类问题的输出层,最常使用哪种激活函数?
- A. Sigmoid
- B. ReLU
- C. Tanh
- D. Softmax
解答:Sigmoid输出(0,1)之间,可直接解释为正类的概率,是二分类输出层的标准选择。Softmax用于多分类。
Q10 [单选] 激活函数tanh(x)与sigmoid(x)的数学关系是什么?
- A. tanh(x) = sigmoid(x) + 1
- B. tanh(x) = sigmoid(x) - 1
- C. tanh(x) = 2·sigmoid(2x) - 1
- D. tanh(x) = sigmoid(x/2)
解答:tanh(x) = (e^x-e^{-x})/(e^x+e^{-x}) = 2/(1+e^{-2x}) - 1 = 2σ(2x) - 1。