12 KiB
12 KiB
智能药品销售预测系统:技术白皮书与核心SOP
1. 项目概述
本文档旨在为新成员提供一个全面的、由浅入深的项目技术指南,并系统性地沉淀项目在迭代演进过程中的核心设计思想、关键决策和标准作业程序(SOP)。
1.1. 核心价值
本系统是一个基于深度学习和机器学习模型的智能预测平台,旨在解决药品零售行业的核心痛点:
- 精准库存管理:通过对未来销量的精确预测,指导采购与备货,降低库存成本,避免缺货损失。
- 智能化决策支持:为营销活动、人员排班、资金规划等提供量化的、数据驱动的决策依据。
- 多维度洞察:支持从“单品”、“店铺”到“区域全局”等多个维度进行训练和预测,满足不同层级的业务分析需求。
1.2. 技术栈
- 后端: Python, Flask, Socket.IO, SQLAlchemy
- 前端: Vue.js, Element Plus, Chart.js
- AI框架: PyTorch, XGBoost, Scikit-learn
- 核心模型: Transformer, KAN, mLSTM, TCN, CNN-BiLSTM-Attention, XGBoost
- 数据存储: SQLite (用于历史记录), Parquet (用于核心时序数据)
- 版本与进程管理: 自研的
ModelManager
和TrainingProcessManager
2. 核心架构设计
系统采用经典的前后端分离架构,并通过模块化的设计,实现了业务逻辑、AI能力与数据处理的有效解耦。
2.1. 架构分层图
+---------------------+ +-----------------------+ +---------------------+
| 前端 (UI) | <--> | API层 (Flask) | <--> | 核心逻辑层 |
| (Vue.js, Chart.js) | | (api.py, Socket.IO) | | (predictor.py) |
+---------------------+ +-----------------------+ +---------------------+
| |
| |
+-------------------------------------------------------+
|
v
+--------------------------+ +---------------------------+
| AI能力层 (Trainers) | <--> | 模型与算法 (Models) |
| (kan_trainer.py, etc.) | | (kan_model.py, etc.) |
+--------------------------+ +---------------------------+
| |
| |
v v
+-------------------------------------------------------------------+
| 数据与工具层 (Utils) |
| (new_data_loader.py, model_manager.py, training_process_manager.py) |
+-------------------------------------------------------------------+
|
v
+--------------------------+ +---------------------------+
| 数据存储 (Storage) | | 原始数据 (Data) |
| (prediction_history.db) | | (*.parquet) |
+--------------------------+ +---------------------------+
2.2. 核心工作流:“数据 -> 智能”的闭环
- 数据加载: 所有的数据请求都由
server/utils/new_data_loader.py
统一处理。 - 模型训练:
- 前端通过 API层 发起训练请求。
- 进程管理器 (
TrainingProcessManager
) 创建一个独立的后台进程来处理该任务。 - 核心逻辑层 (
predictor.py
) 根据请求参数(如训练模式、范围),从数据加载器获取并预处理数据。 - AI能力层 (具体的
trainer.py
) 被调用,负责执行模型的训练、评估和保存。 - 模型管理器 (
ModelManager
) 负责将训练好的模型,以统一、规范的命名格式保存到磁盘。
- 模型预测:
- 前端通过 API层 发起预测请求。
- 模型管理器 根据请求参数找到正确的模型文件。
- 核心预测器 (
model_predictor.py
) 加载模型,并从数据加载器获取预测所需的历史数据。 - 根据模型类型(自回归 vs 直接输出),执行相应的预测逻辑。
- 结果通过 API层 返回给前端,并在数据库中留下历史记录。
- 结果可视化: 前端使用
Chart.js
将API返回的历史数据和预测数据渲染成趋势图。
3. 项目演进全景回顾
第一阶段:奠基与探索 (早期修复与重构)
此阶段的核心目标是打通系统最基础的“训练->预测”闭环,并解决一系列阻碍核心功能运行的初始Bug。
- 设计思路:采用“问题驱动”的模式,从最表层的UI失败开始,逐层深入,定位并修复了从数据流、模型算法到前后端通信的多个核心问题。
- 关键改动与修复:
- 数据流重构:修复了
predictor.py
中数据处理流程中断,导致特征丢失的根本性问题。 - 模型算法修复:
- 根治了所有PyTorch模型因维度不匹配而无法学习(R²恒为0)的严重Bug。
- 修复了
mLSTM
模型因算法设计缺陷导致预测结果无效的问题。
- 配置持久化:系统性地修复了所有训练器,确保在保存模型时,会将完整的、可用于重新实例化模型的配置写入检查点,解决了除Transformer外所有模型预测失败的问题。
- 版本管理统一:引入了
ModelManager
作为系统中唯一负责版本管理、模型命名和IO的组件,彻底解决了因命名和路径不统一导致模型无法被找到的混乱状况。 - 前后端链路打通:通过修复JSON序列化、API响应结构、数据时间戳连续性和图表日期格式化等一系列问题,最终成功实现了所有预测视图的图表渲染。
- 数据流重构:修复了
第二阶段:涅槃与重生 (核心数据源替换)
此阶段的核心目标是将项目的数据源,从一个简单的、理想化的样本数据,彻底更换为全新的、结构更复杂、更贴近真实业务场景的核心数据集。这是一次“换引擎”级别的大手术。
“更换数据源”标准作业程序 (SOP)
我们在此次重构中,沉淀出了一套可复用的、用于安全更换核心数据源的SOP。
第1步:分析与评估 (Analysis & Assessment)
- 目标:全面理解新旧数据源的差异,识别风险,制定策略。
- 动作:
- 对比新旧
.parquet
文件的Schema(表结构)。 - 识别出**“断裂性变更”**,例如:列名不同 (
subbh
vsstore_id
)、数据类型变化、特征缺失(如is_promotion
)。 - 决策:放弃“直接修改代码以适应新数据”的高风险方案,选择**“适配器模式”**,以最小的侵入性实现兼容。
- 对比新旧
第2步:构建数据适配器 (Adapter Construction)
- 目标:创建一个独立的、统一的数据入口,将“新数据”动态转换为“旧代码能理解的格式”。
- 动作:
- 创建
server/utils/new_data_loader.py
。 - 在该模块中,集中实现所有的数据转换逻辑:
- 列名重映射:
{'subbh': 'store_id', 'hh': 'product_id', ...}
。 - 特征填充:为缺失的
is_promotion
列创建代理并填充默认值0
。 - 数据类型转换:将日期列统一转换为
datetime
对象。
- 列名重映射:
- 创建
第3步:全面重构 (Refactoring)
- 目标:将系统中所有直接读取旧数据的代码,全部重构为通过新的数据适配器获取数据。
- 动作:
- 系统性地修改了所有数据消费端,包括:
api.py
,core/predictor.py
, 以及trainers/
目录下的所有训练器脚本。 - 删除了所有旧的、已废弃的数据加载工具,确保了数据源的唯一性。
- 系统性地修改了所有数据消费端,包括:
第4步:端到端测试与迭代修复 (E2E Testing & Iterative Fixing)
- 目标:在新数据源上,对系统的所有核心功能(所有训练模式、所有预测模式)进行完整测试,并修复因此次变更而引发的所有连锁Bug。
- 关键修复成果:
NaN
值处理:在聚合运算(如“按店铺训练”)后,增加了.fillna(0)
数据清理步骤,解决了因数据稀疏性引入NaN
值而导致的训练失败。- 架构错配修复:
- 问题:
XGBoost
和CnnBiLstmAttention
模型在预测时,被错误地调用了为“自回归”模型设计的循环预测逻辑,导致在自定义预测天数时崩溃或返回无效结果。 - 修复:在
model_predictor.py
中为这两类“直接多步输出”模型创建了专属的、正确的、非循环的预测逻辑分支。
- 问题:
- 全链路参数传递修复:
- 问题:“自定义全局训练”功能因新增的
selected_stores
和selected_products
参数在api.py
->training_process_manager.py
->predictor.py
的调用链中丢失而失败。 - 修复:对整条调用链上的所有相关模块进行了同步升级,确保了复杂参数的完整、正确传递。
- 问题:“自定义全局训练”功能因新增的
- 数据特性澄清:确认了“负销量”是源于真实业务(如退货)的数据特性,并决策在代码层面尊重而非修改它,这是一个重要的技术决策。
第5步:环境清理 (Environment Cleanup)
- 目标:在最终验证前,确保一个完全纯净的、不受任何旧数据或旧模型干扰的系统环境。
- 动作:
- 删除了
saved_models
和saved_predictions
文件夹中的所有历史产物。 - 删除了
prediction_history.db
数据库文件,并验证了系统具备自动重建的能力。
- 删除了
第三阶段:展望 (模型优化与能力升级)
在当前稳定的系统基础上,我们规划了以下四个方向的重点工作,以进一步提升系统的核心价值。
- 特征工程:通过创造时间特征、滞后特征和滑动平均特征,充分挖掘新数据源的潜力,提升模型预测精度。
- 模型可解释性:引入SHAP等工具,让AI模型不再是“黑盒”,为每一次预测提供清晰、量化的归因分析。
- 超参数调优:引入Optuna等自动化调优框架,为每个模型找到其最佳的超参数组合,进一步压榨模型性能。
- 架构限制突破:通过改造训练器和API,最终实现让所有模型都能在训练时自由指定预测天数,提升系统的灵活性和易用性。
4. 系统维护与扩展
4.1. 如何引入一个新模型?
- 创建模型文件:在
server/models/
目录下,创建一个新的模型定义文件(如new_model.py
),确保它是一个标准的PyTorchnn.Module
。 - 创建训练器文件:在
server/trainers/
目录下,创建一个新的训练器文件(如new_model_trainer.py
)。- 参考现有训练器的结构,实现完整的“数据准备->训练循环->评估->保存”逻辑。
- 在文件末尾,使用
@register_trainer('new_model_id', train_function)
将其注册到系统中。
- (可选)创建专属预测器:如果你的新模型不是标准的“自回归”模型(像XGBoost那样),则需要在
server/predictors/model_predictor.py
中为其创建一个专属的预测逻辑分支。 - 更新API:
api.py
会自动通过注册表发现你的新模型,无需修改。
4.2. 系统清理与数据管理
- 清理旧模型:可以直接删除
saved_models/
目录下的.pth
文件。 - 清理旧预测:可以安全地删除
saved_predictions/
目录下的.json
文件和根目录下的prediction_history.db
数据库文件。系统会在下次运行时自动重建。