☰
基于BP神经网络的空调负荷预测:PCA降维与参数调优实战
2026/10/5 7:04:36 网站建设 项目流程

简介:这份PDF文献《基于BP神经网络下空调负荷预测模型的研究》面向暖通空调、建筑能源管理及机器学习数据建模方向的学习者与工程技术人员,聚焦如何构建系统化、简便的神经网络负荷预测模型这一实际问题。全文围绕BP神经网络的结构与参数展开,重点讨论输入层与隐含层神经元数目的确定方法、样本集长度的寻优策略,以及数据预处理、归一化、误差反向传播训练等关键环节,并通过实际工程数据验证模型各环节的有效性,最终确定最佳预测结构。资源包内仅含1个PDF文件,约353KB,为2016年《应用能源技术》期刊论文原文,便于精读与引用。目前已有123人学习,适合希望将神经网络方法落地于空调负荷预测、提升模型泛化能力并减少过拟合风险的研究者参考借鉴。

1. 从一篇 2016 年的论文说起:为什么空调负荷预测至今还在用 BP 神经网络

2016 年《应用能源技术》第 9 期上有一篇论文,标题是《基于 BP 神经网络下空调负荷预测模型的研究》,作者是北京建筑大学的林育贤和冯圣红。这篇论文解决的不是“BP 神经网络能不能做负荷预测”这种已经被反复验证过的问题,而是一个更工程化的痛点:如何从零建立一套系统、简便、可复现的空调负荷预测模型。论文的核心贡献在于把输入层神经元怎么选、隐含层节点数怎么定、样本集长度取多少这三个关键环节,用实际工程数据逐一确定下来,最终给出一个明确的结构:4-10/11-1,样本集长度 26~30。

如果你正在做建筑能耗管理、暖通空调系统优化,或者手头有一个冷站运行数据集想跑预测,这份资料的价值在于它提供了一条完整的建模路径,而不是只丢给你一个“用 BP 神经网络”的结论。它适合两类人:一是刚接触负荷预测、需要照着步骤复现一套 baseline 的工程师;二是已经用过 BP 但预测精度不稳定、想搞清楚参数到底怎么调的从业者。下面我会把这篇论文里的方法拆成可执行的步骤,补上论文没写全的代码细节和踩坑记录。

2. 输入层参数怎么定:PCA 降维的实操逻辑与 MATLAB 实现

2.1 为什么不能把所有天气参数直接塞进输入层

论文一开始就点了一个常见问题:很多文献在选输入变量时缺乏考虑,直接把室外干湿球温度、太阳辐射强度、相对湿度等参数一股脑作为输入。这样做的问题有两个。第一,输入变量过多会导致网络训练时间显著增加,尤其是当样本量本身不大的时候,训练效率会低到无法接受。第二,更隐蔽的问题是变量之间的相关性会造成信息叠加。比如干球温度和湿球温度本身就高度相关,太阳辐射强度和相对湿度在白天也存在明显的负相关关系。这些相关性会让网络在训练时反复学习重复的信息,反而掩盖了真正的负荷变化规律。

论文采用的方案是主成分分析(PCA)。PCA 的作用是对多维数据进行主要特征分量的提取,把原来可能相关的变量转换成一组彼此独立的新变量。论文中初选了 9 个影响因素,经过 PCA 处理后,前 4 个主成分的累计贡献率达到了 94.563%,超过了 90% 的经验阈值,所以最终输入层神经元个数定为 4。

2.2 PCA 在 MATLAB 里的具体操作步骤

论文没有给出 PCA 的代码,但根据它的描述和常见做法,我一般会按下面的流程来写。假设你已经把原始数据整理成了一个矩阵,每一列是一个影响因素,每一行是一个时间点的样本。

% 假设 rawData 是 n×9 的矩阵,n 是样本数,9 是初选的影响因素个数 % 第一步:数据归一化,消除量纲影响 rawData_normalized = mapminmax(rawData', 0, 1)'; % 按行归一化到 [0,1] % 第二步:计算相关系数矩阵 corrMatrix = corrcoef(rawData_normalized); % 第三步:对相关系数矩阵做特征值分解 [eigenVectors, eigenMatrix] = eig(corrMatrix); eigenValues = diag(eigenMatrix); % 第四步:按特征值从大到小排序 [eigenValues_sorted, idx] = sort(eigenValues, 'descend'); eigenVectors_sorted = eigenVectors(:, idx); % 第五步:计算贡献率和累计贡献率 contributionRate = eigenValues_sorted / sum(eigenValues_sorted); cumulativeRate = cumsum(contributionRate); % 第六步:确定主成分个数,累计贡献率超过 90% 即可 numComponents = find(cumulativeRate >= 0.90, 1); % 第七步:计算主成分得分,作为新的输入变量 newInput = rawData_normalized * eigenVectors_sorted(:, 1:numComponents);

这段代码的逻辑是:先归一化消除量纲,再通过相关系数矩阵的特征值分解找到数据方差最大的方向。特征值越大,说明该方向包含的信息越多。累计贡献率超过 90% 的前几个主成分,就足以代表原始数据的大部分信息。numComponents就是最终确定的输入层神经元个数,论文中这个值是 4。

注意:PCA 之前必须做归一化。如果跳过这一步,量纲大的变量(比如太阳辐射强度,数值可能在几百)会主导特征值分解的结果,导致主成分完全偏向那个变量,降维就失去意义了。

2.3 参数说明与常见误用

mapminmax是 MATLAB 自带的归一化函数,默认把数据映射到 [-1,1],这里改成 [0,1] 是为了后续和 BP 网络的传递函数匹配。corrcoef计算的是皮尔逊相关系数矩阵,要求数据近似服从正态分布。如果你的数据里有明显的异常值,建议先用filloutliers或 3σ 准则剔除,否则相关系数会被拉偏。

一个常见的误用是:有人把 PCA 直接用在未归一化的数据上,然后看到累计贡献率很快就超过 90%,以为降维效果很好,实际上是因为某个量纲大的变量占据了绝大部分方差。另一个误用是:确定了主成分个数后,没有保存特征向量矩阵,导致每次预测新样本时重新计算,训练集和测试集的降维标准不一致。正确的做法是把训练集得到的eigenVectors_sorted保存下来,测试集用同一个矩阵做投影。

3. 隐含层节点数与样本集长度:试凑法的工程化操作

3.1 隐含层神经元个数为什么没有解析解

论文明确指出,隐含层神经元数目的确定是一个难题,当前尚无理想的解析式或严格的数学方法。神经元太少会导致网络容错性差,无法很好地学习,出现欠拟合;神经元太多则会造成训练时间过长,网络联想能力降低,出现过拟合。论文采用的策略是试凑法:在相同的网络结构下,改变隐含层神经元个数,考察预测精度,从而确定最佳数目。初选范围是 6 到 15 个。

论文的实测结果是:隐含层神经元个数为 10 时,模型精度最高。此后精度略有下降,但波动不大,说明网络趋于平稳。最终确定的网络结构是 4-10-1。

3.2 试凑法的 MATLAB 实现框架

下面这段代码是我根据论文思路整理的试凑法框架,可以直接套用到你自己的数据上。

% 假设 newInput 是 PCA 降维后的输入矩阵,target 是负荷实际值 % newInput 维度为 n×4,target 维度为 n×1 hiddenNeurons = 6:15; % 初选隐含层神经元个数范围 accuracy = zeros(length(hiddenNeurons), 1); for i = 1:length(hiddenNeurons) % 创建 BP 网络,隐含层神经元个数为 hiddenNeurons(i) net = feedforwardnet(hiddenNeurons(i)); % 设置训练算法为 L-M 算法 net.trainFcn = 'trainlm'; % 设置数据划分比例,论文未明确说明,常见做法是 70% 训练,15% 验证,15% 测试 net.divideParam.trainRatio = 0.7; net.divideParam.valRatio = 0.15; net.divideParam.testRatio = 0.15; % 训练网络 [net, tr] = train(net, newInput', target'); % 用验证集计算精度 % 这里假设用最后一天的数据作为验证,具体划分根据你的数据来 valInput = newInput(end-23:end, :)'; % 举例:最后 24 个点 valTarget = target(end-23:end)'; predicted = net(valInput); % 计算相对误差或均方根误差 rmse = sqrt(mean((predicted - valTarget).^2)); accuracy(i) = rmse; end % 找到精度最高(RMSE 最小)对应的隐含层神经元个数 [~, bestIdx] = min(accuracy); bestHiddenNeurons = hiddenNeurons(bestIdx); fprintf('最佳隐含层神经元个数为:%d\n', bestHiddenNeurons);

这段代码的核心是循环遍历 6 到 15 个隐含层神经元,每次训练一个 BP 网络,用验证集的 RMSE 衡量精度。feedforwardnet是 MATLAB 中创建前馈神经网络的函数,默认就是 BP 网络。trainlm是 L-M 算法,论文中明确采用该算法,因为它比标准梯度下降法收敛更快、精度更高。

注意:每次训练网络时,MATLAB 会随机初始化权重,导致同一结构下的结果有波动。建议对每个神经元个数重复训练 5 到 10 次,取平均精度,否则试凑法的结论可能不可靠。论文中没有提到这一点,但这是实际工程中必须做的。

3.3 样本集长度的寻优:为什么不是越长越好

论文的另一个关键结论是关于样本集长度的。BP 神经网络在学习新样本的过程中会出现遗忘已学样本的现象,训练样本太长会影响计算速度,造成过拟合。论文用 7 月 20 日到 9 月 3 日的数据,分别选取样本集长度 N=14 到 34 进行训练,以取样后一天同一时刻的实际负荷值作为检测值。

结果是:样本长度较少时,相对误差在 9% 到 12% 之间,波动大;随着样本长度增加,误差稳步递减;当样本长度达到 26 到 30 时,相对误差最小,在 3% 到 4% 之间;超过 30 后,精度没有显著改进,反而有所下降。最终确定的样本集长度范围是 26 到 30。

这个结论的工程含义是:样本集长度存在一个最优区间,不是越多越好。对于每半小时采样一次的数据,26 到 30 个样本大约对应 13 到 15 个小时的数据量。如果你的数据是逐时采样的,这个区间可能需要相应调整,但寻优方法是通用的。

3.4 完整的建模流程与参数调节顺序

论文在 1.5 节给出了建立 BP 神经网络模型的流程,我把它整理成可执行的步骤:

  1. 数据预处理:天气状况量化、太阳辐射量化、剔除伪数据、归一化。
  2. 用 PCA 确定输入层神经元个数,论文中为 4。
  3. 用试凑法确定隐含层神经元个数,初选 6 到 15,论文中最优为 10。
  4. 固定网络结构,改变样本集长度,重复训练,确定最优样本长度区间。
  5. 用最优结构进行验证,论文中以 8 月 26 日作为检验集,逐时负荷的实际值和模拟值呈现出良好的跟随性。

这个顺序不能颠倒。如果先定样本长度再调隐含层节点数,样本长度变化会改变输入数据的分布,导致之前确定的隐含层节点数不再最优。论文中特别强调了“重复性模拟仿真”和“反复进行上述步骤”,说明这是一个迭代过程,不是一次就能定下来的。

4. 避坑与排查:复现这篇论文时最容易翻车的五个地方

4.1 现象:PCA 累计贡献率始终达不到 90%

原因:原始数据没有做归一化,或者数据中存在大量异常值,导致方差分布极度不均匀。另一个可能的原因是初选的影响因素本身就不包含足够的信息,比如只选了温度没选太阳辐射。

解决:先检查归一化是否执行,再用箱线图或 3σ 准则剔除异常值。如果仍然达不到 90%,说明初选变量需要调整,可以尝试增加与负荷相关性高的变量,比如前一天同一时刻的负荷值。

4.2 现象:隐含层节点数试凑时,每次运行得到的最佳值都不一样

原因:MATLAB 的feedforwardnet每次训练都会随机初始化权重和偏置,导致同一结构下的结果有随机波动。论文中没有提到这一点,但这是实际复现时最常见的困惑。

解决:在每次训练前固定随机种子,例如rng(42)。更稳妥的做法是对每个候选节点数重复训练 5 到 10 次,取平均 RMSE 作为评价指标,而不是只看单次结果。

4.3 现象:训练集精度很高,但验证集误差很大

原因:典型的过拟合。可能的原因包括隐含层神经元过多、样本集长度过长、或者训练集和验证集的数据分布不一致。论文中提到的“遗忘样本”现象也会导致这个问题。

解决:先检查样本集长度是否超过了 30。如果超过了,尝试缩短到 26 到 30 区间。然后检查隐含层节点数是否过大,可以适当减少。另外,确保训练集和验证集来自同一季节、同一工况,不要用夏季数据训练、冬季数据验证。

4.4 现象:L-M 算法训练时出现“Maximum MU reached”或提前停止

原因:L-M 算法中的阻尼因子 μ 达到了上限,通常是因为网络规模相对于样本量太大,或者输入数据存在共线性。论文中采用 PCA 降维就是为了消除共线性,但如果 PCA 的主成分个数选得太多,共线性仍然可能存在。

解决:检查 PCA 的主成分个数是否严格按照累计贡献率 90% 来确定,不要为了“保留更多信息”而多选。另外,可以适当降低隐含层神经元个数,或者增加样本量。如果问题持续,可以尝试调整net.trainParam.mu_max参数,但这不是根本解决办法。

4.5 现象:预测结果与实际负荷的跟随性差,滞后明显

原因:输入变量中没有包含足够的时间信息。论文中用的是 14:00 到 15:00 时段的数据,输入参数为 9 个,经过 PCA 后变成 4 个主成分。但如果你的数据是逐时预测,输入变量中缺少前一时刻的负荷值,网络就无法捕捉负荷变化的趋势。

解决:在输入变量中加入前一时刻或前几个时刻的负荷值作为输入。论文中没有明确提到这一点,但在实际工程中,加入历史负荷作为输入是提高跟随性的常用做法。你可以把当前时刻的天气参数和前一时刻的负荷值一起做 PCA,或者直接把历史负荷作为额外的输入变量。

5. 从论文到落地:用 L-M 算法和滚动预测把模型跑稳

论文最终确定的网络结构是 4-10/11-1,样本集长度 26 到 30。这个结论是在特定工程数据下得到的,直接套用到你的项目上不一定最优,但方法论是通用的。我在实际项目里通常会做两件事来让模型更稳。

第一件事是用滚动预测代替单次预测。论文中是以 8 月 26 日作为检验集,用训练好的网络预测这一天的逐时负荷。实际运行中,我会每天用最新的数据重新训练一次网络,或者至少每周更新一次。具体做法是:保持网络结构不变,把最新的 26 到 30 个样本加入训练集,剔除最旧的样本,重新训练。这样网络能跟踪负荷的季节性变化和工况漂移。

% 滚动预测框架示例 windowSize = 28; % 样本集长度,取论文推荐的 26-30 中间值 retrainInterval = 24; % 每 24 个新样本重新训练一次 for t = windowSize+1:length(allData) if mod(t, retrainInterval) == 0 % 提取最新的 windowSize 个样本 trainInput = newInput(t-windowSize:t-1, :)'; trainTarget = target(t-windowSize:t-1)'; % 重新训练网络 net = feedforwardnet(10); net.trainFcn = 'trainlm'; net = train(net, trainInput, trainTarget); end % 用当前网络预测下一时刻 currentInput = newInput(t, :)'; predictedLoad(t) = net(currentInput); end

这段代码的逻辑是:维护一个固定长度的滑动窗口,每积累 24 个新样本就重新训练一次网络。windowSize取 28,是论文推荐区间的中间值。retrainInterval设为 24,对应一天的数据量(如果逐时采样)。这样既保证了网络能跟踪最新工况,又不会因为频繁训练导致计算负担过重。

第二件事是用相对误差的统计分布来验证模型,而不是只看某一天的跟随曲线。论文中给出的综合平均相对误差在 3% 到 4% 之间,这个指标比单日曲线更有说服力。我一般会计算验证集上所有样本的相对误差,然后看它的均值、标准差和 95% 分位数。如果 95% 分位数超过 10%,说明模型在某些工况下不可靠,需要检查那部分数据是否属于训练集未覆盖的工况。

验证指标论文中的结果工程可接受范围检查方法
平均相对误差3%~4%<5%验证集所有样本的相对误差均值
最大相对误差未明确<10%验证集相对误差的最大值
累计贡献率94.563%>90%PCA 前 m 个主成分的累计贡献率
隐含层节点数10试凑法确定6~15 范围内 RMSE 最小

最后说一个我自己的习惯。从那以后我每次复现这类论文,都会先把论文中的参数范围原封不动跑一遍,确认能复现出相近的结果,再在此基础上调参。如果直接跳过论文的初选范围去试更大的范围,很容易陷入“调参玄学”,最后自己也说不清哪个参数起了作用。论文给出的 6 到 15 和 26 到 30 这两个区间,是经过实际工程数据验证的,先在这个范围内找,找不到再往外扩,比盲目搜索高效得多。

希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询