共计 1411 个字符,预计需要花费 4 分钟才能阅读完成。
1. 从 UCI 数据集看 BP 神经网络应用
以经典的 Iris 鸢尾花数据集为例,我们需要根据花瓣长度、宽度等特征预测花的种类。这个三分类问题非常适合演示 BP 神经网络:
% 加载数据
data = readtable('iris.csv');
X = table2array(data(:,1:4))'; % 转置为 4×150 矩阵
y = grp2idx(data.species); % 类别转数字标签
2. 数据预处理:标准化之战
Min-Max 标准化(归一化到 [0,1])
X_minmax = (X - min(X,[],2)) ./ (max(X,[],2) - min(X,[],2));
Z-score 标准化(均值 0 方差 1)
X_zscore = (X - mean(X,2)) ./ std(X,0,2);
实际项目中建议优先使用 Z -score,特别是存在异常值时。
3. 网络结构设计:隐藏层的秘密
根据 Kolmogorov 定理,隐藏层节点数 $n_h$ 应满足:
$$ n_h = 2n_i + 1 $$
其中 $n_i$ 是输入特征数。对于 Iris 数据集:
inputSize = 4; % 4 个特征
hiddenSize = 9; % 2*4+1=9
outputSize = 3; % 3 个类别
4. 核心代码实现
前向传播矩阵运算
function [a2, a3] = forwardProp(X, W1, W2, b1, b2)
z2 = W1*X + b1; % 隐藏层加权输入
a2 = tanh(z2); % 激活函数
z3 = W2*a2 + b2; % 输出层加权输入
a3 = softmax(z3); % 多分类输出
end
反向传播梯度计算
delta3 = a3 - y_onehot; % 输出层误差
delta2 = (W2' * delta3) .* (1 - a2.^2); % tanh 导数 =1-a^2
gradW2 = delta3 * a2'; % 权重梯度
gradW1 = delta2 * X';
5. 性能优化实战
优化器对比(traingdx vs trainlm)
% 创建网络时指定训练函数
net = feedforwardnet(hiddenSize, 'traingdx'); % 梯度下降
net = feedforwardnet(hiddenSize, 'trainlm'); % Levenberg-Marquardt

早停法实现
net.divideFcn = 'divideblock'; % 按顺序划分数据
net.divideParam.trainRatio = 0.7;
net.divideParam.valRatio = 0.15;
net.trainParam.max_fail = 10; % 验证集误差连续上升次数
6. 避坑指南
梯度爆炸解决方案
将 log-sigmoid 替换为 ReLU:
net.layers{1}.transferFcn = 'poslin'; % ReLU 函数
类别不平衡处理
修改损失函数实现代价敏感学习:
classWeights = [1, 2, 1.5]; % 给少数类更高权重
net.performParam.regularization = 0.1;
7. 扩展挑战:Fashion-MNIST
尝试将当前模型迁移到 Fashion-MNIST 数据集(28×28 灰度图像分类):
- 修改输入层节点数为 784
- 添加第二个隐藏层(建议 128 节点)
- 使用卷积层替换全连接层(进阶)
完整代码已上传 GitHub 仓库,包含数据集和预训练模型。通过这个实战流程,我们不仅提升了模型准确率,更重要的是掌握了 BP 神经网络工程化的完整方法论。建议读者尝试调整网络深度、更换优化器,观察模型性能的变化规律。
正文完
