第5章 用数据预测下一阶段变化

工作阶段: 在行动之前形成有证据的数量预测。
公共核心项目: 与AI协同开发一个本地运行的“小型门店用电负荷预测器”,预测门店营业区下一日用电量。
核心技术: 时间序列回归、滞后特征、时间切分、上期值与移动平均基线、Keras回归、MAE、峰值漏报和数据漂移。
输入输出链: 连续日负荷与预测时已知信息 → 7日历史窗口 → 两种基线/Keras模型 → 下一日kWh候选 → 冻结未来期误差 → 人工使用判断。
应用中的AI: 根据历史负荷、温度预报和计划活动等已知信息生成下一日负荷候选值的本地Keras回归模型。
协助开发的AI: 帮助学生澄清预测时点、检查字段可得性、生成和解释代码、阅读误差并完成限定修改的大语言模型。
人的责任: 确认计量口径与预测用途,排除未来泄漏,比较模型和基线,审查峰值漏报,决定采用、限用、退回或停止。
主要交付物: 任务合同、220天教学数据、两种基线、Keras模型、完整Notebook与.py工程、35天未来期报告、模型卡和复现说明。
明确边界: 输出只是人工观察候选,不自动断电、控制设备、采购能源或承诺预算;口径变化、数据缺失和超出范围时停止模型判断。
跨章关系: 本章把第2章的数据治理用于预测;预测结果可作为第6章排程的一个输入,但不能替代资源约束和审批。

学习目标

完成本章学习后,你将能够:

  1. 把“预测用电”改写为对象、单位、时点、提前量和行动用途明确的任务;
  2. 识别目标日实际值、事后处置等未来泄漏,并按时间划分训练、验证和测试;
  3. 实现并解释上一日值、7日移动平均两种透明基线;
  4. 在大语言模型协助下运行完整Keras回归工程,指出归一化、特征、模型和输出的连接;
  5. 用MAE、最大误差、峰值召回和逐日错例比较复杂模型与基线;
  6. 完成一次单变量实验、四类固定测试和可由另一组复现的交付判断。

项目导入

“预测下一阶段用电”仍然太宽。预测整座工厂、某个仓库还是一家门店营业区?输出按小时、日还是月?在什么时候给出?预测结果是用来安排检查、准备营业,还是直接控制设备?这些差异会改变数据、模型、误差后果和责任。本章把任务缩小为:在目标日前一天的数据结算后,只用当时已经知道的信息,预测一家小型门店营业区的下一日用电量,单位为kWh。

本项目不是一段孤立的回归代码。学生要从任务合同出发,审查连续220天教学数据,建立“等于上一日”和“最近7日平均”两个基线,训练Keras模型,再把三种方法放到同一段从未参与训练的未来35天上比较。最后还要查看峰值漏报、模拟字段故障和口径漂移,并决定模型是否值得保留。

这两个透明方法共同构成本章的规则基线:它们不学习神经网络参数,假设下一日延续最近历史。规则基线不是陪衬,而是判断复杂模型是否带来实际增益的最低参照。

配套数据由确定性脚本生成,包含门店周内营业节奏、温度、计划促销活动、前一日惯性和小幅随机扰动。它适合观察时间切分和工程链,却不是真实门店数据。实际运行得到较好结果,只能说明模型学会了这套教学机制,不能写成真实工作现场准确率。

连续220天记录
   │
   ├─ 前150天:训练期 ─→ 建立7日窗口与归一化状态 ─→ Keras回归
   ├─ 中间35天:验证期 ─→ 早停与方案观察
   └─ 最后35天:冻结未来期
             ├─ 上一日值
             ├─ 最近7日平均
             └─ Keras预测
                    ↓
        MAE、最大误差、峰值召回、逐日错例
                    ↓
       人工决定限用、退回或停止,不自动控制

建议用6—8学时完成。第一课先运行随工程提供的模型和报告,理解作品;第二课在Notebook中逐格观察时间切分、基线和训练;第三课从.py工程重训、修改一个变量并运行验收。学生不必从空白默写TensorFlow语法,但必须能够解释一条日期记录怎样变成特征、预测和验收结论。

本章成果

AI协同开发路线

先把任务用自然语言交给协助开发的AI:“我们在目标日前一日结算后预测一家小型门店营业区的下一日用电量。请先追问单位、时间粒度、当时可得字段、低估和高估后果,不要先给模型代码。”AI可能询问温度是实测还是预报、促销活动是否已正式确定、计量表是否更换。学生只能依据门店数据责任人确认的材料回答;AI不能把“明天实际用电”包装成一个看似有效的特征。

任务冻结后,再要求AI列出工程文件:数据生成与审查、样本构造、两个基线、模型训练、固定未来期评价、单次预测、测试、模型卡和Notebook。学生逐个检查文件输入输出后才让AI生成完整代码,并约束依赖只使用Python、NumPy和Keras/TensorFlow。代码运行后,把真实终端日志和reference_evaluation.json交给AI分析,不让它凭训练代码臆测成绩。

协同修改必须限定范围。例如:“只在训练/验证开发视图中比较7日均值与14日均值,保持数据版本、共同验证日期、Keras模型和指标不变;不要打开冻结未来期。”又如出现日期乱序错误,可要求AI只修数据校验,不改数据和模型。学生在模型与峰值门槛冻结后,才运行一次最终评价与acceptance.py --require-model。聊天中的“看起来更准”不能代替可复现文件。

第一节 明确预测对象、预测时点和行动用途

一、把“预测未来”改写成可验收任务

本项目的一条目标是某个自然日门店营业区的总用电量,单位kWh。预测在前一日记录结算后形成,提前量为一天。工作使用者是店长、设施或能源责任人,输出用于提示“明天可能处于普通或较高负荷”,便于安排人工检查,不直接进入控制系统。

任务合同至少回答五个问题:预测什么;何时预测;当时能看到什么;输出给谁;错误会造成什么后果。若预测对象从一家门店营业区悄悄变成整座商场,历史数据便不再同口径。若温度字段来自目标日结束后的实测,它在训练时虽然完整,真实预测时却不可用。只有目标日前已经发布的温度预报和确认的促销活动才可作为输入。

配套工程位于resources/ch05/project/。TASK_CONTRACT.md冻结任务,data/store_load.csv保存完整数据,data/development_load.csv物理排除最后35天,供数据准备、基线、训练和选参使用;完整文件只在最终评价入口读取。DATA_CARD.md说明生成机制和限制。CSV主要字段如下:

字段 含义 预测时点是否可用
date 目标日期,用于排序和切分 可用于确定星期,不直接代表因果
load_kwh 当日实际用电量 作为历史或目标;目标日值不可作输入
forecast_temperature_c 目标日前已知的温度预报 可用,但必须记录预报来源和发布时间
weekend 是否周末 可用
planned_event 是否有已确认活动 只有预测前已批准时可用
split 训练、验证或冻结测试 只用于工程管理,不是模型特征
source_group 生成或采集来源组 用于追溯,不是模型特征

数据生成脚本固定随机种子20260807。前150天标记训练,建立7日窗口后形成143个训练样本;接着35天验证;最后35天固定为2025-07-05至2025-08-08的未来测试。测试期日期和样例在训练前就确定,不能反复移动到成绩最好的一段。

二、识别数据泄漏和目标漂移

预测任务最隐蔽的错误往往不是模型结构,而是时间。把全部日期随机打乱后再切分,会让模型在训练中看到未来季节和制度变化;用全数据计算归一化均值,也会让测试期分布提前进入训练流程。正确顺序是训练在前、验证居中、测试在后,均值和标准差只从训练样本计算。

另一类泄漏来自字段产生时间。例如“目标日实际室温”“目标日结束后的设备运行时长”“事后制定的节能措施”都可能与用电量高度相关,却在真实预测时不存在。判断字段能否使用,不看它与目标相关不相关,而看预测时点是否已经合法、稳定地获得。

目标漂移是被预测对象或生成机制发生变化。计量表更换、建筑用途改变、统计从“总表读数差”改成“分表求和”,都会使同名load_kwh含义变化。漂移不是多训练几轮就能解决。数据卡要记录变化点;运行时发现单位、口径或分布超出范围,先停止模型并由数据与设施责任人确认。

三、先写错误后果,再选指标

MAE把每个预测与真实值的绝对差求平均,单位仍是kWh,容易解释。但平均值会隐藏峰值。如果35天大多数误差很小,却在两个高负荷日严重低估,平均数仍可能漂亮。因此本项目同时报告最大误差和峰值召回:先用训练目标的90%分位定义教学峰值,再检查真实峰值是否也被预测到峰值区。

峰值阈值只是教学评价工具,不是电气安全值。安全容量、告警规则和设备控制必须来自专业制度。模型即使正确预测“明天77 kWh以上”,也没有权决定断电或调整设备。人的行动应写成分层规则,例如普通范围仅记录,接近人工关注区时复核天气与活动,口径变化或极端事件时停用模型。

专业迁移卡:商业贸易与智能制造
商贸方向可把目标改为下一日或下一周品类销量,输入为历史销量与预测时已确认的促销日历;高代价错误是缺货或积压,品类负责人确认行动。智能制造方向可预测下一班次能耗或产量,输入为历史节拍、计划班次和已批准停机;设备状态与安全容量仍由专业系统处理。迁移时不是换标题,必须重建目标单位、字段产生时间、时间切分、基线与峰值定义。

第二节 先用历史平均、周期和规则建立基线

一、上期值回答“如果明天像今天”

最简单基线是下一日等于上一日。它不需要训练,清楚表达“短期延续”假设。若负荷惯性很强,这个方法可能难以被复杂模型超过;若周末与工作日差异明显,它又会在周五到周六、周日到周一附近产生较大误差。

二、移动平均回答“近期通常是多少”

最近7日平均利用一个完整星期平滑偶然波动。配套core.py只读取7个历史列:

WINDOW = 7

def baseline_predictions(x):
    history = x[:, :WINDOW]
    return {
        "previous_day": history[:, -1].astype("float32"),
        "moving_average_7": history.mean(axis=1).astype("float32"),
    }

基线必须与模型使用同一批目标日期。不能让模型在35天测试、基线只在容易的20天测试。历史不足7天、日期重复、负荷为负或切分顺序错误时,程序明确停止,不用零填补并继续给出一个看似正常的数字。

三、用走步逻辑理解真实预测

预测2025-07-05时只能读取7月4日及以前的实际记录;到7月6日的预测时,7月5日实际值已经结算,才可进入历史。项目数据把每个目标日与此前7日构成一个样本,保证特征都早于目标。虽然模型一次性评价整个测试数组,样本构造仍遵守这个时间关系。

学生应抽取一条样本,写出7个历史日期、目标日期和目标值,再从代码验证列顺序。若大语言模型把目标日load_kwh也放进输入,学生应指出这不是“更强特征”,而是直接泄漏答案。

四、完成一个基线控制变量实验

可只把移动平均窗口从7改为14。实验前预测:14日窗口更平稳,但对温度转折和计划活动响应更慢。保持开发数据版本、共同验证日期、Keras模型、缺失处理、MAE和峰值定义不变。两种窗口必须在共同可预测的验证日期上比较;若14日窗口少了前7个难例,直接比较MAE不公平。冻结未来期在方案确定前不得打开。

协助开发的AI可以生成修改,但学生要审查它是否悄悄读取完整数据、改变验证起点或把模型也重训。记录两个窗口在验证期的MAE、最大误差、峰值召回和逐日变化。基线实验的价值是理解假设,而不只是选一个更小数字。

第三节 训练模型并在未来时间段检验误差

一、把7日历史与已知日历转成特征

每条模型输入包含此前7日用电、目标日温度预报、周末/活动标记,以及星期的正弦与余弦表示,共12个数。正余弦让星期日和星期一在周期上相邻,避免简单整数把星期六误解为“比星期一大五倍”。这些特征仍只是候选;真实项目应由能源责任人判断其来源和稳定性。

不同列量纲差异较大,因此只用训练集计算均值和标准差:

mean = x_train.mean(axis=0)
std = x_train.std(axis=0)
std[std == 0] = 1.0
x_train_n = (x_train - mean) / std
x_val_n = (x_val - mean) / std
x_test_n = (x_test - mean) / std

若对测试集各自计算均值,运行时每批输入会改变尺度;若用全部数据计算,未来信息会进入训练。保存模型时还要保存mean和std,否则另一组即使拿到.keras文件也无法复现相同输入。

二、运行完整Keras回归主链

权威实现位于train.py。模型很小:12维输入经过24与12个ReLU单元,最后一个线性单元输出kWh。损失使用MAE,验证期用于早停。

inputs = keras.Input(shape=(x_train.shape[1],),
                     name="known_history_and_calendar")
x = keras.layers.Dense(24, activation="relu")(inputs)
x = keras.layers.Dense(12, activation="relu")(x)
outputs = keras.layers.Dense(1, name="next_day_kwh")(x)
model = keras.Model(inputs, outputs,
                    name="store_load_forecaster")
model.compile(
    optimizer=keras.optimizers.Adam(0.006),
    loss="mae",
    metrics=["mae"],
)
stop = keras.callbacks.EarlyStopping(
    monitor="val_loss", patience=25,
    min_delta=0.01, restore_best_weights=True,
)
model.fit(
    x_train_n, y_train,
    validation_data=(x_val_n, y_val),
    epochs=180, batch_size=24,
    callbacks=[stop], verbose=2,
)
model.save("models/load_forecaster.keras")

学生要能回答:哪12个数进入模型;目标为何只有一个;归一化状态存在哪里;验证期为什么不更新权重;输出为什么不是概率;模型文件故障时程序怎样停止。完整学习Notebook在resources/ch05/project/notebooks/ch05_load_forecasting.ipynb,训练、评价和单次预测分别由train.py、evaluate.py和predict.py承担。

三、读取本次真实训练与固定未来结果

参考环境为Windows、Python 3.12.13、TensorFlow 2.21.0、Keras 3.15.1、CPU。本次实际使用143个训练样本和35个验证样本训练180轮,随后只在固定的35天未来期评价。报告不是手工填写,而由evaluate.py --write-reference生成。

方法 未来35天MAE 最大误差 峰值命中/真实峰值
上一日值 7.9329 kWh 27.1600 kWh 0/2
最近7日平均 6.7376 kWh 19.7157 kWh 0/2
Keras回归 2.4017 kWh 9.3011 kWh 1/2

Keras模型在这组教学数据上明显降低MAE,也把最大误差缩小,但仍漏掉一个峰值。结论不是“模型已经可以管理门店用电”,而是“在教学合成数据范围内,模型相对两个基线有增益,可作为人工观察候选;峰值仍需人工与正式规则处理”。

这些数据由一个稳定公式生成,模型能够学习星期、温度和活动关系,难度远低于真实工作现场。测试期也只有35天,未覆盖完整季节、设备更换和制度变化。报告中的2.4017不能写成未来真实误差,更不能据此设安全阈值。

四、从逐日错例回到工作原因

reports/reference_errors.csv保存每个测试日的真实值和三种预测。学生按绝对误差排序,检查最大错误是否集中在活动日、周末转换或温度变化。向AI提问时要提供日期、真实值、三种预测和已知特征,例如:“只解释7月某日三种方法为何都低估,列出数据中能验证的假设,不修改模型。”

若AI建议增加“当天实际用电”或复制固定错例进入训练,应拒绝。合理下一步可能是核对活动标记在预测时是否真的已知、增加新的训练时期、为口径变化分段评价,或输出更保守的人工关注区。错误分析的目标是找到可验证原因,不是让AI编一个故事。

第四节 把不确定性和错误成本转化为行动边界

一、冻结正常、边界、陌生和故障测试

正常测试是冻结未来期内与训练机制一致的普通工作日和周末,检查三种方法是否在同一日期输出。边界测试包括峰值日、周末切换、温度变化和计划活动,重点看最大误差与峰值漏报。陌生测试包括统计口径改变、未见极端天气、新建筑或长期停课,预期不是强行外推,而是标记超出验证范围并转人工。

故障测试包括日期重复或乱序、负负荷、非法0/1标记、历史不足7天、模型文件或元数据缺失。tests/test_project.py实际验证开发视图不含冻结日期、陌生统计口径与字段漂移在模型前转人工、模型文件故障安全接管,以及基线只读历史列。程序必须给出明确错误或人工路由,不用零填补,也不沿用上一次缓存预测。

工程一键验收命令为:

cd resources\ch05\project
python acceptance.py
python acceptance.py --require-model

默认入口检查必需文件、Python语法、9项单元测试、Notebook冻结隔离,以及报告中的固定测试、模型、配置与元数据摘要;--require-model再现场加载模型,把评价与正式参考结果逐项比较,只排除明确不稳定的环境版本字段。验收通常数秒完成,不在全书测试时重新训练。

二、把误差变成可执行边界

预测值不能单独触发动作。较稳妥的界面或报告应并列显示日期、模型候选、两个基线、历史范围、活动/温度条件和“人工确认必需”。当模型与两个基线差异很大时,差异本身就是复核信号;当输入超出数据卡范围时,停止比输出一个精确小数更可靠。

学生可设计三档低风险使用规则:普通候选只进入观察日志;接近训练峰值或模型与基线分歧过大时请能源人员复核;口径、设备或采集流程变化时停止模型。具体阈值必须由项目数据和责任人确认,教材不把教学峰值写成通用标准。

三、让AI完成一次限定修改并回归

可要求协助开发的AI只在predict.py增加“历史7日范围外时转人工”的检查,不改训练数据、模型和测试。学生先写预期行为,审查文件差异,再增加一个边界测试并运行全部回归。另一项学生亲手实验可以只改移动平均窗口;两项活动都要保持固定未来期不变。

若修改针对某个冻结错例,不能直接把该日期及答案复制回训练后继续用同一报告宣称泛化提升。数据变化应另建版本,重新训练,并准备从未参与讨论的新未来期。测试一旦反复指导设计,就不再是完全独立的最终证据。

四、形成交付与使用判断

完整项目文件夹含README、任务合同、数据生成器、CSV、数据卡、核心代码、Notebook、模型、元数据、训练历史、逐日误差、模型卡和测试。另一组应能从干净环境安装依赖,先运行基础验收,再加载模型、复现35天指标,并解释为何结论仍是“教学合成数据范围限用”。

采用意味着在冻结范围内达到预设标准;限用意味着只作人工候选并保留停止条件;退回表示模型未胜较优基线或峰值错误不可接受;停止表示数据授权、口径、维护或安全条件不具备。如果下一版本复杂模型不再超过7日平均,保留基线是技术上正确的结论,而不是项目失败。

专业迁移卡:风景园林与生物技术
园林方向可预测下一日灌溉需求或温室能耗,特征只能使用预测时已知天气、历史传感和种植阶段;自动开泵仍需水量、安全和设备规则。生物方向可预测培养环境的下一时间段趋势,但批次、设备校准和实验规程必须进入数据卡;模型不能作生物安全结论。两类迁移都要保留上期值或移动平均基线、按时间隔离测试和漂移停止条件。

本章小结

本章完成了一个真正的时间序列垂直项目:从预测合同、连续日数据、时间切分和两种基线出发,构造7日历史与预测时已知特征,训练Keras回归模型,再在固定未来35天比较MAE、最大误差和峰值漏报。应用中的AI负责数值候选,协助开发的AI帮助澄清、编码和分析,人负责字段可得性、错误后果和使用决定。

真实运行表明模型在教学生成数据上超过两个基线,却仍漏掉一个峰值。最重要的结论不是某个漂亮误差,而是:未来不能泄漏到训练;复杂模型必须公平超过简单方法;平均分不能掩盖高代价错误;超出范围时要停止;另一组能复现的工程与报告才是交付物。

关键术语

目标测试

  1. 为什么目标日实际用电量不能作为预测该日用电量的输入?
    A. 数值太大 B. 会增加模型层数 C. 预测时尚不可得,会造成未来泄漏 D. CSV不能保存
  2. 本项目为什么不能随机打乱全部220天后再切分?
    A. 随机会让文件变大 B. 会让未来模式进入训练,破坏真实时间顺序 C. Keras不支持随机数据 D. 移动平均必须用文本
  3. 公平比较Keras模型和7日移动平均,必须满足什么条件?
    A. 模型代码行数相同 B. 使用同一未来期、目标和指标 C. 都训练180轮 D. 输出完全相同
  4. Keras模型在冻结未来期MAE较低,但峰值只命中1/2,最合理的结论是?
    A. 可自动控制设备 B. 峰值指标不重要 C. 教学范围可作人工候选,峰值仍需复核 D. 删除漏掉的峰值
  5. 判断并改错:“用全部220天计算归一化均值不会影响模型权重,因此不算泄漏。”
  6. 判断并改错:“第5章预测值可以直接成为第6章正式排程和设备控制命令。”
  7. 写出本项目的预测对象、预测时点、两个可用字段和两个禁止字段。
  8. 设计只把移动平均窗口从7改为14的控制变量实验,说明共同验证日期怎样保持公平,并说明为何不能据此读取冻结测试期。
  9. 各设计一条陌生测试和故障测试,并写出系统预期行为。
  10. 某次重训后模型MAE为7.1 kWh,7日平均为6.7 kWh;模型在峰值上也没有改善。请作出采用、限用、退回或停止结论,并说明基线、责任人和重新验收范围。

答案编号:A3-5-01—A3-5-10。完整答案和评分要点统一放入书后“目标测试参考答案”。