ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

数学建模竞赛实战:从需求预测到联合优化,拆解自动定价与补货决策

数学建模竞赛实战:从需求预测到联合优化,拆解自动定价与补货决策 1. 项目概述从一篇论文到一套方法论每年数学建模竞赛结束后总有一批“神作”在圈内流传2023年C题的优秀论文就是其中之一。我花了将近一周时间把能找到的高分论文都捋了一遍不是为了膜拜而是想搞清楚一件事在题目看似常规的“蔬菜类商品自动定价与补货决策”背后这些顶尖队伍到底做对了什么才让他们的论文从海量作品中脱颖而出这不仅仅是看他们用了什么模型更是要拆解他们构建问题、分析数据、设计方案的完整逻辑链条。对于准备参赛的同学或者任何需要处理复杂优化决策问题的人来说这种“逆向工程”式的分析价值远超单纯学习一个算法。它关乎如何将模糊的实际问题转化为清晰、可解、且能打动评委的数学模型。简单来说2023年C题要求参赛者为一个生鲜超市的蔬菜品类设计自动化的定价与补货策略。题目给出了过去四年多个蔬菜品类的销售数据包括成本、售价、销量、损耗等。核心目标就两个第一基于历史数据建立定价模型实现利润最大化第二设计补货决策模型在满足需求的同时最小化损耗。听起来像是经典的“报童问题”升级版但实际做起来坑多得能绊倒一个排。很多队伍折戟沉沙要么是模型过于理想化脱离实际要么是求解复杂到算不出来要么是论文写得像实验报告缺乏洞察。而我分析的这些优秀论文它们共同的成功秘诀在于没有把题目当成一道数学题而是当成一个真实的商业决策模拟。它们深入挖掘了数据背后的故事比如蔬菜销售的强季节性、不同品类间的关联性、损耗的非线性特征并将这些洞察巧妙地融入了模型假设和约束条件中。接下来我就把自己从这些“学霸笔记”里提炼出的核心思路、关键技术选型、实操细节以及那些容易踩坑的地方系统地分享给你。无论你是备战下一次数模竞赛还是在工作中面临类似的资源优化问题相信这些来自实战顶端的经验都能给你带来实实在在的启发。2. 核心思路拆解优秀论文的四大共性特征看完几十篇论文后我发现高分作品在思路上有明显的共性。它们没有追求算法的炫技而是在问题理解的深度、模型结合的巧度、以及方案表述的清晰度上做到了极致。下面我把它拆解为四个关键特征。2.1 特征一问题重构与多阶段建模题目直接问“定价”和“补货”但高手绝不会直接套用现成的定价模型或库存公式。他们首先做的是问题重构。他们会问定价和补货真的是两个独立问题吗显然不是。补货量取决于对需求的预测而需求又受价格直接影响。因此这本质上是一个联合决策优化问题。大部分优秀论文都采用了多阶段建模的框架数据预处理与特征工程阶段这不是简单清洗而是深度挖掘。例如除了常规的日期、销量、成本他们会构建衍生特征周销量增长率、品类间销量相关系数、历史损耗率与销售量的比值等。有一篇论文特别指出叶菜类如菠菜的损耗对前一日剩余库存量极为敏感而非简单的线性关系这个洞察直接影响了后续损耗模型的建立。需求预测阶段这是整个模型的基石。几乎所有高分论文都摒弃了单一的预测模型而是采用了集成或分层的预测思路。对于整体趋势如年度、季度可能使用时间序列模型如SARIMA对于节假日、周末等季节性因素采用季节性分解或LightGBM/XGBoost这类树模型对于新品或数据稀疏的品类则采用类似品类的迁移学习或贝叶斯平滑方法。关键点在于他们不仅预测了“点估计”平均销量更预测了“概率分布”或“置信区间”为后续的鲁棒优化打下了基础。联合优化阶段在此阶段将预测的需求作为随机变量或带参数的分布嵌入到一个优化模型中。目标函数通常是最大化期望利润而决策变量就是价格和补货量。约束条件则复杂得多包括库存容量约束、资金约束、最小展示量约束超市货架不能空、以及最重要的——损耗与库存和时间的动态关系约束。很多论文在这里引入了条件风险价值CVaR的概念不再只追求平均利润最高而是要求“在95%的情况下利润不低于某个值”这更符合企业稳健经营的需求。策略输出与模拟验证阶段优化模型求解出的可能是一组复杂的函数或规则。优秀论文会将其转化为可执行的“策略表”或“决策树”。例如“当A蔬菜昨日剩余库存大于X且预测明日气温高于Y度时采取降价Z%的策略并补货W公斤”。最后他们一定会用历史数据或模拟数据对策略进行回测并与简单的基准策略如固定价格、按昨日销量补货对比用清晰的图表展示利润提升、损耗降低的具体幅度。注意切忌将多阶段建模做成流水账。每个阶段之间的逻辑传递必须清晰。例如需求预测阶段的输出误差如何在优化阶段被考虑是通过随机规划还是在目标函数中加入惩罚项这一点必须在论文中明确阐述这是评委考察建模连贯性的重点。2.2 特征二成本与损耗模型的精细化处理这是区分普通论文和优秀论文的最大分水岭。很多队伍对损耗的处理过于粗糙简单地用“销量*固定损耗率”来计算这完全不符合生鲜零售的现实。高分论文普遍将损耗分为两大类自然损耗随时间推移必然发生的腐败、脱水。这部分通常建模为关于库存时间Age的函数例如指数衰减模型损耗量 初始库存 * (1 - exp(-k * t))其中k是腐败速率系数不同蔬菜叶菜vs根茎的k值差异巨大。机会损耗因未能及时售出而被迫丢弃的部分。这部分与需求不确定性和定价策略强相关。如果定价过高导致销量低于预期剩余库存就会转化为机会损耗。更精彩的在于对成本的分解。除了显性的进货成本优秀论文还考虑了损耗成本不仅是货物成本还包括处理损耗的人工、垃圾清运等隐形成本。缺货成本货架空空导致的客户满意度下降和潜在销售损失。这部分难以量化但有的论文巧妙地用“历史同期同类产品销量”作为机会成本的参照。资金占用成本库存占用的资金本可以用于其他投资这部分成本在长期运营中不可忽视。有一篇让我印象深刻的论文它甚至为不同的蔬菜品类赋予了不同的“新鲜度价值衰减曲线”。例如西兰花一旦花蕾变黄价值急剧下跌适合采用“阶梯式折扣”定价策略而土豆的贬值曲线则平缓得多可以采用“缓慢降价”策略。这种基于商品特性的差异化建模极大地提升了模型的现实解释力。2.3 特征三算法选型与求解的务实性面对这样一个包含随机变量、非线性约束的优化问题算法求解是另一大挑战。我观察到顶尖队伍在算法选型上非常务实遵循“能用简单的不用复杂的能结合使用的不单一依赖”的原则。预测算法如前所述融合模型是主流。具体工具上Python的statsmodels库用于传统时间序列scikit-learn和LightGBM用于机器学习回归。他们通常会做特征重要性分析来验证构建的特征是否有效比如发现“前一周平均销量”比“上月同期销量”预测力更强这本身就是一个有价值的发现。优化算法对于简化后的确定性模型如将需求取为预测均值线性规划LP或混合整数线性规划MILP可以通过PuLP、Gurobi等求解器高效解决。这是很多论文的起点。对于考虑不确定性的随机规划或鲁棒优化模型直接求解可能非常困难。常用的方法是样本平均近似SAA从需求预测的概率分布中抽取大量场景例如1000个将随机优化问题转化为一个大规模但确定性的优化问题再用求解器处理。虽然计算量大但借助云计算平台或高效求解器是可实现的。对于模型过于复杂、无法用传统优化方法求解的情况不少论文转向了启发式算法如遗传算法GA、模拟退火SA。这里的关键不是证明算法全局最优而是证明该算法找到的解显著且稳定地优于人工经验策略或其他基准算法。论文中需要展示算法参数的调优过程如交叉率、变异率和收敛曲线。仿真验证无论用什么优化算法得到策略都必须通过仿真来评估。他们会编写一个模拟器模拟长达数月的每日运营随机生成符合历史规律的需求应用自己的定价补货策略计算每日利润和损耗。这个过程通常重复成千上万次蒙特卡洛模拟以得到策略性能的统计分布平均利润、利润方差、最大回撤等。这种“用仿真检验优化”的思路极大地增加了论文结论的可信度。2.4 特征四论文表述与可视化呈现再好的模型如果表达不清也难获高分。优秀论文在写作和呈现上堪称范本。摘要采用“问题-方法-结果-结论”的黄金结构。开门见山指出研究问题简述核心方法如“我们建立了基于随机规划的多阶段联合决策模型”用数据说话展示核心结果如“相比基准策略平均利润提升15.2%损耗降低22.7%”最后总结模型优点。模型假设假设不是随便写的。每一条假设都有其目的要么是为了简化问题如“忽略运输时间”要么是基于数据分析的结论如“假设单个品类的需求相互独立因为相关系数分析显示大部分品类间相关性小于0.3”。后者显示了从数据到模型的推导过程。图表摒弃了软件默认的丑陋图表。所有图表都精心设计颜色简洁、标注清晰。典型的高分图表包括桑基图展示资金流、货物流采购、销售、损耗的走向和比例。热力图展示不同蔬菜品类在不同季节的利润率或损耗率。时间序列对比图将模型推荐的补货量、定价与实际历史数据、基准策略进行多曲线对比一目了然。参数敏感性分析图展示关键参数如损耗率系数、需求波动率在±20%范围内变动时对总利润的影响。这证明了模型的鲁棒性。代码与附录虽然正文不展示代码但他们会提及核心算法的实现工具如PythonPandasPuLP并在附录中给出关键的算法流程图或伪代码。清晰的流程图能让评委快速理解你的求解逻辑。3. 从零到一的实操要点与避坑指南分析了这么多优秀特征我们来看看如果自己动手该如何一步步实现以及过程中有哪些“坑”需要提前避开。3.1 数据预处理不仅仅是清洗题目给的数据通常“脏”且包含信息。预处理的目标是将其转化为适合建模的“干净”特征同时尽可能保留和增强有用信息。异常值处理不要武断地删除。先分析异常值产生的原因。例如销量为0的日子是门店关门节假日、还是缺货如果是节假日这本身就是一个重要的特征应该用“是否节假日”的哑变量来标记而不是删除。对于明显是录入错误的极端值如成本为负才用箱线图或3σ原则进行剔除或修正。缺失值填补时间序列的缺失值不宜用整体均值填补。应采用前向填充、线性插值或者基于同类产品同期数据进行填补。例如菠菜某天数据缺失可以用同期的油菜、生菜的数据趋势来估算。特征工程这是拉开差距的地方。除了从日期衍生出年、月、日、周几、是否节假日、是否周末等还可以构建滞后特征前1天、前7天、前30天的销量、价格。滚动统计特征过去7天的平均销量、销量标准差、平均价格。交互特征自身价格与竞品替代品平均价格的比值。外部特征如果允许虽然题目没给但可以合理推断并作为模型假设。例如可以引入公开的天气数据温度、湿度作为预测特征并在论文中说明其合理性。数据标准化/归一化对于涉及距离计算的聚类或神经网络模型是必须的。对于树模型如LightGBM则不一定需要。但价格和销量单位差异大进行适当的缩放如Min-Max缩放有助于优化求解时的数值稳定性。实操心得建立一个可复现的数据预处理流水线Pipeline。使用Python的sklearn.pipeline或自定义函数确保从原始数据到建模数据的每一步都是透明的。这不仅能保证一致性在调整模型时也能快速重新生成特征。3.2 需求预测模型构建实战我们以构建一个融合模型为例演示具体步骤。步骤1数据划分不要随机划分时间序列数据必须按时间顺序划分。例如用前3年的数据作为训练集最后1年的数据作为测试集来模拟“用历史预测未来”的真实场景。步骤2基准模型建立先建立几个简单的基准模型用于后续对比朴素模型预测值等于前一天的值。季节性朴素模型预测值等于上一周同一天的值。简单移动平均过去7天的平均值。 计算这些基准模型在测试集上的均方根误差RMSE和平均绝对百分比误差MAPE。步骤3高级模型构建与融合模型1SARIMA。使用statsmodels库通过ACF/PACF图确定参数范围用网格搜索寻找最优的(p,d,q)(P,D,Q,s)参数组合。SARIMA能很好地捕捉固定趋势和季节模式。模型2LightGBM。将上一步构建的所有特征滞后、滚动、日期特征等作为输入。需要注意防止过拟合合理设置num_leaves,learning_rate, 并启用早停法early_stopping。模型融合简单有效的融合方法是加权平均。权重如何确定可以在测试集或单独划出一个验证集上以最小化预测误差为目标求解最优权重。更高级的方法可以用线性回归以各模型预测值为特征真实值为目标来学习融合权重。步骤4不确定性量化对于优化而言点预测不够我们需要知道预测的分布。有两种常用方法分位数回归使用LightGBM的objectivequantile分别训练多个分位数如0.05, 0.5, 0.95的模型从而得到预测区间。Bootstrap法对训练数据进行有放回抽样构建多个不同的预测模型用这些模型的预测结果集合来近似分布。# 示例使用LightGBM进行分位数回归预测核心代码片段 import lightgbm as lgb # 准备数据 train_data lgb.Dataset(X_train, labely_train) # 训练中位数回归模型0.5分位数 params { objective: quantile, alpha: 0.5, # 分位数 metric: quantile, boosting_type: gbdt, num_leaves: 31, learning_rate: 0.05, feature_fraction: 0.9 } model_median lgb.train(params, train_data) # 训练上界回归模型0.95分位数 params[alpha] 0.95 model_upper lgb.train(params, train_data) # 训练下界回归模型0.05分位数 params[alpha] 0.05 model_lower lgb.train(params, train_data) # 预测 pred_median model_median.predict(X_test) pred_upper model_upper.predict(X_test) pred_lower model_lower.predict(X_test) # 此时对于每个预测点我们得到了一个区间 [pred_lower, pred_upper]3.3 联合优化模型建模与求解假设我们采用样本平均近似SAA方法处理不确定性。模型建立设决策变量为每日对每个品类i的补货量 (Q_i)定价 (P_i)。 目标最大化期望利润。 约束库存平衡约束、容量约束、非负约束等。由于需求 (D_i) 不确定我们采用SAA。假设我们从预测分布中抽取了N个需求场景 (D_i^1, D_i^2, ..., D_i^N)。则确定性等价模型可以写成 最大化( \frac{1}{N} \sum_{n1}^{N} \sum_{i} [ P_i * min(Q_i I_{i,prev}, D_i^n) - C_i*Q_i - h * I_i^n - v * L_i^n ] ) 其中(I_{i,prev}) 是上日库存。(min(Q_i I_{i,prev}, D_i^n)) 表示在场景n下的实际销售量不能超过需求。(C_i) 是进货成本。(h) 是单位库存持有成本。(I_i^n) 是场景n下的期末库存。(v) 是单位损耗成本。(L_i^n) 是场景n下的损耗量这里可以建模为 (L_i^n \theta * I_i^n)简化线性损耗或更复杂的函数。还需要加上库存平衡方程(I_i^n max(Q_i I_{i,prev} - D_i^n, 0))。模型求解这是一个大规模的线性/非线性规划问题取决于损耗函数的形式。可以使用专业的优化求解器如Gurobi、CPLEX学术免费或开源的PuLP调用CBC求解器来求解。# 示例使用PuLP定义和求解一个简化的确定性补货模型单品类需求已知 import pulp # 创建问题 prob pulp.LpProblem(Single_Product_Inventory, pulp.LpMaximize) # 参数 demand 100 # 预测需求 cost 2 # 单位进货成本 price 5 # 售价 holding_cost 0.1 # 单位持有成本 initial_inventory 20 # 决策变量 order_qty pulp.LpVariable(OrderQuantity, lowBound0, catContinuous) sales pulp.LpVariable(Sales, lowBound0, catContinuous) ending_inventory pulp.LpVariable(EndingInventory, lowBound0, catContinuous) # 目标函数利润 销售收入 - 进货成本 - 持有成本 prob price * sales - cost * order_qty - holding_cost * ending_inventory # 约束条件 prob sales demand, SalesCannotExceedDemand prob sales initial_inventory order_qty, SalesCannotExceedAvailable prob ending_inventory initial_inventory order_qty - sales, InventoryBalance # 求解 prob.solve(pulp.PULP_CBC_CMD(msgFalse)) print(f状态: {pulp.LpStatus[prob.status]}) print(f最优补货量: {order_qty.varValue:.2f}) print(f预期利润: {pulp.value(prob.objective):.2f})对于多品类、多场景的复杂模型决策变量和约束会呈指数级增长需要仔细设计模型结构并可能需要借助更强大的求解器或分解算法。4. 常见问题、调试技巧与进阶思考在实际操作中你会遇到各种各样的问题。下面是我总结的一些典型问题及其解决思路。4.1 模型求解速度慢或无法求解这是最常遇到的问题。问题根源模型规模太大场景太多、品类太多、非线性约束导致非凸、整数变量导致组合爆炸。排查与解决简化模型先从最简化的版本开始。例如先考虑单品类、需求为确定值、损耗为线性函数的模型。确保这个简单模型能快速求解。减少场景数SAA中场景数N不需要极大。可以通过场景缩减技术用少量具有代表性的场景如通过聚类生成来近似原分布。线性化/凸化尝试将非线性约束如包含max/min的损耗函数用线性约束和大M法进行等价转换。如果目标函数或约束是非凸的求解会非常困难需要考虑凸近似或改用启发式算法。松弛整数变量如果补货量被建模为整数变量箱/包可以先松弛为连续变量求解得到最优解后再对结果进行取整并评估取整带来的性能损失。如果损失可接受则可行。使用启发式算法当精确算法失效时转向遗传算法、模拟退火等。虽然不能保证全局最优但一个好的启发式算法通常能找到高质量的解。关键是要设计好的编码方式、适应度函数和邻域搜索操作。4.2 模型结果不理想或违反常识优化结果出来了但补货量是负数或者定价高得离谱这显然是模型或数据有问题。问题根源约束条件不完整或错误目标函数权重设置不合理输入数据存在量纲不一致或异常值。排查与解决检查约束逐条检查约束条件是否反映了现实限制。例如是否遗漏了“补货量非负”、“价格不低于成本”这样的基本约束库存平衡约束的符号是否正确分析对偶变量/影子价格在LP/MILP求解后求解器会给出每个约束的影子价格。它表示该约束右边常数每增加一个单位目标函数值的变化量。如果某个约束的影子价格非常高说明该约束是“紧”的是当前利润的主要瓶颈。这能帮你理解模型的限制在哪里。进行敏感性分析系统地改变关键参数如需求预测的均值、损耗率系数观察最优解如何变化。如果最优解对某个参数极其敏感那么你需要花更多精力去校准这个参数或者说明你的策略在该参数不确定时风险很高。回溯到预测阶段检查输入给优化模型的需求预测值是否合理。用历史数据对比看预测是否存在系统性偏差。4.3 论文写作与呈现中的痛点痛点一模型描述过于晦涩。技巧用“比喻公式文字”三重描述。例如在介绍库存平衡约束时可以写“这就像是一个水池库存每天有进水补货也有出水销售剩下的就是池子里的水期末库存。用公式表示就是期末库存 期初库存 补货量 - 销售量。”痛点二结果分析流于表面。技巧不要只说“模型提升了利润”。要深入分析为什么提升了。是减少了特定品类在特定季节的损耗还是通过动态定价在需求高时多赚了钱结合具体的图表数据给出有因果关系的解释。例如“如图5所示我们的模型在夏季对绿叶蔬菜采用了更激进的降价策略相比基准策略平均低8%这虽然降低了单价但使得销量提升了25%最终该品类在夏季的总利润提升了15%同时损耗降低了30%。”痛点三代码、模型、论文脱节。技巧建立一条清晰的“数据流水线”。从原始数据到最终结果的每一个关键步骤都用脚本自动化。确保论文中的每一个数字、每一张图都能由你的代码重新生成。这不仅能避免低级错误在回答评委质疑时也更有底气。4.4 从优秀到卓越可以深入的进阶方向如果你已经掌握了上述基本框架还想让论文更出彩可以考虑以下进阶方向考虑竞争因素题目假设是单家超市。但在现实中定价会受到周边竞争对手的影响。可以引入博弈论的思想假设竞争对手也采用类似策略建立动态定价博弈模型。引入消费者行为模型需求不仅仅是价格的函数还可能受到促销、陈列方式的影响。可以尝试引入基础的消费者选择模型如Logit模型让需求预测更精细。多目标优化除了利润企业可能还关心客户满意度缺货率低、供应链稳定性补货量波动小。可以将问题建模为多目标优化使用帕累托前沿来展示不同目标之间的权衡。强化学习这是一个非常前沿的尝试。将定价和补货决策视为一个序列决策问题超市是智能体利润是奖励使用深度强化学习算法来学习最优策略。这种方法对数据量和算力要求高但一旦实现会非常亮眼。在论文中你需要详细说明状态空间、动作空间、奖励函数的设计以及训练过程。最后我想强调的是数学建模竞赛和解决真实商业问题的核心是相通的理解问题本质做出合理假设利用数学工具构建简化但有效的模型并用数据驱动决策。2023年C题的这些优秀论文正是这一理念的完美体现。它们的故事告诉我们成功不在于用了多么高深的算法而在于是否构建了一个自洽、合理、且能产生实际价值的解决方案闭环。当你下次面对一个复杂问题时不妨也试试这种“先拆解、再建模、后验证”的思路或许会有意想不到的收获。
返回列表