☰
从数学建模到零售优化:蔬菜定价与补货决策实战解析
2026/10/15 16:14:23 网站建设 项目流程

简介:本资源是2023年全国大学生数学建模竞赛C题——蔬菜类商品自动定价与补货决策优化的完整参赛成果,面向计算机、统计、运筹与管理科学等专业本科生及毕业设计群体,聚焦生鲜供应链中损耗率高、需求波动大、定价与补货协同难等现实问题。压缩包共46个文件(11.9MB),含24个结构化Excel数据表(如单品销售量、平均损耗率、ARIMA与GRU预测结果)、9个Jupyter Notebook分析脚本(覆盖聚类分析、箱线图可视化、混合整数规划求解、回归建模与时序预测)、3个Python主程序(含BONMIN求解器调用)、1份PDF论文定稿及详细README说明文档。已有103人学习下载,提供从原始数据清洗、多模型销量预测(ARIMA/GRU)、品类聚类与损耗建模,到定价-补货联合优化的全流程实现,代码可直接运行,注释清晰,适合作为毕设课题基础框架或建模能力进阶训练材料。

1. 从竞赛题目到真实业务:一次完整的数模实战复盘

去年带队参加全国大学生数学建模竞赛,我们组选的是C题“蔬菜类商品自动定价与补货决策优化”。说实话,拿到题目那一刻,感觉既兴奋又头大。兴奋的是,这题目太“实”了,直接戳中了生鲜零售行业的核心痛点——每天面对几百种蔬菜,到底该卖多少钱?该进多少货?头大的是,这问题背后是典型的“高维、动态、不确定”的商业决策难题,从数据清洗到模型构建,再到最后的策略输出,每一步都是坑。比赛结束后,我们团队把论文、代码和数据都整理了出来,但总觉得缺了点什么。那些写在论文里的“假设”和“简化”,在实际业务中真的行得通吗?那些漂亮的模型曲线,能经得起凌晨三点批发市场嘈杂人声和瞬息万变价格的考验吗?今天,我就以一个过来人的身份,抛开竞赛论文的“学术滤镜”,把这套“蔬菜定价与补货”的优化逻辑,从理论到实践,从代码到业务,掰开揉碎了讲清楚。无论你是对数学建模感兴趣的学生,还是对零售数字化运营有需求的从业者,这篇文章或许能给你一些不一样的启发。

2. 问题本质拆解:定价与补货为何是“连体婴”

在动手建模型、写代码之前,我们必须先想明白:蔬菜的定价和补货,为什么必须放在一起优化?这可不是出题老师故意为难我们,而是生鲜零售业务内在的、无法割裂的孪生问题。

2.1 定价与补货的耦合关系:一个动态博弈

想象一下你是一家社区生鲜店的店长。今天西红柿的进货价涨了,你自然想提高售价来保证利润(定价决策)。但是,如果你提价太高,顾客可能就不买了,导致晚上关门时还剩下一大堆,这些西红柿明天就不新鲜了,只能打折处理甚至扔掉,反而造成更大损失。这里的损失,专业术语叫“损耗”。反过来,如果你为了清库存而大幅降价(定价决策),虽然卖得快了,但单品的利润被摊薄,总体营收可能还是上不去。同时,你今天的销售情况和剩余库存(补货决策的结果),又会直接影响你明天该进多少西红柿(补货决策)。你看,定价直接影响销售速度和库存结余,而库存结余又直接决定了补货需求。这是一个闭环。

在竞赛题目给出的场景里,这种耦合关系被抽象为几个关键约束:成本约束(售价不能低于成本)、需求弹性约束(价格影响销量)、库存容量约束(货架和仓库就那么大)、损耗约束(蔬菜会随时间变质)。我们的优化目标,就是在满足这些约束的前提下,最大化一段时间内的总利润,或者更实际一点,最大化“营收-成本-损耗”的综合收益。很多初次接触的同学容易把问题拆成两步:先根据历史数据预测明天卖多少,然后决定进多少货;再根据进货成本和目标利润率定售价。这看似合理,实则割裂了价格对需求的即时调节作用。正确的思路是建立一个联合决策模型,让定价和补货量作为模型的两个输出变量,同时被优化。

2.2 从竞赛数据到业务数据:我们缺失了什么?

竞赛提供的数据通常是清洗过的、结构化的,比如过去N天各种蔬菜的销售流水、进货记录、成本变动。这已经比很多开放数据集要好了。但根据我们赛后和一些零售业朋友的交流,真实业务数据要复杂和“脏”得多:

  1. 数据粒度问题:竞赛数据往往是“天”级别,但真实促销可能是“小时”级别的(如晚市特价)。蔬菜的新鲜度衰减曲线也不是按天计算的,上午和下午的品相可能就有差异。
  2. 外部因素缺失:竞赛数据很少包含天气、节假日、周边竞品价格、社区活动等信息。而这些因素对蔬菜需求的影响可能比历史销量更大。比如,明天预报有暴雨,大家可能会囤菜,叶菜类需求激增;对面超市黄瓜打五折,你的黄瓜定价就必须反应。
  3. 损耗的量化难题:竞赛中损耗可能用一个简单的线性或指数衰减模型来表示。现实中,损耗与温度、湿度、摆放方式、翻拣次数都有关,极难精确量化。通常,业内会用“报损率”作为一个经验估计值。

所以,我们在构建模型时的第一个重要心得就是:必须明确模型的边界和假设。我们的模型是在“给定数据条件下”的最优,而不是“绝对真理”。在论文和代码中,我们为损耗模型、需求函数都设置了可调节的参数,就是为了让方案具备一定的适应性。接下来,我们就深入模型内部,看看具体是怎么实现的。

3. 核心模型构建:如何用数学语言描述生意

这部分是整篇论文的精华,也是代码实现的核心。我们采用了“数据驱动建模 + 运筹学优化”的混合框架,整体思路分为三步:需求预测、联合建模、策略求解。

3.1 需求预测模型:不仅仅是看昨天卖了什么

定价的基础是预知需求。我们并没有采用复杂的深度学习模型(如LSTM),因为比赛时间有限,且数据量可能不足以支撑深度网络训练,容易过拟合。我们选择了集成树模型(如LightGBM或XGBoost)作为需求预测的核心。为什么?

  • 处理混合类型特征能力强:我们可以轻松地将类别特征(蔬菜品类、星期几)、数值特征(历史价格、历史销量、成本)以及构造的特征(如过去3天的平均销量、与上周同期的销量比、是否节假日)一起扔给模型。
  • 可解释性相对较好:虽然不如线性回归那么直观,但树模型可以提供特征重要性排序。这让我们能知道,影响黄瓜销量的最主要因素是自身价格,还是西红柿的价格(替代品),或者是天气温度。

特征工程是关键中的关键。除了上述基础特征,我们重点构建了几个:

  • 交叉价格弹性特征:计算本品类价格与相关替代品(如黄瓜和西红柿)或互补品(如辣椒和蒜)价格的比例或差值。
  • 衰减特征:对于叶菜类,引入“已上架时间”作为特征,模拟新鲜度下降对需求的影响。
  • 趋势与波动特征:计算销量的移动平均和标准差,捕捉需求的稳定性和趋势。

预测的目标变量不是“明天销量”的绝对点估计,而是价格-销量关系曲线。也就是说,对于一种蔬菜,我们训练模型预测的是,在不同定价水平下,可能的销量分布。这为后续的优化提供了输入。

3.2 联合优化模型:将生意逻辑转化为数学公式

这是最考验运筹学功底的一步。我们建立了一个多周期、多品类的随机规划模型。听起来高大上,其实核心思想就是为一个虚拟的“店长”制定一份未来几天的“作战计划”。

决策变量:

  • x_{i,t}:第i种蔬菜在第t天的补货量。
  • p_{i,t}:第i种蔬菜在第t天的销售定价。
  • I_{i,t}:第i种蔬菜在第t天结束时的库存量。

目标函数(最大化总期望利润):

Maximize Σ_t Σ_i [ E( p_{i,t} * D_{i,t}(p_{i,t}) ) - c_{i,t} * x_{i,t} - h * I_{i,t} - θ * S_{i,t} ]

其中:

  • D_{i,t}(p_{i,t})就是上一步需求预测模型给出的、关于价格的需求函数(通常是一个随机变量,比如服从某个分布)。
  • E(...)表示求期望,因为需求不确定。
  • c_{i,t}是进货成本。
  • h * I_{i,t}是库存持有成本(资金占用、仓储管理)。
  • θ * S_{i,t}是损耗成本,S_{i,t}是损耗量,θ是单位损耗成本(通常≥进货成本,因为包含了处理人工和浪费)。

核心约束条件:

  1. 库存平衡约束:I_{i,t} = I_{i,t-1} + x_{i,t} - D_{i,t}(p_{i,t})。今天的期末库存等于昨天的库存加上今天的进货,再减去今天的销量。
  2. 需求函数约束:D_{i,t}(p_{i,t})服从预测模型给出的分布。这是连接预测与优化的桥梁。
  3. 能力约束:Σ_i x_{i,t} <= C总补货量不能超过物流或仓储能力;I_{i,t} <= S_i单个商品库存不能超过货架容量。
  4. 价格约束:p_{i,t} >= c_{i,t} * (1 + m),售价至少要比成本高出一个最低毛利率m,保证不亏本。

注意:这里的需求函数D(p)是价格p的函数,通常我们假设为线性递减(D = a - b*p)或指数递减(D = a * exp(-b*p))的形式。参数a, b可以通过历史数据回归得到。在随机规划中,a和b也可以是随机变量,以表征预测的不确定性。

3.3 模型求解策略:化繁为简的实用技巧

上述模型是一个含随机变量的非线性规划问题,直接求解非常困难。在竞赛和实际应用中,我们采用了一些简化技巧:

  1. 场景分析法:这是处理随机性的经典方法。我们不直接处理随机变量D_{i,t}(p),而是为其生成多个可能的“场景”。例如,基于历史误差分布,模拟出未来需求“乐观”、“一般”、“悲观”的几种情况。我们的优化目标就变为:最大化在所有场景下的平均利润,或者更稳健一些,最大化在最差场景下的利润(鲁棒优化思想)。我们的代码中实现了场景生成器。
  2. 线性化与离散化:如果需求函数是非线性的,求解会很难。我们可以将价格离散化,例如,每种蔬菜只允许从几个预设的价格点中选择(如[成本*1.3, 成本*1.5, 成本*1.8])。这样,关于价格p的决策就变成了从有限集合中选择,问题可以转化为一个混合整数线性规划问题。虽然损失了一些精度,但求解速度大大提升,可以用专业的求解器(如Gurobi, Cplex)或开源工具(如OR-Tools, PuLP)快速求解。
  3. 滚动优化:我们不会一次性制定未来一周所有日期的死计划。而是采用“滚动时域”策略:每天开始时,根据最新的库存和成本数据,重新运行一次优化模型,制定出当天和未来几天的计划,但只执行当天的决策。第二天,重复这个过程。这样能不断吸收新的信息,调整策略,更适应现实。

我们的代码仓库里,提供了基于Python和PuLP(用于线性规划)的实现示例。核心求解函数大约200行,但围绕它的数据预处理、后处理和分析代码则有上千行。

4. 代码实现与数据处理中的“坑”与“桥”

论文里的模型描述可能看起来很美,但代码实现过程才是“魔鬼细节”的聚集地。这里分享几个我们踩过的坑和搭建的“桥”。

4.1 数据清洗:异常值不是一删了之

题目给的数据通常包含缺失值和异常值。对于缺失的销量或价格,常见的做法是用前后天的均值填充。但对于异常值(比如某天某种蔬菜销量突然暴增或为零),处理需要谨慎。

  • 销量暴增:首先查日历,是不是节假日?或者数据记录是否有误(如单位是“斤”误录为“公斤”)?如果是促销导致,那么这是一个宝贵的“价格弹性”样本,不应该简单删除,而应该将其与当天的价格信息关联起来,用于需求函数的拟合。
  • 销量为零:要区分是“真零”(就是没卖出去)还是“缺货零”(因为没进货所以没得卖)。这需要结合当天的进货记录来判断。如果是“缺货零”,这个样本在训练需求预测模型时应该剔除或特殊标记,因为它不代表零需求,而是供应链中断。

我们的做法是,编写了一个数据诊断报告生成脚本。它会自动识别每种蔬菜销售序列的缺失、零值、突增点,并关联进货数据,给出可能的原因标注,供我们人工复核。这个脚本后来被证明比盲目清洗有用得多。

4.2 需求预测模型的评估陷阱

在训练需求预测模型时,我们犯过一个错误:用全部数据训练,然后用交叉验证评估,得到了很高的R²分数,沾沾自喜。但后来发现,这存在严重的数据泄露问题。因为我们在特征中使用了“当天的价格”,而在实际预测时,第二天的价格是我们需要决策的未知量!

正确的做法是进行时间序列交叉验证。例如,用第1-100天的数据预测第101天的需求,用第1-101天的数据预测第102天的需求,以此类推。这样才能模拟真实的滚动预测场景。评估指标也不应只看R²,更要看在模拟滚动优化环境下,使用预测结果做出的决策能带来多少利润。我们后来增加了一个“模拟回溯测试”模块,用历史数据逐天模拟运行我们的定价补货策略,与历史实际利润对比,这才是最硬的评估标准。

4.3 优化求解器的选择与调试

我们最初使用SciPy的优化库,但在处理几十种商品、多个场景、多周期的问题时,速度慢且容易陷入局部最优。后来切换到PuLP调用CBC求解器(开源),处理线性化后的问题效率很高。对于更复杂的问题,商业求解器如Gurobi有免费学术许可,速度和稳定性是质的飞跃。

一个调试技巧是:先求解一个简化版问题。例如,只选3种有代表性的蔬菜(一个叶菜、一个果菜、一个根茎),优化周期缩短到3天。确保模型逻辑正确、求解器能跑通、结果符合常识(比如价格高时补货应谨慎)。然后再逐步增加品类和周期。我们的代码中保留了多个版本的模型文件(model_simple.py,model_full.py),就是为了方便调试和演示。

5. 从模型输出到业务动作:策略的可解释性与执行

模型输出一堆数字:未来每天每种菜的进货量和建议售价。如何让店长或采购员相信并执行这些“冷冰冰”的数字?这就是模型可解释性和策略柔性化要解决的问题。

5.1 生成“人话”报告:不只是数字

我们的代码最后会生成一份每日决策建议报告,格式如下:

【日期:2023-10-27】 【今日重点】: * 西红柿(品类代码:A01)进货成本上涨15%,但需求弹性较低。建议:**小幅提价10%**,预计销量下降5%,但毛利额增加8%。可维持正常进货量。 * 菠菜(品类代码:B05)库存周转较快,且明日气温下降,预计火锅需求增加。建议:**增加20%的进货量**,价格保持稳定,抓住机会提升销量。 * 土豆(品类代码:C12)库存较高,且未来三天成本稳定。建议:**启动“清库存”促销模式**,降价5%,目标在两天内将库存降至安全线以下。 【风险提示】: * 黄瓜(A03)与竞品价差已缩小至5%以内,若竞品明日促销,我方销量可能下滑20%。请采购部关注市场动态,准备应急调价方案。

这样的报告,把模型的“为什么”讲了出来,结合了业务常识(天气、竞品),给出了明确的行动指令和风险预警,远比只给两个数字更容易被接受。

5.2 设置人工干预接口:尊重业务直觉

再好的模型也只是辅助。我们必须在系统中预设人工干预接口。例如:

  • 价格上下限锁定:店长可以设置某种蔬菜无论如何不能超过某个价格(基于顾客接受度)。
  • 补货量修正系数:如果店长预感到明天有团体采购,他可以手动将某种菜的推荐补货量乘以一个系数(如1.5)。
  • 策略模式选择:模型可以提供不同目标下的策略,如“利润最大化”、“销量最大化”、“损耗最小化”,由管理者根据阶段目标选择。

在我们的代码框架中,这些干预是在优化模型求解之前,以修改输入参数(如需求预测值、约束条件)的方式实现的,而不是在模型输出结果后强行修改。这保证了干预后的决策仍然是内部逻辑自洽的。

6. 项目总结与扩展思考

回顾整个项目,从一道竞赛题出发,我们几乎走完了一个小型数据科学项目的全流程:业务理解、数据准备、建模、求解、评估、部署。最大的收获不是那个奖状,而是对“运筹学如何落地”有了刻骨铭心的体会。

几点核心心得:

  1. 业务第一,模型第二。最开始花在理解“蔬菜定价补货到底在干什么”上的时间,远多于写代码的时间。这个时间值。
  2. 简单模型 + 好特征 > 复杂模型 + 差特征。我们最初想过用强化学习来模拟动态博弈,但后来发现,特征工程扎实的集成树模型+线性规划,在可解释性和求解稳定性上完胜“黑箱”复杂模型。
  3. 不确定性是朋友,不是敌人。通过场景分析、鲁棒优化等方式明确地处理不确定性,得到的策略比假装未来是确定的策略要稳健得多。
  4. 系统要为人服务。最终的输出必须是业务人员能看懂、能信任、能微调的建议,而不是一个无法质疑的“AI圣旨”。

这个框架的扩展性很强。它不仅可以用于蔬菜,稍作修改就能用于水果、鲜奶、短保烘焙食品等所有具有短保质期、需求价格弹性、高损耗率特征的零售商品。模型中的“损耗函数”可以变得更复杂,引入更精细的品相分级(如A级、B级,对应不同价格和需求)。也可以和供应链上游打通,将供应商的供货价格和稳定性作为变量纳入优化。

最后,我们开源了本次竞赛的核心代码和一份简化的示例数据集。代码仓库里包含了数据处理、特征工程、预测建模、优化求解和模拟回溯测试的完整流水线。它不是一套可以直接上线的生产系统,但绝对是一个绝佳的学习框架和实验沙盒。你可以用它来验证自己的新想法,比如换一种需求预测模型,或者尝试不同的优化算法,看看对最终“利润”这个硬指标到底有什么影响。在数据驱动的时代,拥有将复杂业务问题转化为数学模型并求解的能力,正变得越来越重要。希望我们的这次实战复盘和开源代码,能成为你探索这条道路的一块有用的垫脚石。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询