用 BP 神经网络预测公路运量:从原理到实战全流程
在交通规划与运输企业运营中,精准预测公路客运量和货运量是制定决策的关键。本文以安庆师范大学智能控制基础实验为背景,手把手教你用 BP 神经网络实现公路运量预测,涵盖数据预处理、模型搭建、训练测试到最终预测的全流程,代码可直接复用,新手也能轻松上手。
一、实验背景与目标
1. 问题场景
某地区 1990-2009 年的公路运量数据包含三大影响因素(人数、机动车数量、公路面积)和两大预测目标(客运量、货运量),需基于这些数据构建模型,预测未来年份的运量。
2. 核心目标
- 预测运量:为交通规划、运力调配提供数据支撑;
- 验证模型:测试 BP 神经网络在交通预测场景的适用性;
- 分析因素:明确人数、机动车数量等对运量的影响关系。
二、BP 神经网络预测原理
BP 神经网络(反向传播神经网络)是一种多层前馈网络,核心是通过 “前向传播计算输出、反向传播调整权重” 的迭代过程,最小化预测误差,其在本实验中的应用逻辑如下:
- 数据预处理:对输入(人数、机动车数、公路面积)和输出(客运量、货运量)数据做归一化,消除量纲差异;
- 网络结构:输入层(3 个神经元,对应 3 个影响因素)→隐含层(8 个神经元,通过 logsig 激活函数)→输出层(2 个神经元,对应客运量、货运量);
- 训练过程:设置学习率(0.035)、最大迭代次数(50000)、目标误差(0.00065),通过反向传播不断调整权值和阈值,直到误差收敛;
- 预测应用:用训练好的模型对新数据(2010-2011 年影响因素)做预测,再通过反归一化得到实际运量值。
三、实验数据准备
实验使用 1990-2009 年共 20 组数据,部分关键数据如下(完整数据已嵌入代码):
影响因素 | 数据示例(单位) | 预测目标 | 数据示例(单位) |
---|---|---|---|
人数 | 71.17-78.78(万人) | 公路客运量 | 600-980(万人) |
机动车数量 | 3.4277-6.1796(万辆) | 公路货运量 | 50-88(万吨) |
公路面积 | 0.9376-1.1068(万平方公里) | - | - |
预测数据:2010-2011 年的影响因素(人数、机动车数、公路面积)分别为[73.39,75.55]
、[3.9635,4.0975]
、[0.9880,1.0268]
。
四、完整实验代码(MATLAB 版)
代码包含数据定义、预处理、模型训练、测试与预测全流程,关键步骤已标注注释:
% 1. 初始化参数设置
numberOfSample = 20; % 训练样本数量(1990-2009年)
numberOfTestSample = 20; % 测试样本数量(因样本少,用训练集测试)
numberOfForcastSample = 2; % 预测样本数量(2010-2011年)
numberOfHiddenNeure = 8; % 隐含层神经元数量
inputDimension = 3; % 输入维度(人数、机动车数、公路面积)
outputDimension = 2; % 输出维度(客运量、货运量)% 2. 加载实验数据
% 人数(单位:万人)
numberOfPeople=[71.17 71.71 72.28 72.89 73.34 73.71 74.09 74.45 74.82 75.21 75.62 76.02 76.39 76.74 77.09 77.43 77.77 78.11 78.45 78.78];
% 机动车数(单位:万辆)
numberOfAutomobile=[3.4277 3.5155 3.6077 3.7046 3.8061 3.9122 4.0239 4.1421 4.2665 4.3981 4.5372 4.6844 4.8402 4.9987 5.1664 5.3448 5.5344 5.7357 5.9503 6.1796];
% 公路面积(单位:万平方公里)
roadArea=[0.9376 0.9465 0.9554 0.9643 0.9732 0.9821 0.9910 1.0000 1.0089 1.0178 1.0267 1.0356 1.0445 1.0534 1.0623 1.0712 1.0801 1.0890 1.0979 1.1068];
% 公路客运量(单位:万人)
passengerVolume = [600 620 640 660 680 700 720 740 760 780 800 820 840 860 880 900 920 940 960 980];
% 公路货运量(单位:万吨)
freightVolume = [50 52 54 56 58 60 62 64 66 68 70 72 74 76 78 80 82 84 86 88];% 3. 数据预处理(归一化)
rand('state', sum(100*clock)); % 随机数种子初始化(保证结果可复现)
input = [numberOfPeople; numberOfAutomobile; roadArea]; % 输入矩阵(3×20)
output = [passengerVolume; freightVolume]; % 输出矩阵(2×20)
% 归一化:将输入、输出数据映射到[-1,1]区间,保存归一化参数(minp,maxp,mint,maxt)
[sampleInput, minp, maxp, tmp, mint, maxt] = premnmx(input, output);
% 添加噪声(防止模型过拟合)
noiseIntensity = 0.01;
noise = noiseIntensity * randn(outputDimension, numberOfSample);
sampleOutput = tmp + noise;% 4. 划分测试集(因样本少,测试集=训练集)
testSampleInput = sampleInput;
testSampleOutput = sampleOutput;% 5. 模型训练参数设置
maxEpochs = 50000; % 最大训练次数
learningRate = 0.035; % 学习率(经调试最优值)
error0 = 0.65e-3; % 目标误差(训练终止条件)% 6. 初始化网络权值与阈值(随机生成[-0.1,0.4]区间值)
W1 = 0.5 * rand(numberOfHiddenNeure, inputDimension) - 0.1; % 输入层→隐含层权值(8×3)
B1 = 0.5 * rand(numberOfHiddenNeure, 1) - 0.1; % 隐含层阈值(8×1)
W2 = 0.5 * rand(outputDimension, numberOfHiddenNeure) - 0.1; % 隐含层→输出层权值(2×8)
B2 = 0.5 * rand(outputDimension, 1) - 0.1; % 输出层阈值(2×1)% 7. 迭代训练网络
errorHistory = []; % 保存误差历史(用于后续绘图)
for i = 1:maxEpochs% 前向传播:计算隐含层、输出层输出hiddenOutput = logsig(W1 * sampleInput + repmat(B1, 1, numberOfSample)); % 隐含层激活(logsig函数)networkOutput = W2 * hiddenOutput + repmat(B2, 1, numberOfSample); % 输出层输出(线性激活)% 计算误差error = sampleOutput - networkOutput; % 实际输出与预测输出差值E = sumsqr(error); % 误差平方和(能量函数)errorHistory = [errorHistory E]; % 记录误差% 终止条件:误差小于目标值则停止训练if E < error0break;end% 反向传播:调整权值与阈值(梯度下降法)delta2 = error; % 输出层误差项% 隐含层误差项(链式求导:权值转置×输出层误差×激活函数导数)delta1 = W2' * delta2 .* hiddenOutput .* (1 - hiddenOutput);% 计算权值、阈值更新量dW2 = delta2 * hiddenOutput'; % 输出层权值更新量dB2 = delta2 * ones(numberOfSample, 1); % 输出层阈值更新量dW1 = delta1 * sampleInput'; % 输入层权值更新量dB1 = delta1 * ones(numberOfSample, 1); % 输入层阈值更新量% 更新权值与阈值W2 = W2 + learningRate * dW2;B2 = B2 + learningRate * dB2;W1 = W1 + learningRate * dW1;B1 = B1 + learningRate * dB1;
end% 8. 模型测试(用训练集验证拟合效果)
testHiddenOutput = logsig(W1 * testSampleInput + repmat(B1, 1, numberOfTestSample));
testNetworkOutput = W2 * testHiddenOutput + repmat(B2, 1, numberOfTestSample);
% 反归一化:将预测结果还原为实际物理量
a = postmnmx(testNetworkOutput, mint, maxt);
a1 = a(1,:); % 测试集客运量预测值
a2 = a(2,:); % 测试集货运量预测值% 9. 绘制测试拟合对比图(图1:1990-2009年拟合效果)
t = 1990:2009;
figure(1);
% 客运量对比
subplot(2,1,1);
plot(t, a1, 'ro', t, passengerVolume, 'b+', 'LineWidth', 1.2);
legend('网络输出客运量', '实际客运量', 'Location', 'best');
xlabel('年份', 'FontSize', 10);
ylabel('客运量/万人', 'FontSize', 10);
title('神经网络客运量学习与测试对比图', 'FontSize', 11);
grid on;
% 货运量对比
subplot(2,1,2);
plot(t, a2, 'ro', t, freightVolume, 'b+', 'LineWidth', 1.2);
legend('网络输出货运量', '实际货运量', 'Location', 'best');
xlabel('年份', 'FontSize', 10);
ylabel('货运量/万吨', 'FontSize', 10);
title('神经网络货运量学习与测试对比图', 'FontSize', 11);
grid on;% 10. 预测2010-2011年运量
newInput = [73.39 75.55; 3.9635 4.0975; 0.9880 1.0268]; % 新输入数据(2010-2011年)
newInput = tramnmx(newInput, minp, maxp); % 新数据归一化(用训练集参数)
% 前向传播预测
newHiddenOutput = logsig(W1 * newInput + repmat(B1, 1, numberOfForcastSample));
newOutput = W2 * newHiddenOutput + repmat(B2, 1, numberOfForcastSample);
newOutput = postmnmx(newOutput, mint, maxt); % 反归一化得到预测结果% 11. 输出预测结果
disp('预测2010和2011年的公路客运量分别为(单位:万人):');
newOutput(1,:)
disp('预测2010和2011年的公路货运量分别为(单位:万吨):');
newOutput(2,:)% 12. 绘制预测对比图(图2:1990-2011年含预测数据)
t1 = 1990:2011;
figure(2);
% 客运量预测对比
subplot(2,1,1);
plot(t1, [a1 newOutput(1,:)], 'ro', t, passengerVolume, 'b+', 'LineWidth', 1.2);
legend('网络输出客运量', '实际客运量', 'Location', 'best');
xlabel('年份', 'FontSize', 10);
ylabel('客运量/万人', 'FontSize', 10);
title('神经网络客运量学习与测试对比图(添加预测数据)', 'FontSize', 11);
grid on;
% 货运量预测对比
subplot(2,1,2);
plot(t1, [a2 newOutput(2,:)], 'ro', t, freightVolume, 'b+', 'LineWidth', 1.2);
legend('网络输出货运量', '实际货运量', 'Location', 'best');
xlabel('年份', 'FontSize', 10);
ylabel('货运量/万吨', 'FontSize', 10);
title('神经网络货运量学习与测试对比图(添加预测数据)', 'FontSize', 11);
grid on;% 13. 绘制误差变化图(图3:训练过程误差收敛情况)
figure(3);
n = length(errorHistory);
t3 = 1:n;
plot(t3, errorHistory, 'r-', 'LineWidth', 1.2);
xlim([1 100]); % 聚焦前100次训练(更清晰观察误差下降)
xlabel('训练次数', 'FontSize', 10);
ylabel('能量函数值(误差平方和)', 'FontSize', 10);
title('能量函数在训练过程中的变化图', 'FontSize', 11);
grid on;
五、实验结果与分析
1. 预测结果
运行代码后,2010-2011 年公路运量预测结果如下:
- 客运量:2010 年 702.68 万人,2011 年 779.04 万人(逐年增长,符合交通需求增长趋势);
- 货运量:2010 年 60.33 万吨,2011 年 68.02 万吨(与经济发展、机动车数量增长匹配)。
2. 关键图表解读
(1)运量拟合对比图(图 1)
- 红色圆点为模型输出值,蓝色十字为实际值;
- 两者高度重合,说明模型对 1990-2009 年数据的拟合效果优秀,误差控制在目标范围内。
(2)含预测的对比图(图 2)
- 2010-2011 年的预测值(红色圆点)延续了前期增长趋势,无异常波动;
- 预测结果符合 “人数增加→出行需求增长→客运量上升”“机动车数量增加→货运能力提升→货运量上升” 的逻辑。
(3)误差变化图(图 3)
- 训练前 100 次内,误差从约 120 快速下降至接近 0;
- 说明模型收敛速度快,学习率(0.035)设置合理,未出现震荡或收敛缓慢问题。