8.7 KiB
8.7 KiB
开发日志记录
本文档记录了项目开发过程中的主要修改、问题修复和重要决策。
2025-07-13:早期后端修复与重构
开发者: lyf
13:30 - 修复数据加载路径问题
- 任务目标: 解决模型训练时因数据文件路径错误导致的数据加载失败问题。
- 核心问题:
server/core/predictor.py
中的PharmacyPredictor
类初始化时,硬编码了错误的默认数据文件路径。 - 修复方案: 将默认数据路径更正为
'data/timeseries_training_data_sample_10s50p.parquet'
,并同步更新了所有训练器。
14:00 - 数据流重构
- 任务目标: 解决因数据处理流程中断导致关键特征丢失,从而引发模型训练失败的根本问题。
- 核心问题:
predictor.py
未将预处理好的数据向下传递,导致各训练器重复加载并错误处理数据。 - 修复方案: 重构了核心数据流,确保数据在
predictor.py
中被统一加载和预处理,然后作为一个DataFrame显式传递给所有下游的训练器函数。
2025-07-14:模型训练与并发问题集中攻坚
开发者: lyf
10:16 - 修复训练器层 KeyError
- 问题: 所有模型训练均因
KeyError: "['sales', 'price'] not in index"
失败。 - 分析: 训练器硬编码的特征列表中包含了数据源中不存在的
'price'
列。 - 修复: 从所有四个训练器 (
mlstm
,transformer
,tcn
,kan
) 的features
列表中移除了对不存在的'price'
列的依赖。
10:38 - 修复数据标准化层 KeyError
- 问题: 修复后出现新错误
KeyError: "['sales'] not in index"
。 - 分析:
server/utils/multi_store_data_utils.py
中的standardize_column_names
函数列名映射错误,且缺少最终列选择机制。 - 修复: 修正了列名映射,并增加了列选择机制,确保函数返回的
DataFrame
结构统一且包含sales
列。
11:04 - 修复JSON序列化失败问题
- 问题: 训练完成后,因
Object of type float32 is not JSON serializable
导致前后端通信失败。 - 分析: 训练产生的评估指标是NumPy的
float32
类型,无法被标准json
库序列化。 - 修复: 在
server/utils/training_process_manager.py
中增加了convert_numpy_types
辅助函数,在通过WebSocket或API返回数据前,将所有NumPy数值类型转换为Python原生类型,从根源上解决了所有序列化问题。
11:15 - 修复MAPE计算错误
- 问题: 训练日志显示
MAPE: nan%
并伴有RuntimeWarning: Mean of empty slice.
。 - 分析: 当测试集中的所有真实值都为0时,计算MAPE会导致对空数组求平均值。
- 修复: 在
server/analysis/metrics.py
中增加条件判断,若不存在非零真实值,则直接将MAPE设为0。
11:41 - 修复“按店铺训练”页面列表加载失败
- 问题: “选择店铺”的下拉列表为空。
- 分析:
standardize_column_names
函数错误地移除了包括店铺元数据在内的非训练必需列。 - 修复: 将列筛选的逻辑从通用的
standardize_column_names
函数中移出,精确地应用到仅为模型训练准备数据的函数中。
13:00 - 修复“按店铺训练-所有药品”模式
- 问题: 选择“所有药品”训练时,因
product_id
被错误地处理为字符串"unknown"
而失败。 - 修复: 在
server/core/predictor.py
中拦截"unknown"
ID,并将其意图正确地转换为“聚合此店铺的所有产品数据”。同时扩展了aggregate_multi_store_data
函数,使其支持按店铺ID进行聚合。
14:19 - 修复并发训练中的稳定性问题
- 问题: 并发训练时出现
API列表排序错误
和WebSocket连接错误
。 - 修复:
- 排序: 在
api.py
中为None
类型的start_time
提供了默认值,解决了TypeError
。 - 连接: 在
socketio.run()
调用时增加了allow_unsafe_werkzeug=True
参数,解决了调试模式下Socket.IO与Werkzeug的冲突。
- 排序: 在
15:30 - 根治模型训练中的维度不匹配问题
- 问题: 所有模型训练完成后,评估指标
R²
始终为0.0。 - 根本原因:
server/utils/data_utils.py
的create_dataset
函数在创建目标数据集dataY
时,错误地保留了一个多余的维度。同时,模型文件 (mlstm_model.py
,transformer_model.py
) 的输出也存在维度问题。 - 最终修复:
- 数据层: 在
create_dataset
中使用.flatten()
修正了y
标签的维度。 - 模型层: 在所有模型的
forward
方法最后增加了.squeeze(-1)
,确保模型输出维度正确。 - 训练器层: 撤销了所有为解决此问题而做的临时性维度调整,恢复了最直接的损失计算。
- 数据层: 在
16:10 - 修复“全局模型训练-所有药品”模式
- 问题: 与“按店铺训练”类似,全局训练的“所有药品”模式也因
product_id="unknown"
而失败。 - 修复: 采用了与店铺训练完全相同的修复模式。在
predictor.py
中拦截"unknown"
并将其意图转换为真正的全局聚合(product_id=None
),并扩展aggregate_multi_store_data
函数以支持此功能。
2025-07-15:端到端修复“按药品预测”图表功能
开发者: lyf
10:00 - 阶段一:修复数据库写入失败 (sqlite3.IntegrityError
)
- 问题: 后端日志显示
datatype mismatch
。 - 分析:
save_prediction_result
函数试图将复杂Python对象直接存入数据库。 - 修复: 在
server/api.py
中,执行数据库插入前,使用json.dumps()
将复杂对象序列化为JSON字符串。
10:30 - 阶段二:修复API响应结构与前端不匹配
- 问题: 图表依然无法渲染。
- 分析: 前端期望
history_data
在顶层,而后端将其封装在data
子对象中。 - 修复: 修改
server/api.py
的predict
函数,将关键数据提升到响应的根级别。
11:00 - 阶段三:修复历史数据与预测数据时间不连续
- 问题: 图表数据在时间上完全脱节。
- 分析: 获取历史数据的逻辑总是取整个数据集的最后30条,而非预测起始日期之前的30条。
- 修复: 在
server/api.py
中增加了正确的日期筛选逻辑。
14:00 - 阶段四:重构数据源,根治数据不一致问题
- 问题: 历史数据(绿线)与预测数据(蓝线)的口径完全不同。
- 根本原因: API层独立加载原始数据画图,而预测器使用聚合后数据预测。
- 修复 (重构):
- 修改
server/predictors/model_predictor.py
,使其返回预测结果的同时,也返回其所使用的、口径一致的历史数据。 - 彻底删除了
server/api.py
中所有独立加载历史数据的冗余代码,确保了数据源的唯一性。
- 修改
15:00 - 阶段五:修复图表X轴日期格式问题
- 问题: X轴显示为混乱的GMT格式时间戳。
- 分析:
history_data
中的Timestamp
对象未被正确格式化。 - 修复: 在
server/api.py
中,为history_data
增加了.strftime('%Y-%m-%d')
的格式化处理。
16:00 - 阶段六:修复模型“学不会”的根本原因 (超参数传递中断)
- 问题: 即便流程正确,所有模型的预测结果依然是无法学习的直线。
- 根本原因:
server/core/predictor.py
在调用训练器时,没有将sequence_length
等关键超参数传递下去,导致所有模型都使用了错误的默认值。 - 修复:
- 修改
server/core/predictor.py
,在调用中加入超参数的传递。 - 修改所有四个训练器文件,使其能接收并使用这些参数。
- 修改
2025-07-16:最终验证与项目总结
开发者: lyf
10:00 - 阶段七:最终验证与结论
- 问题: 在修复所有代码问题后,对特定日期的预测结果依然是平线。
- 分析: 通过编写临时数据分析脚本 (
temp_check_parquet.py
) 最终确认,这是数据本身的问题。我们选择的预测日期在样本数据集中恰好处于一个“零销量”的空白期。 - 最终结论: 系统代码已完全修复。图表上显示的平线,是模型对“零销量”历史做出的正确且符合逻辑的反应。
11:45 - 项目总结与文档归档
- 任务: 根据用户要求,回顾整个调试过程,将所有问题、解决方案、优化思路和最终结论,按照日期和时间顺序,整理并更新到本开发日志中,形成一份高质量的技术档案。
- 结果: 本文档已更新完成。