神经网络基础
从感知机到多层神经网络,理解深度学习的基础组件。
感知机
神经网络的基本单元。接收多个输入,加权求和后通过激活函数输出:
import numpy as np
def perceptron(x, w, b):
"""单个感知机"""
z = np.dot(w, x) + b
return 1 if z >= 0 else 0 # 阶跃激活函数
单个感知机只能解决线性可分问题(如 AND、OR),无法处理 XOR。多层感知机解决了这个问题。
多层感知机(MLP)
输入层 → 隐藏层 → 输出层,层间全连接:
class SimpleMLP:
def __init__(self, layer_sizes):
"""
layer_sizes: [输入维度, 隐藏层1维度, ..., 输出维度]
例: [784, 128, 64, 10] — MNIST 的三层网络
"""
self.weights = []
self.biases = []
for i in range(len(layer_sizes) - 1):
# He 初始化(ReLU 的最佳伙伴)
self.weights.append(
np.random.randn(layer_sizes[i], layer_sizes[i+1]) *
np.sqrt(2.0 / layer_sizes[i])
)
self.biases.append(np.zeros((1, layer_sizes[i+1])))
def forward(self, X):
"""前向传播"""
self.z = [] # 激活前的值(反向传播需要)
self.a = [X] # 各层激活后的值
for W, b in zip(self.weights[:-1], self.biases[:-1]):
self.z.append(self.a[-1] @ W + b)
self.a.append(self.relu(self.z[-1])) # 隐藏层用 ReLU
# 输出层
self.z.append(self.a[-1] @ self.weights[-1] + self.biases[-1])
self.a.append(self.softmax(self.z[-1]))
return self.a[-1]
def relu(self, x):
return np.maximum(0, x)
def softmax(self, x):
exp_x = np.exp(x - x.max(axis=1, keepdims=True)) # 数值稳定
return exp_x / exp_x.sum(axis=1, keepdims=True)
激活函数
没有激活函数,多层网络等价于单层线性模型。
| 函数 | 公式 | 特点 |
|---|---|---|
| Sigmoid | 输出 (0,1),两端梯度消失 | |
| Tanh | 输出 (-1,1),零中心 | |
| ReLU | 计算快,缓解梯度消失,首选 | |
| Leaky ReLU | 解决 ReLU 的「神经元死亡」问题 | |
| GELU | Transformer 标配 |
def relu(x):
return np.maximum(0, x)
def leaky_relu(x, alpha=0.01):
return np.where(x > 0, x, alpha * x)
def sigmoid(x):
return 1 / (1 + np.exp(-np.clip(x, -500, 500)))
损失函数
| 任务 | 损失函数 | 公式 |
|---|---|---|
| 二分类 | 二元交叉熵 | |
| 多分类 | 交叉熵 | |
| 回归 | MSE |
反向传播
反向传播的本质是用链式法则从输出层往输入层逐层计算梯度:
def relu_derivative(x):
return (x > 0).astype(float)
def backward(self, X, y, y_pred):
n = len(X)
grads_w = []
grads_b = []
# 输出层梯度: dL/dz = y_pred - y (交叉熵 + softmax 的简洁结果)
delta = y_pred - y
for i in reversed(range(len(self.weights))):
# dL/dW = a.T @ delta / n
grads_w.insert(0, self.a[i].T @ delta / n)
grads_b.insert(0, delta.sum(axis=0, keepdims=True) / n)
if i > 0:
# 链式法则:delta = (delta @ W.T) * relu'(z)
delta = (delta @ self.weights[i].T) * relu_derivative(self.z[i-1])
return grads_w, grads_b
优化器
SGD
# 最基础的优化器
w = w - lr * grad
SGD + Momentum
# 动量累积历史梯度方向,加速收敛
v = momentum * v - lr * grad
w = w + v
Adam(推荐默认使用)
# 结合动量 + 自适应学习率
# PyTorch 中:
# optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
PyTorch 完整示例
import torch
import torch.nn as nn
class SimpleNN(nn.Module):
def __init__(self, input_dim, hidden_dim, output_dim):
super().__init__()
self.net = nn.Sequential(
nn.Linear(input_dim, hidden_dim),
nn.ReLU(),
nn.Linear(hidden_dim, hidden_dim),
nn.ReLU(),
nn.Linear(hidden_dim, output_dim),
)
def forward(self, x):
return self.net(x)
# 训练循环
model = SimpleNN(784, 128, 10)
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
for epoch in range(10):
for X_batch, y_batch in train_loader:
optimizer.zero_grad()
y_pred = model(X_batch)
loss = criterion(y_pred, y_batch)
loss.backward()
optimizer.step()
归一化层
| 类型 | 作用维度 | 使用场景 |
|---|---|---|
| BatchNorm | 一个 batch 内归一化 | CNN 标配 |
| LayerNorm | 一个样本内归一化 | Transformer 标配 |
| Dropout | 随机丢弃神经元 | 正则化、防止过拟合 |
正则化
防止过拟合的常用技巧:
# Dropout
nn.Dropout(p=0.5) # 训练时随机丢失 50% 神经元
# 权重衰减(L2 正则化)
torch.optim.Adam(model.parameters(), lr=0.001, weight_decay=1e-4)
# Early Stopping — 验证损失不再下降时停止训练
# BatchNorm 自带轻微正则化效果
总结
| 特性 | 说明 |
|---|---|
| 要点 | 激活函数、损失函数、梯度下降、反向传播是四大核心 |
| 实践 | ReLU + Adam + BatchNorm + Dropout 是标准组合 |
| 进阶 | 理解梯度流(Gradient Flow)是调试深度学习的关键 |