2. 神经网络基础:感知机模型、激活函数、前向传播与反向传播
各位同学,咱们今天聊聊神经网络的基础。说实话,这部分内容我每年讲都会有些新感悟。你想想看,整个深度学习大厦,就是靠这几块砖头垒起来的。我当年刚入行时,总觉得这些基础太简单,结果在项目里栽了不少跟头。嗯,咱们还是老老实实把地基打牢。
2.1 感知机模型——神经元的鼻祖
感知机,说白了就是模仿人脑神经元的一个简化模型。它接收多个输入,每个输入有个权重,然后把这些加权求和,最后通过一个阈值判断是否激活。
数学上长这样:
y = sign(w₁x₁ + w₂x₂ + ... + wₙxₙ + b)
其中 sign 是符号函数,大于0输出1,小于0输出-1。
我在项目中遇到过这样一个场景:用感知机判断噪声是否超标。输入是分贝值、频率、持续时间三个特征,权重靠人工调。结果呢?调了一整天,准确率不到70%。后来我才明白——感知机只能处理线性可分问题。环境噪声数据哪有那么规整?
核心要点:感知机是线性分类器,只能画一条直线(或超平面)来分割数据。遇到异或问题直接歇菜。
避坑指南:我曾经在噪声源识别项目里硬用感知机,结果模型死活不收敛。后来换成多层网络,问题才解决。记住:单层感知机能力有限,别指望它干太复杂的活。
2.2 激活函数——给网络注入非线性
为什么需要激活函数?你想想看,如果每层都是线性变换,那堆叠再多层也等价于一层。激活函数就是用来打破这种线性关系的。
我常用的三种激活函数,咱们一个一个说。
2.2.1 Sigmoid 函数
公式:σ(x) = 1 / (1 + e⁻ˣ)
输出范围在(0,1)之间。早期神经网络很喜欢用它,因为它能把任意实数映射到概率区间。
但有个致命问题——梯度消失。当x很大或很小时,梯度几乎为0。我在做噪声等级分类时,网络层数一深,Sigmoid 直接让前面几层学不动了。
| 优点 | 缺点 |
|---|---|
| 输出平滑,适合概率输出 | 梯度消失严重 |
| 可导,便于反向传播 | 输出不是零中心,收敛慢 |
| 历史地位高,经典 | 计算指数,开销大 |
2.2.2 Tanh 函数
公式:tanh(x) = (eˣ - e⁻ˣ) / (eˣ + e⁻ˣ)
输出范围在(-1,1)之间。相比 Sigmoid,它是零中心的,收敛速度更快。
我个人习惯在循环神经网络里用 Tanh。记得有一次做噪声时序预测,用 Tanh 比 Sigmoid 快了将近30%的收敛速度。但梯度消失问题依然存在,只是稍微好一点。
2.2.3 ReLU 函数
公式:ReLU(x) = max(0, x)
这玩意儿现在是我的首选。为什么?简单、快、效果好。x大于0时梯度恒为1,梯度消失问题大大缓解。
但要注意——神经元死亡问题。如果某个神经元输出一直为负,那它的梯度永远是0,再也活不过来了。我建议学习率别设太大,可以缓解这个问题。
我的经验:在环境噪声预测这种回归任务里,ReLU 通常比 Sigmoid 和 Tanh 表现好。但如果你做的是分类任务,输出层还是用 Softmax 更合适。
2.3 前向传播——数据从输入到输出
前向传播,说白了就是数据在网络里走一遍。输入层接收数据,经过隐藏层的加权求和和激活函数,最后到输出层给出结果。
咱们用个简单的两层网络来演示:
# 伪代码示例
def forward_propagation(X, W1, b1, W2, b2):
# 第一层:线性变换 + ReLU
Z1 = np.dot(X, W1) + b1
A1 = np.maximum(0, Z1) # ReLU激活
# 第二层:线性变换 + Sigmoid
Z2 = np.dot(A1, W2) + b2
A2 = 1 / (1 + np.exp(-Z2)) # Sigmoid激活
return A2
你看,就这么简单。但实际项目中,我见过有人把前向传播写得特别复杂,各种循环嵌套。其实没必要,用矩阵运算一把梭就行。
下面这张图展示了前向传播的完整流程:
2.4 反向传播——让网络学会东西
前向传播算出了预测值,但和真实值有差距。怎么调整权重让差距变小?这就是反向传播干的事。
核心思想就四个字:链式法则。从输出层开始,逐层计算损失函数对权重的梯度,然后沿着梯度反方向更新权重。
数学推导我就不展开了,咱们直接看代码:
# 反向传播伪代码
def backward_propagation(X, y, A2, W2, A1):
m = X.shape[0] # 样本数
# 输出层梯度
dZ2 = A2 - y # 损失对Z2的梯度
dW2 = np.dot(A1.T, dZ2) / m
db2 = np.sum(dZ2, axis=0, keepdims=True) / m
# 隐藏层梯度(链式法则)
dA1 = np.dot(dZ2, W2.T)
dZ1 = dA1 * (A1 > 0) # ReLU的导数
dW1 = np.dot(X.T, dZ1) / m
db1 = np.sum(dZ1, axis=0, keepdims=True) / m
return dW1, db1, dW2, db2
关键理解:反向传播不是另一个算法,它只是用链式法则高效计算梯度的方法。没有它,深度学习根本跑不起来。
我在做噪声预测模型时,遇到过梯度爆炸的问题。损失直接变成NaN,模型崩了。后来加了梯度裁剪,才稳住。建议你在训练初期监控一下梯度范数,别等炸了再处理。
小技巧:如果你发现模型训练特别慢,可以检查一下梯度是否太小。我习惯在每轮迭代后打印梯度的均值和方差,这样能快速定位问题。
好了,这一章的内容就到这。感知机是起点,激活函数是灵魂,前向传播和反向传播是骨架。把这些搞明白,后面的卷积、循环网络都是锦上添花。