尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

数学建模竞赛实战:基于时序预测与优化模型的蔬菜定价补货决策

数学建模竞赛实战:基于时序预测与优化模型的蔬菜定价补货决策 1. 项目概述从赛题到实战的完整拆解2023年高教社杯全国大学生数学建模竞赛的C题“蔬菜类商品的自动定价与补货决策”可以说是一道非常“接地气”的赛题。它没有去探讨那些高深莫测的理论前沿而是把一个大型商超每天都在面临的、实实在在的经营决策难题直接抛给了参赛者。这道题的核心就是要求我们建立一个数学模型去解决两个核心业务问题每天该给每种蔬菜定什么价以及每天该给每种蔬菜补多少货听起来像是超市经理的日常工作对吧但当你真正拿到题目附件里那几十个Excel表格里面包含了数百种蔬菜品类过去四年多的日度销售数据、损耗数据、成本与售价数据时你就会发现这远不是拍脑袋能决定的事。数据量庞大关系复杂季节波动、节假日效应、品类间的替代与互补关系交织在一起形成了一个典型的、高维的、带约束的时序预测与优化决策问题。这正是数学建模的魅力所在——将模糊的商业直觉转化为清晰的数学语言和可计算的模型。这道题非常适合有一定数据分析基础特别是对时间序列预测和运筹优化感兴趣的同学来深入研究和复现。它不仅能锻炼你从海量数据中提取规律的能力更能让你体会到建立一个“输入历史数据输出明日决策”的自动化系统需要经历怎样的思考过程与技术选型。接下来我将以一名多次参与并指导数模竞赛的“老手”视角带你彻底拆解这道赛题并分享一套经过实战检验的、完整的解决思路与代码框架。我们的目标不是简单地给出答案而是让你理解每一步“为什么这么做”以及在实际编程中会遇到哪些“坑”。2. 核心问题解析与建模总览面对这样一个问题我们首先要避免陷入数据的海洋而迷失方向。我们需要用结构化的思维把大问题分解成几个关键的子问题并理清它们之间的逻辑关系。2.1 问题一销量与损耗的预测这是所有决策的基础。题目要求我们基于过去的数据预测未来一周2023年7月1-7日6个单品和4个品类的日销量与损耗。这里有三个关键点预测目标日销量sale_quantity和日损耗loss_quantity。注意损耗数据可能是按成本或售价计算的金额需要根据题目说明统一量纲。预测对象既有个别畅销单品如花叶类的水生根茎类下的某个具体蔬菜也有聚合的品类如所有花叶类蔬菜。这要求模型既能处理微观波动也能把握宏观趋势。数据特性明显的时序数据。我们必须考虑以下因素趋势性长期是增长、下降还是平稳季节性蔬菜销售有强烈的年度周期淡旺季、季度周期时令菜和月度周期如月末采购高峰。周期性以周为单位的周期周末销量高周中销量低非常关键。节假日效应春节、国庆等长假对销量的巨大冲击。外部因素题目是否提供了天气、促销活动等信息如果有则是宝贵的特征。序列相关性昨天的销量大概率会影响今天。实操心得千万不要一上来就用复杂的深度学习模型如LSTM。对于这类有明显规律且数据量未必足够大的商业时序问题传统时序模型如SARIMA或树模型如LightGBM、XGBoost结合精心构造的特征往往是更稳健、可解释性更强的选择。我的首选方案是LightGBM 丰富的时序特征工程。因为它能很好地处理非线性关系且对特征中的缺失值和异常值相对鲁棒。2.2 问题二单品的定价与补货决策这是赛题的核心优化部分。在预测出未来销量和损耗的基础上我们需要为单个商品制定未来一周7月1-7日的日补货量和日定价。目标是使得商超的收益最大化。这本质上是一个动态规划或带约束的优化问题。我们需要定义以下核心要素决策变量price_t(第t天的价格)replenish_t(第t天的补货量)。目标函数最大化未来一周的总利润或总收益。利润 销售收入 - 采购成本 - 损耗成本 - 库存持有成本如有。约束条件需求函数约束销量预测pred_sale_t是价格price_t的函数。通常价格越高需求越少。我们需要从历史数据中拟合出这个“价格-销量”弹性关系。一个常用的简化模型是线性需求函数pred_sale_t base_demand_t - k * price_t其中base_demand_t是问题一预测的、在“基准价格”下的销量k是价格弹性系数。库存动态平衡inventory_t inventory_{t-1} replenish_t - actual_sale_t - loss_t。实际销量actual_sale_t不能超过当日库存与补货量之和且通常等于预测销量与库存中较小者即不能超卖。业务规则约束补货量有上下限如货架容量、供应商能力价格有上下限如不能低于成本价不能高于市场承受范围库存不能为负。非负约束所有决策变量均需非负。注意事项这里的最大难点在于需求与价格的耦合。我们预测销量时问题一假设价格是已知或固定的如历史平均价。但在优化时价格是变量销量随之变化。这是一个“先有鸡还是先有蛋”的循环。破解方法通常是两阶段法第一阶段在假设价格不变或按某种规则变化下预测基准销量第二阶段在优化模型中将基准销量作为参数引入价格弹性系数来动态调整销量预测。2.3 问题三品类的定价与补货决策问题三将决策层面从单品提升到了品类如所有茄类。这带来了新的复杂性品类内单品汇总品类的销量、损耗、成本、售价都是其下所有单品的汇总。但决策时我们需要将品类的总补货量和平均定价合理地分配到各个单品上。品类间的关联不同品类的蔬菜可能存在替代西红柿贵了消费者可能多买黄瓜或互补买了辣椒很可能再买点蒜关系。这要求模型不能孤立地看待每个品类而需要考虑它们之间的交叉价格弹性。建模思路需要升级预测层面预测品类总销量时除了考虑自身历史还可以加入相关品类的历史价格或销量作为特征以捕捉替代/互补效应。优化层面目标函数变为最大化所有品类的总利润。约束条件中需要为每个品类引入一个需求方程组其中某个品类的销量是其自身价格及其他相关品类价格的函数。这通常需要利用历史数据通过回归方法估计出完整的交叉价格弹性矩阵。分配问题得到品类总补货量后如何分配给单品一个实用的方法是根据各单品在过去一段时间内的销售占比或利润贡献占比进行分配。定价也可类似处理在品类平均价的基础上根据单品的等级、成本进行微调。3. 数据预处理与特征工程实战拿到数据后切忌直接跑模型。高质量的特征工程决定了模型性能的上限。我们以提供的销售数据为例进行详解。3.1 数据清洗与整合通常数据包含多个表sales_data.csv销量loss_data.csv损耗cost_price.csv成本价sale_price.csv售价。第一步是将其按日期、商品编码或品类编码进行关联整合成一张“宽表”。import pandas as pd import numpy as np # 假设读取数据 sales_df pd.read_csv(sales_data.csv, parse_dates[sale_date]) loss_df pd.read_csv(loss_data.csv, parse_dates[loss_date]) cost_df pd.read_csv(cost_price.csv) price_df pd.read_csv(sale_price.csv) # 数据合并示例以单品每日数据为例 # 1. 合并销量与损耗 df pd.merge(sales_df, loss_df, howleft, left_on[sale_date, prod_code], right_on[loss_date, prod_code]) # 2. 合并成本与售价注意成本售价可能是时段性的需要向前或向后填充 df pd.merge(df, cost_df, howleft, on[prod_code]) df pd.merge(df, price_df, howleft, on[prod_code]) # 处理合并后的缺失值 df[loss_quantity].fillna(0, inplaceTrue) # 假设无损耗记录即为0 # 对于成本售价可能需要用前一个有效值填充ffill df[[cost_price, sale_price]] df.groupby(prod_code)[[cost_price, sale_price]].fillna(methodffill) # 检查重复和异常值 print(df.duplicated().sum()) print(df.describe()) # 重点关注销量、损耗为负或极大的异常值需结合业务判断处理或截断3.2 核心特征构造这是提升预测准确性的关键。我们为目标变量y明日销量构造特征X。1. 滞后特征 (Lag Features):这是时序预测的基石。利用过去几天的信息来预测未来。for lag in [1, 2, 3, 7, 14, 21, 30]: # 分别取昨天、前天、大前天、上周同天、两周前等同天... df[fsale_lag_{lag}] df.groupby(prod_code)[sale_quantity].shift(lag) df[floss_lag_{lag}] df.groupby(prod_code)[loss_quantity].shift(lag)2. 滚动统计特征 (Rolling Statistics):刻画近期趋势和波动。for window in [3, 7, 14, 30]: df[fsale_rollmean_{window}] df.groupby(prod_code)[sale_quantity].transform(lambda x: x.rolling(window, min_periods1).mean()) df[fsale_rollstd_{window}] df.groupby(prod_code)[sale_quantity].transform(lambda x: x.rolling(window, min_periods1).std()) # 滚动总和、最小值、最大值、分位数等也很有用3. 时间特征 (Temporal Features):将日期信息转化为模型可理解的格式。df[day_of_week] df[sale_date].dt.dayofweek # 周一0周日6 df[day_of_month] df[sale_date].dt.day df[month] df[sale_date].dt.month df[year] df[sale_date].dt.year df[is_weekend] df[day_of_week].isin([5,6]).astype(int) # 构造节假日标志需要外部节假日列表 holiday_list [2023-01-01, 2023-01-22, ...] # 示例 df[is_holiday] df[sale_date].isin(pd.to_datetime(holiday_list)).astype(int) # 距离最近节假日的天数节前备货节后淡季4. 价格相关特征:df[price_cost_ratio] df[sale_price] / df[cost_price] # 毛利率相关 df[price_change] df.groupby(prod_code)[sale_price].diff() # 价格变动 df[price_rank_in_category] df.groupby([sale_date, category_code])[sale_price].rank() # 品类内价格排名5. 品类/单品统计特征:# 品类每日总销量体现品类热度 category_daily_sale df.groupby([sale_date, category_code])[sale_quantity].sum().rename(category_daily_sale) df df.merge(category_daily_sale, on[sale_date, category_code]) # 单品在品类内的销量占比 df[sale_share_in_category] df[sale_quantity] / df[category_daily_sale]踩坑实录构造滞后和滚动特征时必须严格按时间顺序、按组单品/品类进行并使用shift和rolling确保不会发生“数据泄露”——即用未来的信息预测过去。在划分训练集和测试集之后再在训练集上计算这些特征然后用类似方法应用到测试集是常见的错误。正确做法是在整个数据集上先构造特征然后按日期划分数据集这样测试集的特征也是基于其“过去”的历史数据计算的虽然不完美但更接近实际预测场景。更严谨的做法是使用sklearn的TimeSeriesSplit进行交叉验证。4. 预测模型构建LightGBM实战我们选择LightGBM作为预测模型。它速度快、精度高、能自动处理缺失值并且对特征缩放不敏感。4.1 模型训练与验证import lightgbm as lgb from sklearn.model_selection import TimeSeriesSplit from sklearn.metrics import mean_absolute_error, mean_squared_error # 假设df是经过特征工程后的完整数据框 # 1. 定义特征和目标 # 假设我们要预测‘单品A’的销量 target_item 单品A编码 item_df df[df[prod_code] target_item].copy() item_df item_df.sort_values(sale_date).reset_index(dropTrue) # 按时间排序 # 选择特征列排除日期、目标列、以及可能泄露未来的列 feature_cols [col for col in item_df.columns if col not in [sale_date, prod_code, sale_quantity, loss_quantity, actual_sale]] X item_df[feature_cols] y_sale item_df[sale_quantity] # 销量目标 y_loss item_df[loss_quantity] # 损耗目标 # 2. 时序交叉验证 # 注意不能使用随机划分必须按时间顺序 tss TimeSeriesSplit(n_splits5) # 5折时序交叉验证 mae_scores, rmse_scores [], [] for train_idx, val_idx in tss.split(X): X_train, X_val X.iloc[train_idx], X.iloc[val_idx] y_train, y_val y_sale.iloc[train_idx], y_sale.iloc[val_idx] # 创建LightGBM数据集 train_data lgb.Dataset(X_train, labely_train) val_data lgb.Dataset(X_val, labely_val, referencetrain_data) # 设置参数 params { objective: regression, # 回归任务 metric: l2, # 使用均方误差 boosting_type: gbdt, num_leaves: 31, learning_rate: 0.05, feature_fraction: 0.9, bagging_fraction: 0.8, bagging_freq: 5, verbose: -1, seed: 42 } # 训练 gbm lgb.train(params, train_data, num_boost_round1000, valid_sets[val_data], callbacks[lgb.early_stopping(stopping_rounds50), lgb.log_evaluation(100)]) # 预测与评估 y_pred gbm.predict(X_val, num_iterationgbm.best_iteration) mae mean_absolute_error(y_val, y_pred) rmse np.sqrt(mean_squared_error(y_val, y_pred)) mae_scores.append(mae) rmse_scores.append(rmse) print(fCV平均MAE: {np.mean(mae_scores):.2f}, 平均RMSE: {np.mean(rmse_scores):.2f}) # 3. 使用全部数据训练最终模型用于未来预测 final_train_data lgb.Dataset(X, labely_sale) final_model lgb.train(params, final_train_data, num_boost_roundgbm.best_iteration)4.2 预测未来一周训练好模型后预测未来一周需要“滚动预测”因为我们要预测的是多天而有些特征如滞后特征依赖于前一天的预测值。def rolling_forecast(model, last_known_data, future_dates, feature_cols): 滚动预测未来多天 :param model: 训练好的LightGBM模型 :param last_known_data: 包含最近一段时间数据的DataFrame用于初始化滞后特征 :param future_dates: 需要预测的日期列表 :param feature_cols: 模型使用的特征列名列表 :return: 预测值的列表 predictions [] forecast_df last_known_data.copy() for forecast_date in future_dates: # 1. 为预测日构造一行数据 # 这里需要根据forecast_date设置时间特征星期几、月份等 # 价格特征可能需要使用计划价或近期平均价这里假设使用近期平均价 row {} row[sale_date] forecast_date row[day_of_week] forecast_date.dayofweek row[month] forecast_date.month # ... 设置其他时间特征 # 2. 计算滞后特征依赖于之前的真实值或预测值 # 例如sale_lag_1 应该是昨天的销量如果是第一天预测则用历史最后一天的真实值 if len(predictions) 0: # 预测第一天滞后特征用历史最后一天的真实值 row[sale_lag_1] forecast_df.iloc[-1][sale_quantity] else: # 预测后续天滞后特征用前一天的预测值 row[sale_lag_1] predictions[-1] # 同理设置 sale_lag_2, sale_lag_7等需要回溯历史数据或预测值 # 3. 计算滚动统计特征基于历史数据已产生的预测值 # 这里需要维护一个不断延长的“历史序列” temp_series pd.Series(list(forecast_df[sale_quantity]) predictions) row[sale_rollmean_7] temp_series.tail(7).mean() # ... 计算其他滚动特征 # 4. 将这一行数据转换为模型输入格式并确保列顺序与训练时一致 input_df pd.DataFrame([row])[feature_cols] # 5. 进行预测 pred model.predict(input_df)[0] predictions.append(pred) # 6. 可选将本次预测值作为一个“临时真实值”加入序列用于下一天的预测 # 注意这里不修改原始forecast_df只是在循环内维护一个临时列表 return predictions # 使用示例 last_30_days_data item_df.tail(30) # 取最近30天数据作为已知基础 future_dates pd.date_range(start2023-07-01, periods7, freqD) future_sales rolling_forecast(final_model, last_30_days_data, future_dates, feature_cols) print(f未来一周销量预测: {future_sales})注意事项滚动预测的误差会累积。第一天的预测误差会影响第二天滞后特征的质量从而可能放大后续预测的误差。为了缓解这个问题可以尝试使用多步直接预测模型一次性输出未来7天的预测值但这对模型要求更高。在滚动预测中使用历史真实值作为滞后特征的时间尽可能长例如lag_7用上周的真实值而不是上周的预测值只在必要时才用预测值填充。对预测结果进行后处理校准例如根据历史预测误差的分布进行调整。5. 优化模型构建定价与补货决策预测完成后我们进入优化阶段。这里以问题二单品决策为例展示如何用Python的PuLP或SciPy库来建模求解。5.1 定义优化问题假设我们已经有了未来7天t1 to 7的基准销量预测base_demand_t来自问题一模型假设是在历史平均价格下的预测以及采购成本cost_t初始库存I0价格弹性系数k通过历史数据回归估计得出。我们的目标是最大化总利润Maximize:Σ_{t1}^{7} [ (price_t * sale_t) - (cost_t * replenish_t) - (loss_cost_t) ]Subject to:需求函数:sale_t base_demand_t - k * (price_t - base_price)。base_price是计算base_demand_t时所用的基准价格。库存平衡:I_t I_{t-1} replenish_t - sale_t - loss_t。其中loss_t可以用预测的损耗率乘以库存来估算。销量上限:sale_t I_{t-1} replenish_t(不能超卖)。销量非负:sale_t 0。补货量上下限:replenish_min replenish_t replenish_max。价格上下限:price_min price_t price_max。库存非负:I_t 0。5.2 使用PuLP求解from pulp import LpProblem, LpVariable, LpMaximize, LpStatus, value # 定义参数 T 7 # 7天 base_demand future_sales # 假设这是我们预测的基准销量列表 base_price 5.0 # 基准价格假设为5元 k 10.0 # 价格弹性系数价格每上涨1元销量减少10单位需根据历史数据拟合 cost [3.0] * T # 未来7天成本假设固定为3元/单位 I0 100 # 初始库存 replenish_min, replenish_max 50, 200 # 日补货量上下限 price_min, price_max 3.5, 8.0 # 售价上下限需高于成本 loss_rate 0.02 # 日损耗率假设为2% # 创建问题 prob LpProblem(Vegetable_Pricing_Replenishment, LpMaximize) # 创建决策变量 price_vars LpVariable.dicts(Price, range(T), lowBoundprice_min, upBoundprice_max) replenish_vars LpVariable.dicts(Replenish, range(T), lowBoundreplenish_min, upBoundreplenish_max) sale_vars LpVariable.dicts(Sale, range(T), lowBound0) # 销量非负 inventory_vars LpVariable.dicts(Inventory, range(T), lowBound0) # 库存非负 # 注意sale_vars 还需要满足库存约束这将在下面添加 # 设置目标函数 profit_expr 0 for t in range(T): revenue price_vars[t] * sale_vars[t] purchase_cost cost[t] * replenish_vars[t] loss_cost loss_rate * inventory_vars[t] * cost[t] # 简化损耗成本损耗率*库存*成本价 profit_expr (revenue - purchase_cost - loss_cost) prob profit_expr # 添加约束 for t in range(T): # 约束1: 需求函数 (线性) prob sale_vars[t] base_demand[t] - k * (price_vars[t] - base_price), fDemand_Function_{t} # 约束2 3: 库存平衡与销量上限 if t 0: prob inventory_vars[t] I0 replenish_vars[t] - sale_vars[t] - loss_rate * I0, fInventory_Balance_{t} else: prob inventory_vars[t] inventory_vars[t-1] replenish_vars[t] - sale_vars[t] - loss_rate * inventory_vars[t-1], fInventory_Balance_{t} # 销量不能超过可用库存前一天库存当天补货 if t 0: prob sale_vars[t] I0 replenish_vars[t], fSale_Limit_{t} else: prob sale_vars[t] inventory_vars[t-1] replenish_vars[t], fSale_Limit_{t} # 求解问题 prob.solve() print(f求解状态: {LpStatus[prob.status]}) # 输出结果 if prob.status 1: # Optimal print(最优决策方案:) for t in range(T): print(fDay {t1}: Price{value(price_vars[t]):.2f}, Replenish{value(replenish_vars[t]):.1f}, fSale{value(sale_vars[t]):.1f}, Inventory{value(inventory_vars[t]):.1f}) print(f预计总利润: {value(prob.objective):.2f}) else: print(未找到最优解。)实操心得线性规划LP求解器如PuLP默认的CBC对这类中小规模问题非常有效。但上述模型将需求函数简化为线性这在实际中可能过于理想。更复杂的非线性关系如价格对销量的指数影响或整数约束补货按箱计算可能需要用到非线性规划NLP或混合整数规划MIP求解器如PuLP支持调用Gurobi,CPLEX等商业求解器或开源的SCIP。如果问题规模很大成百上千商品可能需要设计启发式算法如遗传算法、模拟退火来求近似最优解。6. 品类决策与分配问题实现问题三的复杂性在于品类间的关联和内部的分配。这里概述关键步骤。6.1 估计交叉价格弹性假设我们有3个品类A, B, C。我们可以为每个品类建立一个需求方程其中销量受自身价格和其他品类价格影响。Sale_A α_A - β_AA * Price_A β_AB * Price_B β_AC * Price_C ... (其他因素)Sale_B α_B β_BA * Price_A - β_BB * Price_B β_BC * Price_C ...Sale_C ...其中β_ij (i≠j)就是交叉价格弹性。β_ij 0表示品类i和j是替代品j涨价i销量增。β_ij 0表示是互补品j涨价i销量减。我们可以用历史数据对每个品类进行多元线性回归来估计这些系数。特征包括自身价格、其他品类价格、时间特征、历史销量滞后项等。import statsmodels.api as sm # 假设 df_agg 是按天、按品类聚合后的数据包含各品类的日销量和日均售价 # 例如列有date, cat_A_sale, cat_A_price, cat_B_sale, cat_B_price, cat_C_sale, cat_C_price, ... # 为品类A构建回归模型 X_a df_agg[[cat_A_price, cat_B_price, cat_C_price, day_of_week, month, cat_A_sale_lag1, cat_A_sale_lag7]] X_a sm.add_constant(X_a) # 添加截距项 y_a df_agg[cat_A_sale] model_a sm.OLS(y_a, X_a).fit() print(model_a.summary()) # 从结果中读取 cat_B_price 和 cat_C_price 的系数即为交叉弹性 β_AB 和 β_AC。6.2 品类级优化建模在得到需求方程组后品类级的优化模型与单品级类似但决策变量是每个品类的价格和总补货量目标函数是三个品类利润之和约束中包含上述联立的需求方程组。这形成了一个更复杂的优化问题通常仍可用线性/非线性规划求解只要将需求方程作为约束代入。6.3 单品分配策略得到品类总补货量Replenish_Cat后如何分配给下属的N个单品item_1, ..., item_N一个简单有效的策略是按历史销售比例分配计算过去M天如30天每个单品的平均日销量avg_sale_i。计算每个单品的销售占比share_i avg_sale_i / sum(avg_sale_i)。单品补货量replenish_i Replenish_Cat * share_i。更精细的策略可以考虑单品的利润率、损耗率、当前库存和保质期。例如可以构建一个单品级的二次优化在满足品类总补货量的约束下分配方案使得单品总利润最大或总损耗最小。定价分配也可以类似处理先确定品类基准价然后根据单品的成本、等级、历史价格进行上下浮动。7. 完整代码框架与避坑指南将以上所有步骤整合形成一个完整的、模块化的代码框架至关重要。7.1 项目目录结构建议vegetable_pricing_replenishment/ ├── data/ │ ├── raw/ # 存放原始赛题数据 │ └── processed/ # 存放清洗合并后的数据 ├── src/ │ ├── data_preprocessing.py # 数据清洗、合并、特征工程 │ ├── forecasting.py # 销量/损耗预测模型 │ ├── elasticity_estimation.py # 价格弹性与交叉弹性估计 │ ├── optimization.py # 定价与补货优化模型 │ └── utils.py # 工具函数评估指标、可视化等 ├── config.yaml # 配置文件路径、参数 ├── main.py # 主程序串联整个流程 └── requirements.txt # 项目依赖7.2 核心避坑指南与常见问题数据泄露这是新手最容易犯的错误。永远不要在全局数据上计算统计特征如均值、标准差后再划分训练测试集。正确的做法是在训练集上计算统计量然后用这些统计量去转换测试集。对于时序问题更安全的做法是使用sklearn的Pipeline结合TimeSeriesSplit。特征工程过拟合不要盲目构造大量特征。使用特征重要性LightGBM自带或递归特征消除RFE来选择对预测最有用的特征。对于滞后特征可以通过相关性分析确定最佳的滞后阶数。预测与优化的循环依赖如前所述预测模型假设价格已知优化模型又需要预测的销量。在实际系统中这可能是一个迭代或动态调整的过程。在竞赛的静态环境下我们采用“两阶段法”是合理的。但在方案阐述中需要明确指出这个假设及其局限性。模型评估不恰当对于时序预测不要用简单的随机划分验证。务必使用时序交叉验证TimeSeriesSplit或滚动窗口验证。评估指标也不要用R²而应该用MAE平均绝对误差、RMSE均方根误差或MAPE平均绝对百分比误差注意分母为零的情况等业务相关指标。优化问题不可行或无解检查约束条件是否相互矛盾。例如价格下限设得过高可能导致需求函数计算出的销量为负数进而违反非负约束。初始参数设置要合理。可以尝试逐步放松约束或检查求解器的日志输出。代码效率处理数百个单品几年数据时循环操作可能极慢。尽量使用Pandas的向量化操作和groupby。对于需要为每个单品单独训练模型的情况可以考虑使用joblib进行并行计算。结果的可解释性与稳定性数学建模竞赛不仅看结果更看重建模过程的合理性。确保你的模型结果符合业务常识例如价格提高预测销量应下降。对关键参数如价格弹性k进行敏感性分析说明其变化对最终利润的影响能极大提升论文的说服力。这套从数据到预测再到优化决策的完整框架不仅适用于这道赛题也适用于许多类似的供应链管理、零售库存优化问题。真正的挑战在于根据具体数据和业务背景灵活调整和细化每一个模块。记住没有一劳永逸的模型只有不断迭代和贴近业务逻辑的解决方案。
返回列表