十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

天池数字制造赛事代码拆解:从初赛17名学到的建模全流程

天池数字制造赛事代码拆解:从初赛17名学到的建模全流程 简介天池“津南数字制造算法挑战赛”赛场一初赛第17名Drop队的完整源码包面向数据竞赛选手、算法工程师和希望提升预测建模能力的入门者。压缩包共13个文件以7个ipynb分析笔记为主体配合3个Markdown说明、2个Python脚本和1个CSV数据文件完整呈现从数据清洗、特征工程、模型选择到超参数调优、交叉验证与效果评估的竞赛流程整个包仅2.98MB轻量便于下载。已有140人学习说明该方案具备较好的参考热度。通过这份源码可以重点学习Pandas数据预处理操作、XGBoost/LightGBM等集成模型在制造数据上的应用以及GridSearchCV/RandomizedSearchCV调参、K折交叉验证避免过拟合、多指标评估等实战技巧目录结构清晰适合逐模块复现也能感受队伍在项目组织和代码注释上的实践经验对理解天池赛题思路和工业制造场景下的数据建模都有直接借鉴价值。1. 一场天池比赛的 zip 里藏着比分数更值钱的东西初赛 17 名这个位次在榜单上不亮眼却是竞赛代码最值得拆开的样本前排队伍的代码多半已经收得很紧反而这个段位的代码还能看到完整的试错痕迹、特征迭代记录和团队对业务指标的理解。“津南数字制造算法挑战赛”赛场一放在数字制造这类赛道上出题方向通常绕不开“用一段加工过程参数预测产线结果”的建模问题数据形态以高维表格、时序片段的组合为多评估指标在 MAE、MSE、F1 之间轮转。这篇博文顺着标题里的代码包把一条能打进初赛前 20 的常规路线拆解成五个环节任务与数据分析、基线模型、特征构造、调参与融合、交付代码的整理。既适合第一次带队参加天池比赛的工程师也适合想把手头表格建模流程往生产环境迁移的人。2. 赛场一的赛题先猜清数据、任务与评估指标之间的关系拿到一个以 zip 形式交付的竞赛代码第一步不是看模型而是先还原赛题假设。数字制造类比赛有一个共同点提供给选手的不是干净的特征表而是带时序关系、带异常值、带字段缺失的原始过程数据。赛场一具体是预测质量合格率、预测工艺参数输出还是做异常判定题目给的评估指标会直接决定建模的方向。2.1 从代码结构反推数据结构一个初赛打进前 20 的队伍代码包里一般会包含数据探索的痕迹。常见做法是先读一遍 train / test 的字段类型分布再决定后续特征怎么构造。数字制造场景里常见的数据集形态有三种数据形态典型字段建模方式纯表格型物料编号、工序号、温区、压力、速度LightGBM、XGBoost 直接拟合时间序列片段传感器读数、时间戳、设备 ID窗口特征 树模型或 LSTM混合型过程段统计量 成品终检标签统计特征 分类/回归模型很多选手拿到数据就急着做归一化这在树模型竞赛里是个常见误用。数字制造数据里的“温度 220”和“压力 3.5”量纲不同但 LightGBM 这类基于分裂的模型对单调变换不敏感反而对特征里的缺失值分布、尾部异常值很敏感。先看字段缺失率和取值分布再决定是补还是删是更稳妥的顺序。2.2 评估指标决定模型优化目标赛场一的指标如果是回归型初赛排名大概率看的是 MAE 或 MSE。这两者的差异直接影响调参策略MSE 对离群点惩罚重需要处理长尾标签MAE 则更贴近“预测误差绝对值”的业务口径LightGBM 里对应objective: regression_l1。如果是指标是 F1 之类的分类指标就要注意正负样本比例数字制造场景下合格品总是占多数少数类召回才是拿分关键。还有一类容易忽略的情况比赛数据里可能存在时间泄漏。比如 test 集的时间范围在 train 集之前或者同一物料批次同时出现在 train 和 test 里。用pandas做交叉检查时一般可以看nunique和 ID 交集import pandas as pd train pd.read_csv(train.csv) test pd.read_csv(test.csv) # 检查是否存在重叠 ID若重叠需要按时间分组 id_col material_id overlap len(set(train[id_col]) set(test[id_col])) print(foverlap: {overlap}) # 查看时间分布是否倒挂 if time in train.columns: print(train[time].min(), train[time].max()) print(test[time].min(), test[time].max())这段代码做的事很简单先查 ID 交集再查时间范围。如果 overlap 很大说明训练和测试来自同一批物料的不同工序段此时直接随机划分会高估模型效果需要改成按物料分组切分验证集。这个步骤看起来基础但很多初赛翻车的队伍就是漏了它线下分数比线上高出一大截怎么调都回不去。2.3 赛场一的常见任务假设结合“津南数字制造”的赛题范围赛场一更偏向回归任务用加工过程参数预测一个连续质量指标。原因有三点回归任务的评估指标弹性大初赛可以按误差排序数字制造的过程数据天然连续特征工程的可发挥空间比分类任务大方便筛选选手。基于这个假设后续的模型方案都围绕回归来设计同时保留分类头的切换能力这样即使题目实际是二分类代码也不至于推翻重来。3. 用 LightGBM 跑通第一版 baseline最小代码与核心参数竞赛界的共识是第一版提交不要上深度学习先跑通树模型基线。树模型对缺省值、异质特征、量纲差异的容忍度高调参路径清晰而且后续特征工程带来的收益可以直接归因。赛场一这种中等规模表格数据LightGBM 是效率上最稳的选择。3.1 最小训练代码以下代码是 baseline 的常见写法直接读取训练集做最简单的时间特征然后训练并预测提交。import lightgbm as lgb import pandas as pd from sklearn.model_selection import KFold from sklearn.metrics import mean_absolute_error train pd.read_csv(train.csv) test pd.read_csv(test.csv) target quality_score features [c for c in train.columns if c not in [target, id, time]] # 简单时间特征小时、星期 for df in [train, test]: df[hour] pd.to_datetime(df[time]).dt.hour df[weekday] pd.to_datetime(df[time]).dt.weekday features [hour, weekday] params { objective: regression_l1, metric: mae, learning_rate: 0.05, num_leaves: 31, feature_fraction: 0.8, bagging_fraction: 0.8, bagging_freq: 1, verbose: -1, seed: 2024, } kf KFold(n_splits5, shuffleTrue, random_state42) oof pd.Series(0.0, indextrain.index) pred pd.Series(0.0, indextest.index) for tr_idx, va_idx in kf.split(train): tr, va train.iloc[tr_idx], train.iloc[va_idx] dtr lgb.Dataset(tr[features], tr[target]) dva lgb.Dataset(va[features], va[target]) model lgb.train(params, dtr, num_boost_round2000, valid_sets[dva], callbacks[lgb.early_stopping(100)]) oof.iloc[va_idx] model.predict(va[features], num_iterationmodel.best_iteration) pred model.predict(test[features], num_iterationmodel.best_iteration) / kf.n_splits print(CV MAE:, mean_absolute_error(train[target], oof))3.2 参数选择的逻辑objective: regression_l1对应 MAE 优化和线上指标一致num_leaves从 31 起步不要一上来就调 256叶子增多会放大噪声feature_fraction和bagging_fraction设为 0.8让每棵树看到不同的特征子集和样本子集降低方差。这套参数在没有明显过拟合信号时能跑出一个可对比的分数基线。关于早停轮数100 轮在表格数据里比较常见。设置太小时模型欠拟合太大则白白浪费时间。验证集采用 K 折交叉验证而不是单次 holdout原因在于工艺数据往往存在批次效应单次划分的分数可能落在乐观或悲观的位置上K 折的均值才能反映真实水平。3.3 baseline 跑完之后的三个判断拿到第一版 CV 分数后要做三件事对比 CV 和线上分数差距在 5% 以内说明划分方式合理查看特征重要性model.feature_importance()看是不是只有少数特征在起作用看预测值分布和真实值分布是否接近。如果预测值整体偏移说明标签本身需要处理比如取对数或做分位变换。这里要专门提醒一个容易踩的坑不要把time列直接删掉。赛题数据里的时间戳即使不作为特征也应作为验证集划分的依据。用train_test_split默认随机切分会打散同一批物料的过程片段CV 分数虚高到线上对不上。4. 特征工程与模型调优把 CV 分数打下来才能进前 20Baseline 只是入场券打进初赛 17 名靠的是特征迭代。数字制造数据的特征空间有其固定套路按“时序特征 - 统计特征 - 目标编码 - 非线性交互”的层次递进每加一组特征都要重新跑一次 CV禁止一次性堆几十个特征然后指望模型自己挑。4.1 滑动窗口与滞后特征赛场一数据如果带时间顺序滑动窗口是收益最大的一组特征。常见的做法是对每个物料/设备 ID 分组计算传感器列的滚动均值、滚动标准差、滚动最大值和滚动最小值。窗口大小需要尝试一般从 3、5、10 开始做网格搜索。# 对每个批次做滑动窗口特征 def add_rolling_features(df, group_col, value_cols, windows[3, 5, 10]): df df.sort_values([time]).reset_index(dropTrue) g df.groupby(group_col)[value_cols] for w in windows: df[f{value_cols}_mean_{w}] g[value_cols].transform( lambda x: x.rolling(w, min_periods1).mean()) df[f{value_cols}_std_{w}] g[value_cols].transform( lambda x: x.rolling(w, min_periods1).std().fillna(0)) return df滚动窗口的关键是min_periods1保证窗口前几个样本不全为空值不然第一行数据直接丢弃会引入系统性偏差。标准差列要在 fillna 之前算标准差为 0 代表窗口内无波动对数字制造场景来说这是一个有效信号不能填成全局均值。窗口大小的选择要考虑业务节拍一个工序循环大概多久窗口太短抓不住趋势太长则把多个工艺阶段混在一起。滞后特征lag在时间序列竞赛里常见但数字制造数据不一定是严格时序用的时候要做条件判断。只有当同 ID 的记录按时间排序有意义时才能给某列加 lag_1、lag_2。加了滞后特征之后要检查最重要的特征是不是滞后列本身如果是说明模型是在用历史结果猜未来值可能存在泄漏风险。4.2 外部 ID 类字段的处理方式物料编号、设备编号、人员编号这类高基数类别特征树模型直接 label encode 也能用但效果一般因为 0、1、2 之间的数值距离对树分裂没有语义含义。常见做法是目标编码target encoding用历史均值替代类别本身。这一步要用 K 折内编码防止泄漏from sklearn.model_selection import KFold import numpy as np def target_encoding(df, col, target, n_folds5): df[temp] df[col].astype(str) df[te] np.nan kf KFold(n_splitsn_folds, shuffleTrue, random_state42) for tr_idx, va_idx in kf.split(df): te_map df.iloc[tr_idx].groupby(temp)[target].mean() df.loc[va_idx, te] df.loc[va_idx, temp].map(te_map) return df.drop(columns[temp])目标编码的平滑参数平滑系数没有在这段代码里展示实际使用中一般会加一个min_samples_leaf防止某类只有一两条样本时均值失真。目标编码在分类比赛里是神器在回归比赛里要谨慎因为把目标变量编码进特征后CV 分数会显著下降容易误判为模型变好需要结合线上分数判断是否真的有效。4.3 调参顺序与组合策略LightGBM 的调参不能一次全调。常见顺序是先固定learning_rate0.05调num_leaves和min_data_in_leaf控制模型复杂度再固定这两个调feature_fraction和bagging_fraction增加随机性最后调lambda_l1和lambda_l2正则。每一步只动一个参数记录 CV 变化做成一张表实验num_leavesfeature_fractionbagging_fractionCV MAE说明baseline310.80.82.153初始参数加深630.80.82.147叶子增加有微弱收益加大随机性630.60.72.156随机性过大欠拟合加正则630.80.82.149lambda_l11.0 稳定这张表反映的规律常见于树模型竞赛叶子数增加带来的收益一般 0.01 以内而随机性调过头会让 CV 恶化接近 0.01正则项的主要作用是稳定线上表现而不是提升线下分数。你能拿到的排名提升大多来自特征组而不是调参基线 2.153 的分数里特征工程一般能打掉 0.03 以上调参只能打掉 0.01。4.4 模型融合与误差分析模型融合在初赛前 20 的代码里几乎必然出现。常见做法是 LightGBM XGBoost CatBoost 三个模型的结果做加权平均权重通过线性搜索确定。但比融合更先做的应该是误差分析把 CV 预测值按真实值区间划分看误差集中在哪个区间。数字制造比赛最常见的误差形态是中间区段误差小两端极值误差大。这说明模型学到了均值回归倾向对异常质量情况不敏感。处理方式是单独训练一个极值分类器先判断样本是否落在两端区间再对两端样本用另一个回归模型单独校正。这类“套层模型”的结构在竞赛中并不复杂但对业务落地很有参考价值先粗筛再精修。5. 固定随机源、重放特征流程把 zip 里的代码变成团队资产初赛排名之外的隐形考核是代码复用性。数字制造挑战赛这类企业赛题评委或主办方可能会要求复现代码或者后续办复赛时要求在同一套数据上扩展方案。一个 zip 包能不能在另一个工程师机器上原样跑出相近分数决定了这份代码的实际价值。5.1 随机种子固定的三个位置固定随机源不只是设置random_state42。第一处是KFold的shuffle这个漏掉会导致每次切分不同第二处是 LightGBM 的seed参数第三处是模型融合时若用到sklearn的模型要给它们的random_state逐一赋值。误用做法是只固定 KFold模型侧完全随机结果线上分数每次重跑差 0.002看起来不多但在初赛这种差距只有 0.001 的排名段足够让排名浮动十几位。验证固定是否生效的方法在代码里把 seed 打印出来同一台机器跑两次比较oof输出的 SHA256 哈希一致才说明随机源全部锁死。5.2 特征代码的版本化管理特征工程代码最忌大段注释和多次复制粘贴。常见做法是写一个build_features.py内部按函数划分特征组add_basic_features、add_rolling_features、add_target_encoding每个函数只操作 DataFrame 并返回新列。给每个特征命名加上前缀比如roll_、te_、lag_这样后续在特征重要性列表里能一眼看出特征来源。zip 包的目录结构建议按“数据、特征、模型、提交”分层保留模型文件和预测结果文件方便回滚到特定版本。不推荐把所有代码塞进一个 notebook 里notebook 的单元格执行顺序一旦乱掉整个流程就无法复现。5.3 提交前的最后验证最后一晚的技术动作通常是一次完整的干净重跑。删掉中间缓存、新建虚拟环境、按文档序依次执行三个脚本python 1_preprocess.py --input data/train.csv --output data/train_fe.csv python 2_train.py --fold 5 --seed 2024 python 3_predict.py --model output/lgb_0415.txt --output submit.csv三个脚本串行执行完毕之后对比本次提交分数与上一次提交分数的差异来源确认不是由随机波动引起。如果 CV 分数下降但线上分数上升说明验证集划分与线上分布有偏差这时候要检查是否漏了时间维度上的分组。这一系列操作让 zip 里的代码从“比赛代码”变成“可复现的算法资产”换一个人拿到手也能在半小时内重新跑出同一份提交文件。本文还有配套的精品资源点击获取
返回列表