介绍
工作室现在有了诚实的预测边界。与早期到场人数中位数相比,小型回归模型能否改善材料规划估计?你将拟合简短的 Pipeline,在相同的有标签工作坊上比较两种方法,保存真实对比图和未来预测。
你需要掌握 Python 函数、pandas 选择与连接、Scikit-learn 回归和训练集/测试集的基础概念,以及入门 Matplotlib。前一引导实验解释了七天截止时间与只在训练集上拟合填补器。本实验独立准备全部文件,包括已完成的 ID/日期切分;不需要上一台 VM 的文件。所有数据都是原创合成教学材料。60 分钟为作者估计。
在早期工作坊上拟合小型 Pipeline
本步中,你将把看似诱人的活动后模型替换为可复用的七天前预测器。
从 WebIDE → Terminal → New Terminal 开始。cd 改变当前终端的工作目录。准备好的 ./python 可执行文件启动课程环境;./ 选择当前目录中的启动器,而非系统解释器。
cd /home/labex/project/workshop-attendance
cat 显示文件而不修改文件;多个文件名参数会依次显示各文件。
cat season.json history.csv labels.csv future.csv
每个历史行是一场以 session_id 为键的工作坊。labels.csv 以独立行序按该键关联 actual_attendance。允许的数值模型特征只有 booked_7d,即活动前恰好七天保存的快照,以及 duration_minutes,即截止时已公布的时长。数值空单元格表示信息缺失;每个允许特征都存在非空训练观测值。ID 与日期用于关联和切分,不是模型输入。final_bookings 和 scanned_entries 在活动发生时才产生,会泄漏七天前尚不可得的信息。
已完成的切分将训练冻结在 2026 年 4 月 1 日 00:00 UTC,并保留从 4 月 12 日开始的历史活动用于评估。训练标签在各早期活动当日结束前已知;这里最后一场训练活动是 3 月 8 日。最早留出预测发生在 4 月 5 日,使用该活动自己的七天前快照和已冻结模型。并不声称 4 月 1 日就已知道 4 月 5 日输入。后期快照文件回放对应的后期预测日期。future.csv 没有真实标签;其五月活动只获得预测,不计算实测误差。配置间隔内没有历史行。本课不讨论滚动重拟合或训练特征整列为空的情况。
cat split.py
观察其中按键连接的 merge、解析后的日历边界和日期排序。这是上一课完成的切分,此处独立提供。保留它、全部 CSV/JSON 输入、python、run.py、coursekit.py、show_results.py 和 starter-*.py 文件。只编辑 model.py、chart.py 及自己的 output/ 产物。提供的 model.py 最初使用扫码建模:即使历史结果看似完美,也无法补救信息选择无效的问题。
Pipeline 将预处理与模型串联。fit 时,填补器从传入的训练特征学习均值,然后回归器从填好的训练矩阵学习。predict 时,同一填补器只转换后期输入,绝不在留出或未来数据上重新拟合。LinearRegression 用普通最小二乘拟合截距和特征系数;这里保留小模型,不调优大量替代方案。
编写两个可复用模型函数。FEATURES 恰为 ['booked_7d', 'duration_minutes']。fit_model 返回拟合后的估计器和训练目标中位数。predict_events 对每张输入表选择相同的允许特征。占位的 evaluate 将在下一步完成;fit 阶段不调用它。
shell 的 > 替换文件。<<'PY' 开始带引号的 here-document:请粘贴到最后仅含 PY 的一行;shell 将其中的 Python 原样保存。也可在 WebIDE Explorer 中编辑 model.py,再选择 File → Save。
cat > model.py <<'PY'
import numpy as np
from sklearn.impute import SimpleImputer
from sklearn.linear_model import LinearRegression
from sklearn.pipeline import make_pipeline
from coursekit import FEATURES
def fit_model(train):
model = make_pipeline(SimpleImputer(strategy="mean"), LinearRegression())
model.fit(train[FEATURES], train.actual_attendance)
return model, float(train.actual_attendance.median())
def predict_events(model, events):
return model.predict(events[FEATURES])
def evaluate(actual, predicted, baseline):
raise NotImplementedError("Complete the continuous-error comparison")
PY
./python run.py fit
保存的预览应将 W-88 与接近 32.718 的原始预测、实际人数 46 和基线 24.5 关联;W-09 的预测接近 62.236,实际为 74,基线相同。即使实际工作坊人数是整数,回归输出也可以是小数。
./python show_results.py fit
这些是汇总误差之前的预测,拟合时未使用后期标签。改变这些标签应改变最终误差,而非拟合后的预测。学习到的系数为零时,某特征可以合法地没有影响;任意输入变化并不一定改变预测。
在同一留出集上比较连续误差
本步中,你将从真实留出标签计算绝对误差,并以人数为单位比较均值。
继续在 WebIDE 的 /home/labex/project/workshop-attendance 下操作。绝对误差是 actual - predicted 的大小。np.abs 逐元素计算,np.mean 对结果数组求平均。为了公平比较基线,要从相同的各个真实留出标签中减去同一早期目标中位数。绝不比较不同活动集合,也不用预测替代真实结果。
所有误差和 MAE 都使用原始连续预测。先把预测四舍五入为显示人数会改变评估。包装器将终端 MAE 格式化为三位小数方便阅读,同时将未取整的数值保存在 JSON 中。
用下面的完整版本替换 model.py。它保留拟合模型和预测逻辑,并完成之前空缺的 evaluate 函数。函数返回逐活动误差数组及其均值;包装器写入 output/holdout.csv 时保留同一留出行的 ID。误差向量遵循传入实际/预测数组的位置顺序。包括 pandas Series 在内的等效类数组值均按此顺序接受;其数值 Series 索引标签不是工作坊 ID。
cat > model.py <<'PY'
import numpy as np
from sklearn.impute import SimpleImputer
from sklearn.linear_model import LinearRegression
from sklearn.pipeline import make_pipeline
from coursekit import FEATURES
def fit_model(train):
model = make_pipeline(SimpleImputer(strategy="mean"), LinearRegression())
model.fit(train[FEATURES], train.actual_attendance)
return model, float(train.actual_attendance.median())
def predict_events(model, events):
return model.predict(events[FEATURES])
def evaluate(actual, predicted, baseline):
model_errors = np.abs(actual - predicted)
baseline_errors = np.abs(actual - baseline)
return {
"model_abs_error": model_errors,
"baseline_abs_error": baseline_errors,
"model_mae": float(np.mean(model_errors)),
"baseline_mae": float(np.mean(baseline_errors)),
}
PY
./python run.py evaluate
预期终端摘要:
Model MAE (people): 12.523
Baseline MAE (people): 35.500
./python show_results.py evaluate
对于 W-88,模型误差约为 13.282 人,基线误差为 21.5。对于 W-09,约为 11.764 和 49.5。未取整均值分别约为 12.5230751656 和恰好 35.5 人。早期小练习的基线是 18;完整季节的训练中位数为 24.5,因为早期样本不同。
这里小模型在两场留出活动上的误差较低。这只是这份小型合成留出集的证据,不证明未来可靠性,也不说明预约引起了某种效果。如果正确模型的 MAE 更高,诚实结论就是它未改善这项比较。评分从不要求模型胜过基线,常量或无信息特征也合法。
交付图表与无标签未来预测
本步中,你将清晰展示留出比较,并导出未来估计,不编造真实结果。
继续在 WebIDE 的 /home/labex/project/workshop-attendance 下操作。图表必须对每个留出 ID,分别绘制 Actual、Model、Baseline 三组序列各一个值,使用对比表中以人数为单位的原始值。折线或散点图均合适;标签与 ID 使其含义明确。PNG 必须可读,至少为 600×300 像素;同一数据上重跑时应重现相同的可见图表。样式可以不同。评分检查实际绘制值和保存图像,而非自报图表清单。每个业务点必须位于可见坐标轴范围内,必需序列不能隐藏或完全透明。恰好位于边界上的点也接受;颜色与轴范围可不同。
Matplotlib 的 Agg 后端无需打开桌面窗口即可写图。subplots 创建图与坐标轴,plot 绘制各个按 ID 关联的序列。下面的标记字符串区分空心实际人数圆点、模型菱形和基线虚线十字,即使实际值与基线重合也可识别。tight_layout 为标签留出空间,savefig 写入真实 PNG,close 释放图对象。
cat > chart.py <<'PY'
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
def draw_comparison(result, destination):
fig, ax = plt.subplots(figsize=(9, 5))
ids = result.session_id
ax.plot(ids, result.actual_attendance, "o-", color="#2454a6",
markerfacecolor="white", markersize=8, label="Actual")
ax.plot(ids, result.model_prediction, "D-", color="#c66a19", label="Model")
ax.plot(ids, result.baseline_prediction, "+--", color="#24815d",
markersize=11, label="Baseline")
ax.set(xlabel="Workshop session", ylabel="People",
title="Seven days ahead: holdout attendance")
ax.legend()
ax.grid(axis="y", alpha=0.2)
fig.tight_layout()
fig.savefig(destination, dpi=120)
plt.close(fig)
PY
先练习无害的拼写错误。下一命令故意使用无效阶段名,产生参数错误并退出;不会改变保存的结果。
./python run.py delvier
消息列出允许选项。修正拼写,运行交付阶段。若出现文件不存在错误,用 pwd 和 ls 检查,使用开始的 cd 返回后,再尝试正确文件名。
./python run.py deliver
./python show_results.py deliver
读取器加载保存的 CSV/JSON 并解码实际 PNG,从不从输入数据补齐缺失结果。在 WebIDE Explorer 中展开 output 并打开 comparison.png。模型应低于两个实际人数点,基线保持在 24.5。不同标记使相同数值的序列也可区分。将 holdout.csv 与图像并排检查,关联各点的 ID 和实际误差。

此提供数据的示例中,W-88 和 W-09 的实际人数为 46、74,模型预测接近 32.718、62.236,虚线基线为 24.5。实际点与预测之间的垂直距离代表该活动的绝对误差。样式可以不同,但 ID 和底层数值必须一致。
forecast.csv 只包含 session_id、原始 model_prediction 和 display_people。F-6 的预测接近 19.119,显示人数为 19;F-101 的预测接近 25.245,显示人数为 25。仅为了显示,包装器将负估计裁剪到零,再用 floor(max(raw, 0) + 0.5) 按半数向上取整。这是实用展示规则,不改变所评估的模型。即使预测为负或含小数,原始预测也保持不变。
不会制造未来实际人数或未来 MAE。模型可以在后期预测快照到达前冻结:到每场五月活动的七天前截止日,再复用现有模型和该活动保存的已知特征。小型合成样本、缺失快照和到场行为变化限制了此分析可支持的结论。独立挑战将更换季节和日期,保留同一工作流程。只要 ID 关系正确,等效数值实现、不同输出行序与折线/散点样式均接受,数值容差为 1e-8。
总结
你在早期工作坊上训练了小型填补/回归 Pipeline,将原始留出误差与训练中位数基线比较,并保存了按 ID 关联的对比图。你还导出了未来估计,同时将未知结果排除在评估之外。较低的留出 MAE 可以支持这项有限比较;只要计算诚实,更差的结果同样有效。



