神经网络的核心思想源自对人类大脑工作方式的简化模拟。生物神经元通过突触接收信号,当输入信号超过某个阈值时,神经元会被激活并向下游神经元传递电信号。人工神经网络(ANN)将这一过程抽象为数学运算:
关键区别:生物神经元使用电化学信号和复杂的时空编码,而人工神经元仅进行矩阵乘法和非线性变换。这种简化使得计算可以在现代硬件上高效执行。
现代神经网络通常采用全连接结构,即每一层的每个神经元都与下一层的所有神经元相连。这种结构虽然计算量大,但具有强大的表示能力。以三层网络为例,其数学表达为:
code复制输出 = f3(W3·f2(W2·f1(W1·输入 + b1) + b2) + b3)
其中W为权重矩阵,b为偏置项,f为激活函数。这种层级结构使网络能够学习输入数据的层次化特征表示。
激活函数是神经网络引入非线性的关键组件,常见类型包括:
| 函数类型 | 公式 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
| Sigmoid | 1/(1+e^-x) | 输出平滑(0,1) | 梯度消失问题 | 二分类输出层 |
| Tanh | (e^x-e^-x)/(e^x+e^-x) | 输出(-1,1) | 梯度消失 | 隐藏层 |
| ReLU | max(0,x) | 计算简单 | 神经元死亡 | 大多数隐藏层 |
| LeakyReLU | max(0.01x,x) | 缓解死亡问题 | 超参数需调 | 深层网络 |
| Softmax | e^x/∑e^x | 输出概率分布 | 计算量大 | 多分类输出层 |
在实际应用中,ReLU及其变种(LReLU,PReLU)已成为隐藏层的默认选择,主要因为:
设计神经网络架构时需要考虑以下关键因素:
层数与宽度:
参数初始化:
正则化技术:
实用建议:从简单架构开始,逐步增加复杂度。使用验证集评估性能提升是否值得增加的模型复杂度。
垃圾邮件检测是典型的二分类问题。我们需要构建包含以下特征的数据集:
文本特征提取:
数据标准化:
python复制# 标准化示例
mean = np.mean(X_train, axis=0)
std = np.std(X_train, axis=0)
X_train = (X_train - mean) / std
X_test = (X_test - mean) / std # 使用训练集统计量
以下是一个完整的三层神经网络实现:
python复制import numpy as np
class NeuralNetwork:
def __init__(self, layer_sizes):
self.weights = []
self.biases = []
for i in range(len(layer_sizes)-1):
# He初始化
w = np.random.randn(layer_sizes[i], layer_sizes[i+1]) * np.sqrt(2./layer_sizes[i])
b = np.zeros((1, layer_sizes[i+1]))
self.weights.append(w)
self.biases.append(b)
def relu(self, x):
return np.maximum(0, x)
def sigmoid(self, x):
return 1 / (1 + np.exp(-np.clip(x, -250, 250)))
def forward(self, X):
self.activations = [X]
self.z_values = []
current = X
for W, b in zip(self.weights, self.biases):
z = np.dot(current, W) + b
self.z_values.append(z)
if W is self.weights[-1]: # 输出层用sigmoid
current = self.sigmoid(z)
else: # 隐藏层用ReLU
current = self.relu(z)
self.activations.append(current)
return current
def backward(self, X, y, learning_rate=0.01):
m = X.shape[0]
dW = [np.zeros_like(w) for w in self.weights]
db = [np.zeros_like(b) for b in self.biases]
# 输出层梯度
error = self.activations[-1] - y
dW[-1] = np.dot(self.activations[-2].T, error) / m
db[-1] = np.sum(error, axis=0, keepdims=True) / m
# 隐藏层梯度
for l in range(len(self.weights)-2, -1, -1):
error = np.dot(error, self.weights[l+1].T) * (self.z_values[l] > 0)
dW[l] = np.dot(self.activations[l].T, error) / m
db[l] = np.sum(error, axis=0, keepdims=True) / m
# 参数更新
for l in range(len(self.weights)):
self.weights[l] -= learning_rate * dW[l]
self.biases[l] -= learning_rate * db[l]
使用10,000个邮件样本训练网络,典型训练曲线如下:
| Epoch | 训练集准确率 | 验证集准确率 | 损失值 |
|---|---|---|---|
| 0 | 52.3% | 50.8% | 0.693 |
| 100 | 78.6% | 76.2% | 0.452 |
| 300 | 92.1% | 89.7% | 0.218 |
| 500 | 95.4% | 92.8% | 0.132 |
| 1000 | 97.2% | 94.3% | 0.087 |
关键观察:
识别方法:
解决方案:
python复制# Dropout实现示例
def forward_with_dropout(self, X, keep_prob=0.5):
self.masks = []
current = X
for i, (W, b) in enumerate(zip(self.weights, self.biases)):
z = np.dot(current, W) + b
if i < len(self.weights)-1: # 不在输出层应用
mask = (np.random.rand(*z.shape) < keep_prob) / keep_prob
self.masks.append(mask)
z = z * mask
current = self.relu(z) if i < len(self.weights)-1 else self.sigmoid(z)
return current
现象:
解决方案:
关键超参数及其典型范围:
| 参数 | 搜索范围 | 调整策略 |
|---|---|---|
| 学习率 | 1e-5到1e-1 | 对数尺度采样 |
| 批大小 | 16-256 | 根据内存选择最大可能值 |
| 层数 | 1-5 | 从简单开始逐步增加 |
| 每层神经元数 | 32-512 | 通常2的幂次方 |
| Dropout率 | 0.2-0.5 | 深层网络用更高值 |
实用调优方法:
卷积神经网络(CNN)通过以下特性优化图像处理:
典型CNN架构:
code复制输入 → [[卷积→激活→池化]×N] → 全连接 → 输出
循环神经网络适合处理时序数据,其变种包括:
现代架构如Transformer完全基于注意力机制:
这些创新使模型能够更灵活地处理长距离依赖和复杂关系。