文章目录
-
- [📚 核心逻辑:用非线性激活与反向传播实现复杂分类](#📚 核心逻辑:用非线性激活与反向传播实现复杂分类)
- 一、算法设计:前向传播与反向传播
-
- [1.1 前向传播设计](#1.1 前向传播设计)
- [1.2 损失函数设计](#1.2 损失函数设计)
- [1.3 反向传播设计](#1.3 反向传播设计)
- 二、训练机制:SGD与超参数调优
-
- [2.1 随机梯度下降(SGD)](#2.1 随机梯度下降(SGD))
- [2.2 超参数调优](#2.2 超参数调优)
- 三、关键参数与效果
-
- [3.1 关键参数](#3.1 关键参数)
- [3.2 效果分析](#3.2 效果分析)
- [📖 核心概念](#📖 核心概念)
本文聚焦两层全连接神经网络的核心设计思路和算法原理,解释代码背后的设计原因和数学基础。
📚 核心逻辑:用非线性激活与反向传播实现复杂分类
图像分类需要学习分类规则。线性分类器(SVM 37-39%,Softmax 33.8%)只能学习线性决策边界 ,准确率有限。神经网络通过ReLU激活引入非线性,能够学习非线性决策边界,准确率显著提升(48-52%)。这是本文的核心结论。
1.为什么需要神经网络?
线性分类器的局限在于只能学习线性决策边界。对于复杂的图像分类任务,数据往往不是线性可分的,需要非线性模型。神经网络通过ReLU激活函数引入非线性变换,使模型能够学习更复杂的特征组合和决策边界。
2.解决神经网络的两个关键问题:
问题1:梯度计算复杂 。神经网络有多层参数( W 1 , b 1 , W 2 , b 2 W_1, b_1, W_2, b_2 W1,b1,W2,b2),需要计算每层参数的梯度。如果手动推导每层的梯度公式,计算量大且容易出错。如何高效准确地计算所有参数的梯度?
问题2:超参数难选。神经网络有更多超参数(隐藏层大小、学习率、正则化强度),每个超参数的选择都影响模型性能。如何选择最优的超参数组合?
解决方案:采用反向传播算法和验证集调优的双重策略。
解决方案1:反向传播算法。通过链式法则从输出层向输入层逐层计算梯度,一次前向传播和一次反向传播就能计算所有参数的梯度,高效且准确。这解决了梯度计算复杂的问题。
解决方案2:验证集调优。通过网格搜索在验证集上搜索最优超参数组合(隐藏层大小、学习率、正则化强度),避免过拟合测试集,确保选择的超参数能够泛化到新数据。这解决了超参数难选的问题。
3.神经网络还需要两个核心机制:
核心机制1:ReLU激活引入非线性 。ReLU激活通过 max ( 0 , x ) \max(0, x) max(0,x)引入非线性,使模型能够学习非线性决策边界。这是神经网络相比线性分类器的关键优势,也是准确率提升的根本原因。
核心机制2:SGD高效优化。SGD通过随机采样batch计算梯度,比全批量梯度下降快,适合大规模数据。这使得训练过程高效,能够快速迭代和调优。
最终效果如何? 在CIFAR-10数据集上,默认参数(hidden_size=50, learning_rate=1e-4, reg=0.25, num_iters=1000)下验证集准确率为28.7%,说明模型容量不足。通过超参数调优(增加隐藏层大小到300-500,调整学习率和正则化强度,增加迭代次数到3000),预期可以达到48-52%的分类准确率,虽然不如深度学习方法(通常>90%),但相比线性分类器(SVM 37-39%,Softmax 33.8%)有显著提升,证明了非线性模型的优势。
核心逻辑链条:
任务(图像分类)→ 方法选择(神经网络非线性模型)→ 问题转化(多层变换优化)→ 关键问题(梯度计算复杂+超参数难选)→ 解决方案(反向传播+验证集调优)→ 核心机制(高效梯度计算+最优选择+非线性激活+优化方法)→ 最终效果(快速训练+较高准确率)
一、算法设计:前向传播与反向传播
基于核心逻辑,算法设计需要实现前向传播(计算得分)和反向传播(计算梯度)。下面分别说明设计思路。
1.1 前向传播设计
目标:计算所有样本的类别得分。
数学公式 :
第一层 z 1 = X ⋅ W 1 + b 1 z_1 = X \cdot W_1 + b_1 z1=X⋅W1+b1, a 1 = ReLU ( z 1 ) = max ( 0 , z 1 ) a_1 = \text{ReLU}(z_1) = \max(0, z_1) a1=ReLU(z1)=max(0,z1);
第二层 s c o r e s = a 1 ⋅ W 2 + b 2 scores = a_1 \cdot W_2 + b_2 scores=a1⋅W2+b2。
设计原因:全连接层学习特征组合,ReLU激活引入非线性(这是神经网络的关键优势),第二层将隐藏层特征映射到类别得分。
实现代码:
python
# First layer: fully connected + ReLU
z1 = X.dot(W1) + b1 # (N, H)
a1 = np.maximum(0, z1) # ReLU: (N, H)
# Second layer: fully connected
scores = a1.dot(W2) + b2 # (N, C)
关键点 :前向传播时保存中间结果( z 1 , a 1 z_1, a_1 z1,a1),供反向传播复用,提高效率。
1.2 损失函数设计
目标:衡量预测与真实分布的差异,并防止过拟合。
数学公式 : L = 1 N ∑ i ( − log ( p y i ) ) + λ ( ∑ W 1 , i j 2 + ∑ W 2 , i j 2 ) L = \frac{1}{N}\sum_i \left(-\log(p_{y_i})\right) + \lambda \left(\sum W_{1,ij}^2 + \sum W_{2,ij}^2\right) L=N1∑i(−log(pyi))+λ(∑W1,ij2+∑W2,ij2),其中 p y i = e s y i ∑ j e s j p_{y_i} = \frac{e^{s_{y_i}}}{\sum_j e^{s_j}} pyi=∑jesjesyi是softmax概率。
设计原因:交叉熵损失衡量预测与真实分布差异,L2正则化防止权重大大(这是验证集调优的基础),计算softmax时减去最大值保证数值稳定。
1.3 反向传播设计
目标:高效计算所有参数的梯度(这是解决梯度计算复杂问题的关键)。
梯度计算 (链式法则):
Softmax损失梯度 ∂ L ∂ s c o r e s = p − 1 y i \frac{\partial L}{\partial scores} = p - \mathbf{1}_{y_i} ∂scores∂L=p−1yi;
第二层 ∂ L ∂ W 2 = a 1 T ⋅ ∂ L ∂ s c o r e s + 2 λ W 2 \frac{\partial L}{\partial W_2} = a_1^T \cdot \frac{\partial L}{\partial scores} + 2\lambda W_2 ∂W2∂L=a1T⋅∂scores∂L+2λW2, ∂ L ∂ b 2 = ∑ i = 1 N ∂ L ∂ s c o r e s i \frac{\partial L}{\partial b_2} = \sum_{i=1}^N \frac{\partial L}{\partial scores_i} ∂b2∂L=∑i=1N∂scoresi∂L;
ReLU梯度 ∂ a 1 ∂ z 1 = 1 z 1 > 0 \frac{\partial a_1}{\partial z_1} = \mathbf{1}_{z_1 > 0} ∂z1∂a1=1z1>0;
第一层 ∂ L ∂ W 1 = X T ⋅ ∂ L ∂ z 1 + 2 λ W 1 \frac{\partial L}{\partial W_1} = X^T \cdot \frac{\partial L}{\partial z_1} + 2\lambda W_1 ∂W1∂L=XT⋅∂z1∂L+2λW1, ∂ L ∂ b 1 = ∑ i = 1 N ∂ L ∂ z 1 , i \frac{\partial L}{\partial b_1} = \sum_{i=1}^N \frac{\partial L}{\partial z_{1,i}} ∂b1∂L=∑i=1N∂z1,i∂L。
设计原因:链式法则逐层计算梯度(一次前向+反向传播计算所有参数梯度,高效准确),ReLU梯度简单(正区域1,负区域0),矩阵运算批量计算提高效率。
实现代码:
python
# Gradient from softmax loss
dscores = probs.copy()
dscores[np.arange(N), y] -= 1
dscores /= N
# Backprop through second layer
grads['W2'] = a1.T.dot(dscores) + 2 * reg * W2
grads['b2'] = np.sum(dscores, axis=0)
# Backprop through ReLU
da1 = dscores.dot(W2.T)
dz1 = da1.copy()
dz1[z1 <= 0] = 0 # ReLU gradient
# Backprop through first layer
grads['W1'] = X.T.dot(dz1) + 2 * reg * W1
grads['b1'] = np.sum(dz1, axis=0)
关键点 :向量化矩阵运算代替循环,缓存中间结果( z 1 , a 1 z_1, a_1 z1,a1)供反向传播复用,偏置梯度累加所有样本。
二、训练机制:SGD与超参数调优
基于核心逻辑,训练机制需要实现SGD高效优化和验证集调优。下面分别说明设计思路。
2.1 随机梯度下降(SGD)
目标:高效优化损失函数(这是SGD高效优化的核心机制)。
实现逻辑:随机采样batch,计算损失和梯度,更新权重,每个epoch衰减学习率。
设计原因 :batch梯度计算比全批量快(适合大规模数据),随机采样跳出局部最优,学习率衰减后期精细优化。
实现代码:
python
for it in range(num_iters):
# 随机采样batch
batch_indices = np.random.choice(num_train, batch_size, replace=True)
X_batch = X[batch_indices]
y_batch = y[batch_indices]
# 计算损失和梯度
loss, grads = self.loss(X_batch, y=y_batch, reg=reg)
# 更新权重
self.params['W1'] -= learning_rate * grads['W1']
self.params['b1'] -= learning_rate * grads['b1']
self.params['W2'] -= learning_rate * grads['W2']
self.params['b2'] -= learning_rate * grads['b2']
# 每个epoch衰减学习率
if it % iterations_per_epoch == 0:
learning_rate *= learning_rate_decay
2.2 超参数调优
目标:选择最优超参数组合(这是验证集调优的核心机制)。
调优策略:网格搜索在验证集上搜索最优超参数组合(隐藏层大小、学习率、正则化强度),保存最佳模型。验证集评估避免过拟合测试集(确保选择的超参数能够泛化到新数据)。
实现代码:
python
best_val_acc = -1
best_net = None
for hidden_size in hidden_sizes:
for lr in learning_rates:
for reg in regularization_strengths:
# 创建网络
net = TwoLayerNet(input_size, hidden_size, num_classes)
# 训练
stats = net.train(X_train, y_train, X_val, y_val,
num_iters=3000, batch_size=200,
learning_rate=lr, learning_rate_decay=0.95,
reg=reg, verbose=False)
# 评估
val_acc = (net.predict(X_val) == y_val).mean()
# 更新最佳模型
if val_acc > best_val_acc:
best_val_acc = val_acc
best_net = net
三、关键参数与效果
基于核心逻辑和训练机制,关键参数的选择直接影响最终效果。下面说明各参数的作用和影响。
3.1 关键参数
隐藏层大小 :控制模型容量,决定网络的表达能力。太小(100)欠拟合,太大(500)易过拟合需强正则化,合适(300)平衡表达和泛化。典型值:300-500。
学习率 :控制更新步长。太大不稳定,太小训练慢,合适快速收敛。典型值:5e-4到1e-4(配合衰减)。
正则化强度 :防止过拟合。太小过拟合,太大欠拟合,合适平衡。典型值:0.1到0.25。
学习率衰减率 :每个epoch衰减因子。太大(0.9)过早停止,太小(0.99)不稳定,合适(0.95)平衡。典型值:0.95。
3.2 效果分析
默认参数效果:hidden_size=50时验证集准确率28.7%,模型容量不足,说明需要调优。
调优后效果:通过超参数调优(隐藏层300-500,迭代3000次),预期达到48-52%,相比线性分类器(SVM 37-39%,Softmax 33.8%)显著提升,证明非线性模型优势。
📖 核心概念
两层全连接神经网络:非线性分类器,通过多层变换实现分类。架构:输入 → 全连接层1 → ReLU → 全连接层2 → Softmax损失。
ReLU激活函数 : ReLU ( x ) = max ( 0 , x ) \text{ReLU}(x) = \max(0, x) ReLU(x)=max(0,x),引入非线性,使模型能够学习非线性决策边界。
反向传播(Backpropagation):使用链式法则计算梯度,从输出层向输入层逐层传播误差。
随机梯度下降(SGD):每次迭代随机采样batch计算梯度,比全批量梯度下降快,适合大规模数据。
正则化 : R ( W ) = λ ( ∑ W 1 , i j 2 + ∑ W 2 , i j 2 ) R(W) = \lambda (\sum W_{1,ij}^2 + \sum W_{2,ij}^2) R(W)=λ(∑W1,ij2+∑W2,ij2),防止过拟合,限制模型复杂度。