2025-07-25 15:06:39 +08:00
|
|
|
|
# 项目快速上手指南 (v2.0 - 2025年7月版)
|
2025-07-17 15:52:04 +08:00
|
|
|
|
|
2025-07-25 15:06:39 +08:00
|
|
|
|
欢迎加入项目!本指南旨在帮助你快速理解项目的核心功能、最新的技术架构和开发流程。
|
2025-07-17 15:52:04 +08:00
|
|
|
|
|
2025-07-25 15:06:39 +08:00
|
|
|
|
## 1. 项目核心功能
|
2025-07-17 15:52:04 +08:00
|
|
|
|
|
2025-07-25 15:06:39 +08:00
|
|
|
|
这是一个基于历史销售数据的 **智能销售预测系统**,其核心是实现一个 **"数据 -> 训练 -> 模型 -> 预测 -> 可视化"** 的完整闭环。
|
2025-07-17 15:52:04 +08:00
|
|
|
|
|
2025-07-25 15:06:39 +08:00
|
|
|
|
所有功能均通过Web界面操作:
|
|
|
|
|
1. **模型训练**: 用户可以选择某个**药品**、某个**店铺**或**全局**数据,然后选择一种机器学习算法(如Transformer、KAN等)进行训练。训练过程是**异步**的,并能通过WebSocket实时反馈进度。
|
2025-07-17 15:52:04 +08:00
|
|
|
|
2. **销售预测**: 使用已经训练好的模型,对未来的销量进行预测。
|
|
|
|
|
3. **结果可视化**: 将历史销量和预测销量在同一个图表中展示出来,方便用户直观地看到趋势。
|
2025-07-25 15:06:39 +08:00
|
|
|
|
4. **模型与历史管理**: 提供对已训练模型和历史预测记录的查询、详情查看和删除功能。
|
2025-07-17 15:52:04 +08:00
|
|
|
|
|
2025-07-25 15:06:39 +08:00
|
|
|
|
## 2. 技术栈
|
2025-07-17 15:52:04 +08:00
|
|
|
|
|
2025-07-25 15:06:39 +08:00
|
|
|
|
| 层面 | 本项目技术 | 说明 |
|
|
|
|
|
| :--- | :--- | :--- |
|
|
|
|
|
| **后端框架** | **Flask** | 轻量级的Python Web框架,用于提供API接口。 |
|
|
|
|
|
| **前端框架** | **Vue.js** | 用于构建用户交互界面的现代化JavaScript框架。 |
|
|
|
|
|
| **核心算法库** | **PyTorch** | 实现深度学习算法的核心库。 |
|
|
|
|
|
| **数据处理** | **Pandas** | Python中用于数据分析和处理的核心库。 |
|
|
|
|
|
| **数据库** | **SQLite** | 一个轻量级的本地文件数据库,用于记录模型元数据和预测历史。 |
|
|
|
|
|
| **实时通信** | **Flask-SocketIO** | 用于后端在训练时向前端实时推送日志和进度。 |
|
|
|
|
|
| **异步任务** | **multiprocessing** | Python标准库,用于将耗时的训练任务放到独立的子进程中执行,避免阻塞API服务。 |
|
2025-07-17 15:52:04 +08:00
|
|
|
|
|
2025-07-25 15:06:39 +08:00
|
|
|
|
## 3. 系统架构与数据流
|
2025-07-17 15:52:04 +08:00
|
|
|
|
|
2025-07-25 15:06:39 +08:00
|
|
|
|
本项目是经典的前后端分离架构,其数据流和核心组件如下:
|
2025-07-17 15:52:04 +08:00
|
|
|
|
|
|
|
|
|
```
|
2025-07-25 15:06:39 +08:00
|
|
|
|
+-----------------------------------------------------------------+
|
|
|
|
|
| 用户 (Browser - Vue.js) |
|
|
|
|
|
+-----------------------------------------------------------------+
|
|
|
|
|
| (1. HTTP/WebSocket请求)
|
|
|
|
|
+-----------------------------------------------------------------+
|
|
|
|
|
| 后端API层 (Backend API - Flask) |
|
|
|
|
|
| - api.py: 定义所有RESTful接口 (e.g., /api/training) |
|
|
|
|
|
| - 接收请求, 验证参数, 调用核心服务层 |
|
|
|
|
|
+-----------------------------------------------------------------+
|
|
|
|
|
| (2. 调用核心服务)
|
|
|
|
|
+-----------------------------------------------------------------+
|
|
|
|
|
| 核心服务与管理层 (Core Services) |
|
|
|
|
|
| - training_process_manager.py: 异步训练任务管理器 (关键) |
|
|
|
|
|
| - model_manager.py: 模型保存、加载、版本控制 (关键) |
|
|
|
|
|
| - model_registry.py: 算法与训练器的注册表 (关键) |
|
|
|
|
|
+-----------------------------------------------------------------+
|
|
|
|
|
| (3. 执行具体任务)
|
|
|
|
|
+-----------------------------------------------------------------+
|
|
|
|
|
| 算法实现与数据处理层 (Algorithm & Data) |
|
|
|
|
|
| - trainers/*.py: 具体的算法训练逻辑 (e.g., kan_trainer.py) |
|
|
|
|
|
| - predictors/model_predictor.py: 模型加载与预测逻辑 |
|
|
|
|
|
| - models/*.py: PyTorch模型定义 (e.g., kan_model.py) |
|
|
|
|
|
| - utils/data_utils.py: 数据预处理和转换工具 |
|
|
|
|
|
+-----------------------------------------------------------------+
|
|
|
|
|
| (4. 读写物理文件)
|
|
|
|
|
+-----------------------------------------------------------------+
|
|
|
|
|
| 物理存储层 (Storage) |
|
|
|
|
|
| - data/*.parquet: 原始时序数据 |
|
|
|
|
|
| - saved_models/*.pth: 训练好的模型文件 (权重、配置、缩放器) |
|
|
|
|
|
| - saved_predictions/*.json: 详细的预测结果文件 |
|
2025-07-25 16:32:07 +08:00
|
|
|
|
| - prediction_history.db: SQLite数据库 (存储元数据和文件路径索引) |
|
2025-07-25 15:06:39 +08:00
|
|
|
|
+-----------------------------------------------------------------+
|
2025-07-17 15:52:04 +08:00
|
|
|
|
```
|
|
|
|
|
|
2025-07-25 15:06:39 +08:00
|
|
|
|
## 4. 核心工作流详解:“数据 -> 训练 -> 预测”
|
|
|
|
|
|
|
|
|
|
#### **步骤一:数据准备**
|
|
|
|
|
- **原始数据**: 存储在 [`data/timeseries_training_data_sample_10s50p.parquet`](data/timeseries_training_data_sample_10s50p.parquet)。
|
2025-07-25 16:32:07 +08:00
|
|
|
|
- **数据存储模式**: 本项目采用“数据库作索引,文件系统存内容”的设计模式。
|
|
|
|
|
- **元数据 (索引)**: 存储在根目录的 `prediction_history.db` SQLite数据库中。它只记录轻量级的元信息(如模型版本、预测参数)和指向真实数据文件的**路径**。
|
|
|
|
|
- **真实数据 (内容)**:
|
|
|
|
|
- **模型**: 训练好的模型(`.pth`文件)存放在 [`saved_models/`](saved_models/) 目录。
|
|
|
|
|
- **预测结果**: 详细的预测数据(`.json`文件)存放在 [`saved_predictions/`](saved_predictions/) 目录。
|
2025-07-25 15:06:39 +08:00
|
|
|
|
|
|
|
|
|
#### **步骤二:模型训练 (异步)**
|
|
|
|
|
1. **API触发**: 前端调用 `POST /api/training` ([`server/api.py`](server/api.py:815))。
|
|
|
|
|
2. **任务提交**: `api.py` 将训练请求提交给**训练进程管理器** (`training_process_manager`),并立即返回一个任务ID,不阻塞主服务。
|
|
|
|
|
3. **动态执行**:
|
|
|
|
|
* 管理器在**新的子进程**中运行任务。
|
|
|
|
|
* 它通过**模型注册表** (`model_registry`) 找到 `model_type` 对应的训练器函数(例如,`kan` -> `kan_trainer.py` 中的函数)。
|
|
|
|
|
* 训练器加载数据,进行归一化,然后执行PyTorch训练循环。
|
|
|
|
|
4. **模型保存**:
|
|
|
|
|
* 训练完成后,调用**模型管理器** (`model_manager`) 的 `save_model` 方法。
|
|
|
|
|
* 模型(权重、配置、缩放器)被打包保存在 [`saved_models/`](saved_models/) 目录下,命名如 `kan_product_P001_v1.pth`。
|
|
|
|
|
* 模型的元数据(路径、版本、指标)被写入数据库的 `model_versions` 表。
|
|
|
|
|
|
|
|
|
|
#### **步骤三:模型预测 (同步)**
|
|
|
|
|
1. **API触发**: 前端调用 `POST /api/prediction` ([`server/api.py`](server/api.py:1273))。
|
|
|
|
|
2. **模型定位**: `api.py` 调用**模型管理器** (`model_manager`),根据参数从数据库中找到对应的模型文件路径。
|
|
|
|
|
3. **加载与预测**:
|
|
|
|
|
* 核心逻辑在 [`server/predictors/model_predictor.py`](server/predictors/model_predictor.py) 的 `load_model_and_predict` 函数中。
|
|
|
|
|
* 该函数加载 `.pth` 文件,并利用其中的 `config` 和 `state_dict` **精确重建模型实例**。
|
|
|
|
|
* 执行**自回归预测**:预测一天,将结果作为下一天输入的一部分,循环往复。
|
|
|
|
|
4. **结果保存**:
|
|
|
|
|
* 完整的预测结果(历史、预测、分析等)被保存为一个JSON文件到 [`saved_predictions/`](saved_predictions/) 目录。
|
|
|
|
|
* 该次预测的元数据(包括JSON文件路径)被写入数据库的 `prediction_history` 表。
|
|
|
|
|
5. **返回与渲染**: 完整的JSON结果被返回给前端,前端使用图表库进行可视化。
|
2025-07-17 15:52:04 +08:00
|
|
|
|
|
|
|
|
|
## 5. 如何添加一个新的算法?(开发者指南)
|
|
|
|
|
|
2025-07-25 15:06:39 +08:00
|
|
|
|
假设你要添加一个名为 `NewNet` 的新算法。
|
2025-07-17 15:52:04 +08:00
|
|
|
|
|
|
|
|
|
**目标**: 让 `NewNet` 出现在前端的“模型类型”下拉框中,并能成功训练和预测。
|
|
|
|
|
|
2025-07-25 15:06:39 +08:00
|
|
|
|
1. **创建模型定义文件**:
|
|
|
|
|
* 在 `server/models/` 目录下,创建 `newnet_model.py`。
|
|
|
|
|
* 在其中定义你的 `NewNet` 模型类,继承自 `torch.nn.Module`。
|
|
|
|
|
|
|
|
|
|
2. **创建训练器文件**:
|
|
|
|
|
* 在 `server/trainers/` 目录下,创建 `newnet_trainer.py`。
|
|
|
|
|
* 复制一份现有训练器(如 `kan_trainer.py`)的内容作为模板。
|
|
|
|
|
* **关键修改**:
|
|
|
|
|
* 导入你的 `NewNet` 模型。
|
|
|
|
|
* 在训练函数中,实例化你的 `NewNet` 模型。
|
|
|
|
|
* 在保存checkpoint时,确保 `config` 字典里包含了重建 `NewNet` 所需的所有超参数。
|
|
|
|
|
* 在文件末尾,**注册你的训练器**: `register_trainer('newnet', your_training_function)`。
|
|
|
|
|
|
|
|
|
|
3. **创建预测器逻辑 (如果需要)**:
|
|
|
|
|
* 大多数情况,你可以复用默认的预测器。打开 [`server/predictors/model_predictor.py`](server/predictors/model_predictor.py)。
|
|
|
|
|
* 在 `load_model_and_predict` 函数中,添加一个 `elif loaded_model_type == 'newnet':` 分支,确保它能根据 `config` 正确地创建 `NewNet` 模型实例。
|
|
|
|
|
* 在文件末尾,**注册你的预测器**: `register_predictor('newnet', default_pytorch_predictor)`。如果你的模型有特殊的预测逻辑,可以自定义一个预测函数并注册它。
|
|
|
|
|
|
|
|
|
|
4. **更新前端界面**:
|
|
|
|
|
* 打开 `server/api.py` 中的 `get_model_types` 函数。
|
|
|
|
|
* 在 `model_meta` 字典中添加 `'newnet'` 的元数据,包括名称、描述和标签类型。
|
|
|
|
|
* **无需修改前端代码**,前端的下拉框会自动从这个API获取最新的模型列表。
|
|
|
|
|
|
|
|
|
|
完成以上步骤后,重启服务,你就可以在界面上选择并使用你的新算法了。这个插件式的设计大大简化了新算法的集成过程。
|
|
|
|
|
|
|
|
|
|
## 6. 系统维护与扩展
|
|
|
|
|
|
|
|
|
|
随着系统的持续运行,会不断产生模型文件、预测结果等历史产物。理解如何管理这些产物对于保持系统的健康至关重要。
|
|
|
|
|
|
|
|
|
|
### 6.1. 历史产物管理 (Artifacts Management)
|
|
|
|
|
|
|
|
|
|
**问题**:
|
|
|
|
|
随着时间推移,`saved_models/` 和 `saved_predictions/` 目录下的文件会越来越多,导致项目体积变得臃肿。
|
|
|
|
|
|
|
|
|
|
**当前状态**:
|
|
|
|
|
系统目前依赖**手动清理**。您可以通过Web界面删除单个模型或单条预测历史,程序会自动删除对应的文件。
|
|
|
|
|
|
|
|
|
|
**推荐的解决方案**:
|
|
|
|
|
为了实现自动化管理,推荐创建一个独立的维护脚本,并实施**数据保留策略 (Data Retention Policy)**。
|
|
|
|
|
|
|
|
|
|
#### **自动化清理策略**
|
|
|
|
|
|
|
|
|
|
1. **创建清理脚本**:
|
|
|
|
|
* 可以在 `server/tools/` 目录下创建一个新脚本,例如 `cleanup_artifacts.py`。
|
|
|
|
|
|
|
|
|
|
2. **定义保留规则**:
|
|
|
|
|
* **对于预测结果 (`.json` in `saved_predictions/`)**:
|
|
|
|
|
* **基于时间**: 只保留最近30天的记录。
|
|
|
|
|
* **基于数量**: 只保留最新的1000条记录。
|
|
|
|
|
* **对于模型 (`.pth` in `saved_models/`)**:
|
|
|
|
|
* **基于版本**: 只保留每个模型(同一种药品、同一种算法)最新的3个版本。
|
|
|
|
|
* **保留最佳模型**: 始终保留性能最佳的 `best` 版本,不参与自动清理。
|
|
|
|
|
|
|
|
|
|
3. **执行脚本**:
|
|
|
|
|
* 脚本的逻辑是:连接数据库,查询出所有符合清理条件的记录,然后安全地删除硬盘上对应的文件,最后再删除数据库中的条目。
|
|
|
|
|
* 这个脚本可以通过服务器的定时任务(如Linux的Cron Job或Windows的Task Scheduler)设置为每日自动执行。
|
|
|
|
|
|
|
|
|
|
#### **企业级方案:归档到冷存储**
|
|
|
|
|
|
2025-07-25 16:32:07 +08:00
|
|
|
|
对于需要长期保留数据以备审计的场景,更专业的做法是将旧文件归档至廉价的云对象存储(如阿里云OSS, AWS S3等),而不是直接删除。数据库中仅更新文件路径指向云端地址即可。
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 核心概念扫盲:算法、模型、训练与预测
|
|
|
|
|
|
|
|
|
|
对于初次接触AI和数据科学的开发者来说,这些术语可能会令人困惑。本章节旨在用最通俗易懂的方式,解释本项目核心的AI部分是如何工作的。
|
|
|
|
|
|
|
|
|
|
### 1. 一个简单的比喻:学生备考
|
|
|
|
|
|
|
|
|
|
让我们把整个AI预测系统想象成一个准备参加数学考试的学生:
|
|
|
|
|
|
|
|
|
|
* **历史数据 (Data)**:就像是学生的**教科书和练习册** (`pharmacy_sales.xlsx` 文件)。里面包含了大量的历史题目(过去的销售情况)和对应的正确答案。
|
|
|
|
|
* **算法 (Algorithm)**:是学生的**学习方法和大脑结构** (本项目中的 `KAN` 神经网络)。它定义了学生如何去理解问题、寻找规律,但算法本身不包含任何知识。它只是一套空的学习框架。
|
|
|
|
|
* **训练 (Training)**:就是学生**学习和复习**的过程 (`server/trainers/kan_trainer.py` 脚本)。学生通过不断地做练习册上的题(读取历史数据),然后对照答案(真实的销售额),分析自己错在哪里(计算损失/Loss),然后反思并修正自己的解题思路(反向传播与优化)。这个过程会重复很多遍(Epochs),直到学生在模拟考试(测试集)中取得好成绩。
|
|
|
|
|
* **模型 (Model)**:是学生学习完成后,**学到的所有知识和解题技巧** (保存在 `saved_models/` 下的 `.pth` 文件)。它不再是空的大脑框架,而是包含了所有规律和知识、准备好上考场的“成型的知识体系”。
|
|
|
|
|
* **预测 (Prediction)**:就是学生**正式上考场考试**的过程 (`server/predictors/model_predictor.py` 脚本)。我们给学生一套他从未见过的新题目(例如,提供最近30天的数据,让他预测未来7天),学生利用他已经学到的知识(加载`.pth`模型文件),给出他认为最可能的答案(未来的销售额)。
|
|
|
|
|
|
|
|
|
|
### 2. 训练和预测在本项目中的区别与联系
|
|
|
|
|
|
|
|
|
|
**Q: 训练和预测所使用的算法有区别吗?**
|
|
|
|
|
|
|
|
|
|
**A:** 核心算法(大脑结构)是**完全相同**的,都是 `KAN` 网络。但它们所做的事情(功能)截然不同。
|
|
|
|
|
|
|
|
|
|
* **训练 (`train_product_model_with_kan`)**
|
|
|
|
|
* **目标**:**创造一个模型**。
|
|
|
|
|
* **输入**:大量的历史数据(特征+答案)。
|
|
|
|
|
* **过程**:是一个**学习和迭代**的过程。它会反复调整算法内部的参数(权重),目标是让预测结果与真实答案的差距越来越小。这是一个计算量巨大、非常耗时的过程。
|
|
|
|
|
* **输出**:一个 `.pth` 文件,这就是训练好的模型。
|
|
|
|
|
|
|
|
|
|
* **预测 (`load_model_and_predict`)**
|
|
|
|
|
* **目标**:**使用一个已有的模型**。
|
|
|
|
|
* **输入**:一小段最近的历史数据(只有特征,没有答案)。
|
|
|
|
|
* **过程**:是一个**计算和应用**的过程。它加载训练好的`.pth`模型文件,将输入数据“喂”给模型,模型根据已经固化的参数,直接计算出结果。这个过程非常快。
|
|
|
|
|
* **输出**:对未来的预测数据(JSON格式)。
|
|
|
|
|
|
|
|
|
|
**总结**:训练是“从0到1”打造模型的过程,预测是“使用这个1”来解决实际问题的过程。
|
|
|
|
|
|
|
|
|
|
### 3. 模型的具体实现是怎样的?
|
|
|
|
|
|
|
|
|
|
1. **我们如何得到模型?**
|
|
|
|
|
* 我们运行训练脚本 (`uv run train_model`)。
|
|
|
|
|
* 该脚本调用 `kan_trainer.py` 中的 `train_product_model_with_kan` 函数。
|
|
|
|
|
* 这个函数会加载销售数据,对数据进行预处理(例如,将“星期一”转换为数字1,将所有数据缩放到0-1之间以便于神经网络处理)。
|
|
|
|
|
* 然后,它将数据切分成“用连续30天的数据,预测未来7天销量”这样的样本对。
|
|
|
|
|
* 最后,它通过成千上万次的学习迭代,将学到的知识保存为一个 `.pth` 文件。
|
|
|
|
|
|
|
|
|
|
2. **预测的具体实现是怎样的?**
|
|
|
|
|
* 我们通过API请求预测。
|
|
|
|
|
* API调用 `model_predictor.py` 中的 `load_model_and_predict` 函数。
|
|
|
|
|
* 该函数首先根据请求,找到对应的 `.pth` 模型文件并加载它。
|
|
|
|
|
* 然后,它获取预测开始日期前最新的30天真实数据。
|
|
|
|
|
* 它将这30天数据输入模型,得到对未来第1天的预测销量。
|
|
|
|
|
* **关键一步(自回归)**:它将第1天的预测结果,当作“真实发生过”的数据,拼接到历史数据的末尾,并丢掉最老的一天,形成一个新的30天数据序列。
|
|
|
|
|
* 它用这个新的序列去预测第2天的销量。
|
|
|
|
|
* ……如此循环往复,直到预测出未来7天的全部结果。
|
|
|
|
|
|
|
|
|
|
### 4. 我需要具备哪些技术才能理解?
|
|
|
|
|
|
|
|
|
|
这是一个很好的问题,可以分层来看:
|
|
|
|
|
|
|
|
|
|
* **初级(能使用和调试)**:
|
|
|
|
|
* **Python基础**:能读懂基本的Python代码和逻辑。
|
|
|
|
|
* **Pandas库**:了解如何操作和处理表格数据(DataFrame)。我们项目中的数据预处理大量使用Pandas。
|
|
|
|
|
* **理解本章节内容**:对训练和预测有宏观概念,知道输入什么、输出什么即可。
|
|
|
|
|
|
|
|
|
|
* **中级(能修改和优化)**:
|
|
|
|
|
* **PyTorch框架**:了解PyTorch的基本概念,如 `Tensor`(张量)、`nn.Module`(模型结构)、`Optimizer`(优化器)、`DataLoader`(数据加载器)。我们的 `KAN` 模型就是用PyTorch构建的。
|
|
|
|
|
* **机器学习基础概念**:了解什么是特征工程、训练集/测试集、损失函数、过拟合与欠拟合等。
|
|
|
|
|
|
|
|
|
|
* **高级(能设计和创新)**:
|
|
|
|
|
* **深度学习理论**:深入理解神经网络、反向传播等原理。
|
|
|
|
|
* **时间序列分析**:了解ARIMA、LSTM、Transformer等其他时间序列预测模型的原理和优劣。
|
|
|
|
|
|
|
|
|
|
**给您的建议**:
|
|
|
|
|
您现在完全不需要焦虑。从“初级”开始,先尝试理解数据的流转,即数据是如何从文件加载,被Pandas处理,然后输入给训练器或预测器的。当您能熟练地进行使用和调试后,再逐步去了解PyTorch和机器学习的细节。边学边做是最高效的方式。
|