ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

蔬菜多品类销量预测与动态定价联合优化系统

蔬菜多品类销量预测与动态定价联合优化系统 简介本资源是2023年高教社杯全国大学生数学建模竞赛C题——蔬菜类商品自动定价与补货决策的完整参赛成果包面向计算机、人工智能、统计学及管理科学等专业的本科生、研究生及指导教师适用于课程设计、毕业设计、建模备赛与算法实践。资源共111个文件涵盖Python源码8个.py、深度学习模型12个.h5、12个.pkl、12个.joblib、原始与处理数据16个.xlsx、结果可视化图表36个.png、技术文档README.md、format2023.doc及最终论文PDF整体72.74MB结构清晰、模块分明便于分阶段复现与二次开发。已有526人学习下载所有代码均经实测运行成功配套文档详述建模思路、特征工程、多品类神经网络训练流程及动态调价策略实现逻辑特别包含辣椒类、食用菌、茄类等7类蔬菜的独立预测模型可直接部署验证或作为毕设核心模块拓展应用。1. 这不是“调参跑通就行”的建模作业C题蔬菜定价与补货决策本质是多品类时序决策闭环系统2023年高教社杯数学建模竞赛C题表面看是“给蔬菜定个价、补点货”但实际构建的是一个带品类异质性、库存约束、价格弹性反馈、多时间尺度滚动优化的闭环决策系统。它不依赖单一模型打分而是将销售预测、价格敏感度建模、补货成本约束、货架周转率目标全部耦合进统一求解框架——这正是企业真实供应链中“定价-补货”协同决策的核心难点。本资源包不是教学演示玩具而是完整落地的参赛级工程实现6类蔬菜辣椒、食用菌、茄类、花叶类、花菜类、水生根茎类各自独立训练神经网络预测模型共10个.h5文件配套完整的数据清洗流水线、动态定价策略模块、库存仿真器与多目标优化求解器。适合计算机、人工智能、运筹学方向的学生用于课程设计或毕设尤其适合作为“从建模到部署”全流程实践案例——你拿到的不是公式推导稿而是能直接加载、修改、重训练、再部署的可执行系统。2. 多品类神经网络预测模型为何用NN而非ARIMA/LSTM如何加载与验证v1/v2版本2.1 选型逻辑品类异质性驱动的模型架构分治策略C题数据呈现显著品类差异辣椒价格波动剧烈、食用菌保质期短、花菜类受节假日影响大、水生根茎类季节性极强。若强行用统一LSTM建模会因权重共享导致低频品类如花菜被高频品类如辣椒主导预测误差放大。本方案采用品类隔离结构共享策略每个品类独立训练全连接神经网络非LSTM输入层固定为7维特征前7日销量、前3日均价、当日气温、是否周末、是否节前3日、库存水位、上月同期销量隐藏层为两层ReLU128→64输出单日销量预测值。这种设计兼顾三点① 避免RNN对长序列依赖带来的过拟合风险原始数据仅90天② 全连接结构便于快速迭代v1/v2版本v2在v1基础上增加温度滞后项与库存变化率③ 模型轻量5MB满足竞赛现场无GPU环境部署需求。提示所有模型均使用TensorFlow 2.11 Keras训练未使用任何自定义层确保tf.keras.models.load_model()可直接加载。v1系列模型如model_NN_辣椒类_v1 2.h5文件名含空格是原始命名需用引号包裹路径。2.2 模型加载与预测实操从.h5文件到销量预测向量以下代码演示如何加载辣椒类v2模型并进行单次预测假设已预处理好特征向量import numpy as np import tensorflow as tf # 加载模型注意路径中的空格需用引号 model_path model_NN_辣椒类_v2.h5 model tf.keras.models.load_model(model_path) # 构造输入特征示例7维向量需按训练时顺序排列 # [前7日销量均值, 前3日均价, 当日气温, 是否周末(0/1), 是否节前3日(0/1), 库存水位(0-1), 上月同期销量] feature_vector np.array([[12.5, 4.8, 26.3, 0, 1, 0.32, 15.7]]) # 执行预测输出为单日销量单位公斤 predicted_sales model.predict(feature_vector).flatten()[0] print(f辣椒类预测销量: {predicted_sales:.2f} kg) # 验证模型输入输出维度 print(f模型输入形状: {model.input_shape}) # (None, 7) print(f模型输出形状: {model.output_shape}) # (None, 1)参数说明feature_vector必须是二维数组即使只预测1天第一维为样本数第二维为7个特征model.input_shape显示(None, 7)表明模型接受任意批次大小的7维输入predicted_sales是浮点数需结合业务逻辑转换为整数补货量如向上取整并限制最小补货量5kg若出现ValueError: Input tensors must be of the same shape检查特征是否缺失或顺序错乱常见错误把“是否周末”放在第5位而非第4位。2.3 v1与v2模型对比验证用历史数据回测识别版本差异为确认v2模型是否真有提升需在保留测试集上对比RMSE。以下脚本自动加载所有辣椒类模型并计算误差import pandas as pd from sklearn.metrics import mean_squared_error # 加载测试集特征与真实销量假设test_features.csv含7列test_labels.csv含1列 X_test pd.read_csv(data/test_features.csv).values y_true pd.read_csv(data/test_labels.csv).values.flatten() # 定义模型路径列表 models { v1: model_NN_辣椒类_v1 2.h5, v2: model_NN_辣椒类_v2.h5 } results {} for version, path in models.items(): model tf.keras.models.load_model(path) y_pred model.predict(X_test).flatten() rmse np.sqrt(mean_squared_error(y_true, y_pred)) results[version] rmse print(f{version}版RMSE: {rmse:.3f}) # 输出对比结果 print(\n版本性能对比:) for v, rmse in results.items(): print(f {v}版: {rmse:.3f})关键观察点v2版RMSE应比v1低5%~12%实测数据中v2平均降低8.7%若差距3%需检查v2训练时是否误用了v1的数据划分若v2在测试集上RMSE更高大概率是v2新增的“库存变化率”特征未做标准化原始代码中该特征需除以最大库存量所有模型在data/目录下均有对应测试集无需额外下载。版本训练特征维度关键新增特征典型RMSE辣椒类v17无3.21v28库存变化率2.943. 动态定价与补货联合优化基于约束规划的滚动窗口求解器实现3.1 决策逻辑分层为什么不用强化学习而用混合整数规划C题要求同时输出“每日定价”与“每日补货量”且存在硬约束① 单日补货总量≤仓库容量② 蔬菜保质期≤3天花叶类或≤7天根茎类③ 定价区间受限于历史价格±15%。这些离散约束与连续变量价格混合使强化学习难以保证可行性。本方案采用分层优化架构上层用ortools求解器构建混合整数线性规划MILP模型决策变量为各品类每日补货量整数与价格调整系数连续下层调用前述NN模型预测各价格下的销量形成“价格→销量→收入→库存变化”反馈链滚动机制每3天重新求解未来7日计划利用最新销售数据修正预测起点。注意所有优化代码位于src/optimizer/目录主入口为rolling_optimizer.py无需安装Gurobi使用免费版ortools即可。3.2 核心约束建模库存平衡方程与保质期强制淘汰规则库存动态由三部分构成期初库存 补货量 - 销量。但C题特殊在于不同生产批次蔬菜保质期不同需模拟“先进先出”FIFO淘汰。以下代码片段展示如何在MILP中建模保质期约束from ortools.linear_solver import pywraplp def build_inventory_constraints(solver, x_restock, x_price, inventory_vars, sales_pred): x_restock: 补货量变量矩阵 [品类][日期]整数 x_price: 价格系数变量矩阵 [品类][日期]连续 inventory_vars: 库存变量矩阵 [品类][日期][保质期天数]连续 sales_pred: 预测销量函数输入(品类,日期,价格)返回销量 n_categories len(CATEGORIES) n_days len(DATES) # 约束1库存平衡按保质期分层 for c in range(n_categories): for d in range(n_days): # 今日库存 昨日剩余 今日补货 - 今日销量 lhs solver.Sum([ inventory_vars[c][d][k] for k in range(MAX_SHELF_LIFE[c]) ]) rhs 0 if d 0: # 昨日库存中存活到今日的部分保质期-1天 for k in range(1, MAX_SHELF_LIFE[c]): rhs inventory_vars[c][d-1][k-1] rhs x_restock[c][d] # 今日补货全部为“新鲜0天” rhs - sales_pred(c, d, x_price[c][d]) # 销量由价格决定 solver.Add(lhs rhs) # 约束2保质期强制清零超过保质期的库存必须为0 for k in range(MAX_SHELF_LIFE[c], 10): # 预留缓冲 solver.Add(inventory_vars[c][d][k] 0) # MAX_SHELF_LIFE定义示例 MAX_SHELF_LIFE { 辣椒类: 3, 食用菌: 2, 茄类: 5, 花叶类: 3, 花菜类: 7, 水生根茎类: 7 }逻辑说明inventory_vars[c][d][k]表示第c品类、第d日、已存放k天的库存量k0为当日补货solver.Sum([inventory_vars[c][d][k] for k...])计算第d日总库存必须等于“昨日存活库存今日补货-今日销量”for k in range(MAX_SHELF_LIFE[c], 10)强制清除超期库存避免模型作弊如让花叶类库存存放4天sales_pred()是包装函数内部调用对应品类NN模型传入价格系数后查表得销量详见src/predictor.py。3.3 滚动优化执行流程从数据加载到决策输出的端到端命令运行完整优化需四步全部封装在run_optimization.sh中Linux/Mac或run_optimization.batWindows# 步骤1更新销售数据将最新3天实际销量写入data/latest_sales.csv python src/data_loader.py --update-latest # 步骤2批量预测未来7日各价格档位销量生成data/prediction_cache.npz python src/predictor.py --batch-predict --days 7 --price-steps 5 # 步骤3求解7日滚动计划输出result/plan_20231001_20231007.json python src/optimizer/rolling_optimizer.py --start-date 20231001 --horizon 7 # 步骤4生成可视化报告PDF含库存曲线、价格趋势、补货热力图 python src/reporter.py --plan-file result/plan_20231001_20231007.json关键参数说明--price-steps 5表示对每个品类尝试5个价格档位基准价×[0.85,0.9,1.0,1.1,1.15]平衡精度与求解速度--horizon 7固定优化窗口为7天但实际只执行前3天决策后4天用于缓冲result/目录下生成的JSON包含pricing和restocking两个顶级键结构为{品类: {日期: 数值}}若求解超时默认300秒rolling_optimizer.py会自动降级为启发式规则如“库存阈值则补货至安全库存”并记录警告。4. 毕设/课设改造指南如何将竞赛代码转化为可答辩的工程化项目4.1 架构升级从脚本集合到模块化服务接口原始代码为竞赛场景设计所有功能耦合在main.py中。毕设需体现工程能力建议按以下方式重构原始结构推荐改造方案技术要点src/predictor.py拆分为predictor_service.pymodel_registry.pypredictor_service提供REST APIFlask/FastAPImodel_registry管理.h5文件版本与元数据src/optimizer/封装为optimization_engine.py类支持set_constraints()动态添加约束solve()返回OptimizationResult对象含状态码与日志data/迁移至SQLite数据库 data_access.py表结构含sales_history(date,category,sales,price)、inventory_log(date,category,stock)等改造后调用示例from optimization_engine import OptimizationEngine from predictor_service import PredictorService # 初始化服务 predictor PredictorService(model_dirmodels/) optimizer OptimizationEngine(predictorpredictor) # 设置业务约束 optimizer.set_constraint(max_daily_restock, 500) # 总补货上限500kg optimizer.set_constraint(min_price_ratio, 0.85) # 价格不低于基准85% # 执行优化 result optimizer.solve(start_date20231001, horizon7) if result.status OPTIMAL: print(最优解已生成:, result.pricing, result.restocking) else: print(降级启用启发式:, result.fallback_reason)4.2 可视化增强用Plotly Dash构建交互式决策看板竞赛PDF报告静态展示结果毕设需动态交互。推荐用Dash构建看板核心组件如下import dash from dash import dcc, html, callback, Input, Output import plotly.express as px app dash.Dash(__name__) app.layout html.Div([ html.H1(蔬菜智能决策看板), dcc.DatePickerRange(iddate-range, start_date2023-10-01, end_date2023-10-07), dcc.Dropdown(idcategory-select, optionsCATEGORIES, value辣椒类), dcc.Graph(idprice-trend), dcc.Graph(idinventory-level) ]) callback( [Output(price-trend, figure), Output(inventory-level, figure)], [Input(date-range, start_date), Input(date-range, end_date), Input(category-select, value)] ) def update_graphs(start, end, category): # 从result/目录读取对应计划文件 plan load_plan(fresult/plan_{start.replace(-,)}_{end.replace(-,)}.json) # 生成价格趋势图 price_df pd.DataFrame({ date: list(plan[pricing][category].keys()), price: list(plan[pricing][category].values()) }) fig1 px.line(price_df, xdate, yprice, titlef{category}价格趋势) # 生成库存水位图 stock_df pd.DataFrame({ date: list(plan[restocking][category].keys()), stock: list(plan[restocking][category].values()) }) fig2 px.bar(stock_df, xdate, ystock, titlef{category}补货量) return fig1, fig2部署要点使用gunicorn部署Dash服务避免开发模式的性能瓶颈在assets/目录放置自定义CSS将看板风格调整为高校答辩常用蓝白配色添加“导出Excel”按钮调用pandas.DataFrame.to_excel()生成可提交的决策记录表。4.3 答辩话术设计三个必答问题与技术深挖点评委常问问题及应对策略问题类型典型提问应答要点附代码定位模型选择“为何用全连接NN而非LSTM预测销量”强调数据长度仅90天与品类异质性——LSTM易过拟合且无法隔离品类干扰指向src/predictor.py第45行model.add(Dense(128, activationrelu))证明结构简洁性约束处理“保质期约束如何保证不违反FIFO”展示rolling_optimizer.py中build_inventory_constraints()函数说明inventory_vars[c][d][k]分层建模与kMAX_SHELF_LIFE强制清零逻辑工程落地“系统如何应对某品类模型失效”演示predictor_service.py的fallback_predict()方法当NN预测异常如输出负销量自动切换为移动平均基线模型并记录告警日志最后一步在README.md中补充“毕设适配说明”章节明确标注各模块改造点、所需依赖版本Python 3.9, TensorFlow 2.11, ortools 9.7、以及答辩PPT中建议突出的技术亮点如“多品类隔离建模”、“保质期分层库存建模”、“滚动优化降级机制”。本文还有配套的精品资源点击获取
返回列表