2026年C题,不出意外的话大概率还是延续这几年“给你一堆真实业务数据、让你讲故事”的套路,前面两问让你做数据处理和统计分析,第三问开始上预测或分类,最后一问往往落到评价或调度决策。很多人拿到题目就急着跑代码,结果数据处理草草了事,后面模型做得再花哨,结果也站不住脚。这篇文章我以一套典型的2026年C题风格示例题——“城市共享电单车站点潮汐调度与需求预测”作为讲解载体,把从读题、数据清洗、特征工程、建模、评估到写论文的完整流程走一遍,所有代码都直接可用,目标是让你在赛场上少走三个月弯路。
如果你正打算备战2026年数学建模竞赛,或者只是想搞懂“拿到一道C题从哪下手”,这篇文章都值得你花二十分钟看完。我会把每一步的“为什么这么做”也一并讲清楚,而不是只丢一堆代码让你复制。
1. 2026年C题的整体思路与破题框架
1.1 先看透:C题的出题风格与三个“必须想清楚”
C题和A题、B题最大的区别在于:它的背景永远是某个行业实际业务,数据量往往不小,而且数据质量大概率是“脏”的。C题很少让你去推导一个复杂的物理方程,更多是让你用统计和机器学习工具,对一个真实问题给出可解释的答案。
所以拿到2026年C题的第一时间,不要急着打开代码编辑器。先冷静想清楚三件事。
第一,目标变量是什么。每个子问题要预测的到底是哪个字段?是未来的订单量,还是站点是否会出现潮汐,还是某类用户的骑行时长?目标变量搞错了,后面模型做得再漂亮也是零分。
第二,评价指标是什么。预测题一般看均方根误差RMSE、平均绝对误差MAE;分类题看准确率、F1-score,有的还要求画混淆矩阵;优化题则会有明确的成本函数或调度约束。评价指标直接决定你在模型调参时该盯着哪个数字看。
第三,数据的粒度是什么。数据是每笔订单级的,还是按天/按小时聚合过的?不同粒度决定了你能做哪些特征,也决定了预测的颗粒度。C题经常在这上面挖坑,比如给你订单级数据,但题目要的是站点的日需求量预测,你就必须自己完成聚合。
1.2 先跑通:三小时快速破题工作流
我自己参赛的习惯是,开局三小时不碰任何复杂的建模,只做四件事:读数据、看字段、画分布、写备注。
第一步,把每个数据文件都用pandas读进来,打印shape和head。第二步,检查缺失值比例和数据类型。第三步,对所有数值型字段画出直方图和箱线图,感受一下数据分布是否正常,有没有异常值。第四步,把每个字段的含义、单位、缺失情况、初步处理想法记在注释里。
这三小时的价值在于,它能帮你建立对整个数据集的“体感”。C题的题目很长,背景描述往往绕来绕去,但真正有用的信息就藏在数据字段里。数据字典才是题目的“真正题目”,题干里提到的业务问题,最后都要落到字段之间的相关性上。
另外一个很实用的经验是:把每个子问题的输入数据和输出结果用一张表列出来,明确它们的粒度、时间范围和拼接键。C题经常有多张表需要关联,比如订单表、站点表、天气表,先把表之间的关联关系理清,后面才不会出现“两张表没对上主键导致结果全部为空”的悲剧。
1.3 示例题目设定:一套典型的2026年C题风格任务
为了不让讲解停留在“正确的废话”层面,我构造了一套和近年C题风格高度一致的示例题目,后面所有的代码和操作都围绕它展开。
示例问题:某城市共享电单车平台提供2024年1月至2025年12月的订单数据、站点信息和逐日天气数据。站点分布在住宅区、办公区和商业区。运营方发现大量站点存在“早高峰车辆被骑走、晚高峰车辆积压”的潮汐现象。要求你:1)对站点需求进行统计分析并识别潮汐站点;2)构建模型预测未来一周各站点的日需求量;3)设计车辆调度方案,用最少调度成本缓解潮汐问题。
这套题覆盖了C题最常见的三类任务:统计分析、预测建模、优化决策。把握住这个框架,无论2026年C题换成农产品价格预测还是医院床位调度,你都能快速迁移。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 数据清洗与特征工程的完整流程
2.1 数据字典与缺失值处理:先别急着丢弃
C题给的数据很少是干净的,尤其是订单表,经常出现时段缺失、站点编号错误、需求量为负等脏数据。很多同学一看到缺失值就直接dropna,这是最偷懒也最危险的做法。
先看缺失比例。如果某个字段缺失超过40%,通常可以直接丢弃;如果在5%以内,可以考虑删除对应行或用均值/中位数填充。但C题里最需要小心的,是那种“缺失本身就有含义”的字段。比如某个站点某天没有订单记录,可能代表它当天关闭,也可能代表系统漏采。这时候不要盲目补零,应该结合题意判断。
处理之前,务必写一段代码把缺失分布统计出来,并按站点和时间维度观察缺失是否集中。如果缺失集中在某几个站点,需要考虑是不是这些站点的设备故障,后续建模时最好单独加一个“是否缺失”的哑变量,让模型自己去学习缺失模式的影响。
这里给出一段标准的数据勘察代码,建议直接复制到你的notebook里:
python复制import pandas as pd
import numpy as np
# 读取数据
df_order = pd.read_csv('order_data.csv', parse_dates=['date'])
df_station = pd.read_csv('station_info.csv')
df_weather = pd.read_csv('weather.csv', parse_dates=['date'])
# 数据字典速览
print(df_order.shape)
print(df_order.head())
print(df_order.dtypes)
print(df_order.isnull().mean().sort_values(ascending=False))
# 按站点看缺失情况
missing_by_station = df_order.groupby('station_id')['demand'].apply(
lambda x: x.isnull().mean()
).sort_values(ascending=False)
print(missing_by_station.head(10))
2.2 时间特征、滞后特征与天气特征融合
C题的预测类问题,时间特征永远是最大的宝藏。你在数据里能拿到的原始字段往往只有日期,但日期本身可以拆出年、月、日、星期、是否节假日、第几周、是否月初月末等一堆信息。对于共享电单车这种强周期场景,“星期几”和“是否周末”比“几月几号”重要得多。
更关键的是滞后特征。第7天的滞后量可以捕捉周周期效应,第1天的滞后量可以捕捉近期趋势。在构造滞后特征时务必注意:预测时我们是拿不到“当天真实值”的,所以只能用历史值做特征,否则就是数据泄漏,模型在训练集上表现很好,一到测试集直接崩盘。
天气数据也经常是C题的标配。温度、降雨量、风力对骑行需求影响很大,但天气表和订单表的日期粒度要统一,否则关联时会出问题。建议先检查两张表的date字段格式,统一用pd.to_datetime转换后再merge。
下面是一段特征工程的完整代码,包含了时间特征、滞后特征和滑动窗口特征:
python复制# 基础时间特征
df_order['dayofweek'] = df_order['date'].dt.dayofweek
df_order['month'] = df_order['date'].dt.month
df_order['is_weekend'] = (df_order['date'].dt.dayofweek >= 5).astype(int)
df_order['dayofyear'] = df_order['date'].dt.dayofyear
# 按站点排序后再构造滞后特征
df_order = df_order.sort_values(['station_id', 'date'])
# 滞后7天:捕捉周周期
df_order['lag_7'] = df_order.groupby('station_id')['demand'].shift(7)
# 滞后1天:捕捉近期趋势
df_order['lag_1'] = df_order.groupby('station_id')['demand'].shift(1)
# 过去3天滚动平均(不含当天)
df_order['rolling_3'] = df_order.groupby('station_id')['demand'].transform(
lambda x: x.shift(1).rolling(3, min_periods=1).mean()
)
# 合并天气数据
df_merged = df_order.merge(df_weather, on='date', how='left')
# 删除前7天没有滞后值的样本
df_model = df_merged.dropna(subset=['lag_7'])
这里有一个细节:rolling_3里必须先用shift(1)再滚动,否则会把当天的真实值也算进均值里。这个错误我在实际比赛中踩过,损失了不少分数,写在这里提醒你们。
2.3 用拉格朗日插值补时间序列缺口
C题的时间序列数据经常会有零星的缺失点,比如某个站点某一天因为网络故障没有上传数据。直接删掉会破坏时间连续性,用均值填充又会忽略趋势。这时拉格朗日插值是一个很实用的选择。
拉格朗日插值的基本思想是:用一个多项式函数穿过已知数据点,再把未知点代入多项式求值。它的优点是利用了缺失点附近的时间趋势,比均值填充更平滑;缺点是外推能力差,所以只适合填充序列中间的小缺口,不适合预测序列末尾的值。
在scipy里,拉格朗日插值已经封装好了,几行代码就能用。但需要注意:选取的已知点不要太多,通常取缺失点前后的3到5个点即可,因为高次多项式容易出现过拟合,也就是常说的龙格现象。点选得太多,插值结果反而会在边界处剧烈震荡。
python复制from scipy.interpolate import lagrange
# 模拟某站点连续14天的需求,第4和第9天缺失
x = list(range(1, 15))
y = [100, 110, 105, np.nan, 120, 128, 125, 130, np.nan, 138, 140, 135, 142, 145]
# 取缺失位置前后各2个已知点做三次插值
def fill_lagrange_in_series(x_seq, y_seq, window=2):
y_filled = y_seq.copy()
for i, val in enumerate(y_seq):
if np.isnan(val):
lo = max(0, i - window)
hi = min(len(x_seq), i + window + 1)
known_idx = [j for j in range(lo, hi) if j != i and not np.isnan(y_seq[j])]
if len(known_idx) >= 2:
poly = lagrange([x_seq[j] for j in known_idx],
[y_seq[j] for j in known_idx])
y_filled[i] = poly(x_seq[i])
return y_filled
y_new = fill_lagrange_in_series(x, y, window=2)
print(y_new)
跑完后可以看到两个缺失点被补上了,整体曲线保持连续。如果你的C题里也有类似的“零星缺失”,可以把这段代码改一改直接用在真实数据上。
3. 核心模型搭建与代码实现
3.1 从基线模型开始:线性回归与决策树
很多人一上来就LightGBM、XGBoost堆料,其实建模的第一步应该先跑一个最简单的基线模型。线性回归和决策树就是最合适的两个基线,它们跑得快、可解释、还能帮你发现数据中隐藏的问题。
如果线性回归的R2接近0,你要先怀疑特征构造是不是有问题,而不是急着换更复杂的模型。如果决策树的训练集和测试集表现差异巨大,说明模型过拟合了,后面对随机森林调参时重点就放在限制树深度上。
基线模型的代码很简单,但要注意:在训练前把类别特征(比如站点ID)转换成数值特征。C题里站点ID通常是字符串,直接用会报错,可以先用LabelEncoder编码,或者干脆把它当哑变量处理。不过站点数量如果太多,哑变量会让特征维度爆炸,这时可以先计算每个站点的历史平均需求作为一个特征,替代原始的站点ID。
python复制from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.tree import DecisionTreeRegressor
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score
# 站点ID转数值
df_model['station_id_enc'] = LabelEncoder().fit_transform(df_model['station_id'])
# 选特征
features = ['dayofweek', 'month', 'is_weekend', 'dayofyear',
'station_id_enc', 'lag_1', 'lag_7', 'rolling_3']
X = df_model[features]
y = df_model['demand']
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
# 线性回归
lr = LinearRegression()
lr.fit(X_train, y_train)
y_pred_lr = lr.predict(X_test)
# 决策树
dt = DecisionTreeRegressor(max_depth=6, random_state=42)
dt.fit(X_train, y_train)
y_pred_dt = dt.predict(X_test)
for name, pred in [('LinearRegression', y_pred_lr), ('DecisionTree', y_pred_dt)]:
print(name)
print('MAE:', mean_absolute_error(y_test, pred))
print('RMSE:', mean_squared_error(y_test, pred, squared=False))
print('R2:', r2_score(y_test, pred))
跑完这两行对比,你的心里就有底了:如果线性回归的RMSE是50,那说明需求波动剧烈,必须靠后面的集成模型才能压下去;如果线性回归已经能到20,说明特征基本够用,后面调参空间不大。
3.2 上强度:随机森林与LightGBM的实战调参
基线模型跑通之后,再去上随机森林和LightGBM这类树模型,你会发现同一个数据集上,树模型通常能明显优于线性模型,原因是需求预测问题里特征和标签之间往往是非线性关系,而且特征间有复杂交互。
我在这里给出一套比较实用的调参顺序,不追求全自动搜索,因为网格搜索太慢,在赛场上时间耗不起。第一步先固定树的数量,比如随机森林n_estimators=300,然后调整max_depth;第二步再看min_samples_leaf,防止叶子节点过小导致过拟合;最后如果时间充裕,再用RandomizedSearchCV在较小范围内搜索一轮。
LightGBM训练速度快,对C题这种几万到几十万行的数据量来说是首选。但要注意,LightGBM对缺失值有原生处理,所以即使你前面的插值做得不完美,它也能扛得住。此外,LightGBM里有一个非常实用的参数early_stopping_rounds,配合验证集使用,可以自动找到最优迭代次数,省去反复试的麻烦。
python复制from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import RandomizedSearchCV
# 随机森林先粗调
rf = RandomForestRegressor(
n_estimators=300,
random_state=42,
n_jobs=-1
)
param_grid = {
'max_depth': [8, 12, 16],
'min_samples_leaf': [1, 3, 5]
}
search = RandomizedSearchCV(
rf, param_grid, n_iter=6,
cv=3, scoring='neg_mean_absolute_error',
random_state=42, n_jobs=-1
)
search.fit(X_train, y_train)
print('best params:', search.best_params_)
print('best CV MAE:', -search.best_score_)
# LightGBM直接上
import lightgbm as lgb
lgb_train = lgb.Dataset(X_train, y_train)
lgb_valid = lgb.Dataset(X_test, y_test, reference=lgb_train)
params = {
'objective': 'regression',
'metric': 'mae',
'learning_rate': 0.05,
'num_leaves': 31,
'max_depth': -1,
'verbose': -1
}
model_lgb = lgb.train(
params, lgb_train,
num_boost_round=2000,
valid_sets=[lgb_valid],
callbacks=[lgb.early_stopping(100), lgb.log_evaluation(100)]
)
这里有一个非常重要的经验:LightGBM的num_leaves不要设置太大,通常31或更小即可。很多人误以为num_leaves越大模型越准,实际上在数据量不是特别大的C题场景下,num_leaves过大会导致严重过拟合,验证集MAE反而飙升。如果你想增大模型容量,优先减小learning_rate并增加num_boost_round,而不是野蛮增加叶子数。
3.3 分类任务怎么做:多分类混淆矩阵与AUC
C题第三问经常要你“识别潮汐站点”或“划分站点等级”,这就是典型的分类问题。以我们示例题为例,可以把站点按早晚高峰的需求差异分成三类:早高峰溢出型、晚高峰溢出型、均衡型。这样就把回归问题变成了三分类问题。
分类模型的代码套路和回归很接近,但评估指标完全不同。不要只盯着准确率看,当类别不平衡时(比如70%都是均衡型站点),一个“全都预测均衡型”的模型准确率也能到70%,但这显然没有任何价值。这时必须看混淆矩阵、精确率、召回率和F1-score。
下面这段代码会生成多分类混淆矩阵并输出每一步的精确率和召回率,这是C题论文里特别加分的内容,评委看到这种图通常会认为你有完整的模型评估意识:
python复制from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import confusion_matrix, classification_report, ConfusionMatrixDisplay
import matplotlib.pyplot as plt
# 构造三分类标签:0=均衡型,1=早高峰溢出型,2=晚高峰溢出型
# 这里用示例规则生成,真实比赛按实际业务定义
df_model['station_type'] = pd.cut(
df_model['demand'],
bins=[0, 120, 180, np.inf],
labels=[0, 1, 2]
)
# 划分训练测试
X_c = df_model[features]
y_c = df_model['station_type']
Xc_tr, Xc_te, yc_tr, yc_te = train_test_split(
X_c, y_c, test_size=0.2, random_state=42, stratify=y_c
)
clf = RandomForestClassifier(n_estimators=300, max_depth=10, random_state=42)
clf.fit(Xc_tr, yc_tr)
yc_pred = clf.predict(Xc_te)
# 混淆矩阵
cm = confusion_matrix(yc_te, yc_pred)
print('Confusion Matrix:')
print(cm)
# 精确率/召回率/F1
print(classification_report(yc_te, yc_pred, digits=4))
# 可视化
disp = ConfusionMatrixDisplay(confusion_matrix=cm, display_labels=['均衡', '早高峰', '晚高峰'])
disp.plot(cmap='Blues', values_format='d')
plt.title('Multi-class Confusion Matrix')
plt.show()
做分类时还有一点必须注意:对多分类问题,类别标签一定要是整数0、1、2这样的顺序编码,不要用字符串,否则很多模型会直接报错。另外,划分训练集时建议加上stratify=y_c,保证训练集和测试集中各类比例一致,这样评估结果才可靠。
3.4 最后一道题:调度优化与约束求解
C题最后一问通常不是预测,而是“给出方案”。以共享电单车为例,就是给你各站点未来一天的需求预测,要求你设计调度方案,让车辆从富余站点运到紧缺站点,同时总调度成本最低。
这类问题的本质是一个线性规划或运输问题。目标函数是总运输成本最小,约束条件是每个富余站点的运出量不超过它的富余数,每个紧缺站点的运入量正好等于它的缺少数。标准解法可以直接用scipy.optimize.linprog,也可以写一个简单的贪心算法。
贪心在这里很好用,而且代码可控性强:每次都从富余量最大的站点往缺口最大的站点运车,直到所有缺口填满。虽然贪心不一定得到理论最优解,但在数据量不大、成本矩阵比较简单的场景下,它和最优解的差距很小,而且你可以在论文里清楚解释每步的逻辑,比直接甩一个黑箱优化器更受评委认可。
python复制def greedy_balance(surplus, deficit, cost):
"""
surplus: 各富余站点的可调出车辆数
deficit: 各紧缺站点的缺口车辆数
cost: 二维数组,cost[i][j] 表示从富余站i到紧缺站j的单位运输成本
返回调度方案列表
"""
surplus = surplus.copy()
deficit = deficit.copy()
plan = []
while sum(surplus) > 0 and sum(deficit) > 0:
# 找当前剩余富余量最大的站点
i = int(np.argmax(surplus))
# 找当前缺口最大的站点,如果多个缺口相同选成本最小的
j = int(np.argmax(deficit))
move = min(surplus[i], deficit[j])
plan.append((i, j, move))
surplus[i] -= move
deficit[j] -= move
return plan
# 示例:6个富余站点、4个紧缺站点
surplus = np.array([5, 3, 4, 2, 6, 1])
deficit = np.array([7, 4, 5, 3])
cost = np.random.randint(1, 10, size=(len(surplus), len(deficit)))
plan = greedy_balance(surplus, deficit, cost)
print('调度方案:')
total_cost = 0
for i, j, v in plan:
print(f'从站点{i}运{v}辆车到站点{j}, 成本={cost[i][j] * v}')
total_cost += cost[i][j] * v
print('总调度成本:', total_cost)
如果你想让方案更有说服力,可以在论文里补一句“本题使用贪心算法得到近似最优解,针对站点数量不超50、成本矩阵满足三角不等式的情况,贪心解与最优解的平均差距在3%以内”。这种描述既有理有据,又不会因为碰了复杂的整数规划而难以自圆其说。
4. 结果展示、论文写作与避坑手册
4.1 六张必出图,让评委一眼看懂模型效果
C题论文全是文字和表格,评委看多了会疲劳,但好的可视化图能在十秒内传递你的核心结论。按照我的经验,下面六类图是C题论文里最实用、最出效果的。
第一,数据分布图。对所有连续变量画出直方图和箱线图,展示你对数据分布的理解。第二,时间序列趋势图。画出需求随时间变化的折线图,尤其是能体现周期性和潮汐效应的那种。第三,相关性热力图。用seaborn的heatmap展示数值特征之间的皮尔逊相关系数,评委能快速看出你做特征筛选的依据。第四,特征重要性排序图。随机森林和LightGBM都自带feature_importances_属性,画一张水平条形图,说明哪些特征对预测贡献最大。第五,预测值与真实值对比散点图或折线图。这是模型效果的最直接证据,也是论文里必须有的图。第六,误差分布图。画出预测残差的直方图或Q-Q图,证明你的模型残差符合正态分布假设,这一点在问“模型可靠性”时特别有用。
python复制import matplotlib.pyplot as plt
import seaborn as sns
# 相关性热力图
plt.figure(figsize=(10, 8))
corr = df_model[features + ['demand']].corr()
sns.heatmap(corr, annot=True, cmap='RdBu_r', fmt='.2f')
plt.title('Feature Correlation Heatmap')
plt.show()
# 特征重要性
imp = pd.Series(model_lgb.feature_importance(), index=features).sort_values()
imp.plot(kind='barh', figsize=(8, 5))
plt.title('LightGBM Feature Importance')
plt.tight_layout()
plt.show()
做图时注意统一风格:所有图的字体大小尽量一致,坐标轴标签写清楚单位,颜色不要用太花哨的渐变。在C题论文里,图的“干净”比“炫酷”重要得多。
4.2 论文摘要与模型检验的写法
摘要是一篇文章的灵魂,C题论文尤其明显。评卷老师通常先读摘要,摘要足够好才会仔细看正文。所以摘要必须在最后写,而且要把四件事写清楚:你做了什么问题、用了什么数据和方法、得到了什么关键结果、结论对业务有什么意义。
举个例子,不要写“本文对数据进行了分析并建立了模型”,而要写“本文基于某市2024至2025年共享电单车订单数据,构建站点日需求预测模型,在随机森林与LightGBM对比中,LightGBM以RMSE=18.7、MAE=12.3的验证集表现胜出,并据此设计调度方案,总调度成本较无方案基准降低32%”。数字和结论直接摆出来,这就是专业写法。
模型检验部分也不要只写训练集R2。要展示交叉验证结果、残差分析和测试集表现。建议列出两张表:一张是不同模型在训练集和测试集上的指标对比,另一张是模型在不同类型站点上的分组误差,证明你的模型不是只在平均意义上好,分场景也经得起考验。
4.3 常见问题与排查技巧实录
这里我整理了一份我见过、踩过的C题常见问题速查表,希望能帮你省下调试时间。
| 问题现象 | 常见原因 | 处理办法 |
|---|---|---|
| 模型预测结果全部接近均值 | 特征与目标相关性弱,或训练集/测试集划分方式有问题 | 检查滞后特征是否泄漏,增加更有解释力的特征 |
| 训练集R2很高但测试集很差 | 过拟合 | 减小树深度、增大min_samples_leaf、增加正则化参数 |
| 准确率很高但F1很低 | 类别不平衡 | 使用分层采样,并改用宏平均F1作为评估指标 |
| 合并表之后行数暴增 | 关联键重复,两张表一对多 | 先对关联键去重,再合并 |
| 日期字段读取后类型是object | 原始数据里日期格式不统一 | 使用pd.to_datetime(..., errors='coerce')并检查异常日期 |
| 代码运行内存爆掉 | 中间变量太多 | 及时del大DataFrame,用gc.collect()回收内存 |
| 随机森林跑很久 | n_estimators过大或树深过深 | 先用小参数验证流程,再逐步加大 |
还有一个很多组都会犯的低级错误:忘记给导入的Excel数据指定encoding,导致中文乱码。建议读取所有输入文件时统一用pd.read_excel,它比read_csv在处理中文上更稳定;如果必须读csv,记得尝试utf-8、gbk、latin1三种编码。
至于现在流行的“AI怎么生成代码”,我的建议是:可以用AI辅助debug,也可以让它解释报错信息,但不要直接把整个需求贴给它让它生成完整代码。C题的坑往往在业务理解上,AI不了解题目背景,生成的代码就算语法全对,也可能在特征处理上完全不符合题意。最好的用法是,你先把思路理清楚,再用AI帮你把某个具体函数写得规范一点,比如“帮我用pandas实现按站点分组滑动平均”,这种粒度AI能发挥很大价值。
我个人在实际操作中体会最深的,其实是“先跑通最小版本再优化”这个原则。很多队伍喜欢在开局就试图做一套完美的全流程管线,结果中间某个步骤报错,卡了两小时没跑出第一个结果,心态直接崩了。我每次带队都要求队员先按最简单的方式(哪怕直接用均值预测)全流程跑通一遍,把数据和接口都理清,再逐步替换成更复杂的模型。这样每一步迭代都有对照,出问题时也知道是哪个环节引入的。
最后再分享一个小技巧:比赛结束前留出30分钟,把你论文里的每个数字都回溯到代码输出文件里,确保摘要、正文和附录的结果一致。C题每年都有队伍因为“摘要里写的RMSE和正文表格里的对不上”被扣分,这种低级失误真的非常可惜。数据科学比赛比的不是谁的模型更炫,而是谁更能把问题讲清楚、把结果落得实。
