资讯详情

2021安徽省大数据与人工智能竞赛本科组赛题实战:从数据清洗到模型融合全流程

📅 2026/10/10 17:27:36 | 华诺云谱 👁 阅读
2021安徽省大数据与人工智能竞赛本科组赛题实战:从数据清洗到模型融合全流程
简介这份资源是2021年安徽省大数据与人工智能应用竞赛人工智能网络赛本科组的完整赛题数据包面向高校参赛选手、AI课程学习者及需要真实项目练手的数据科学从业者。内容覆盖两大典型任务一是基于人脸图像预测年龄标签二是依据房源信息回归预测房屋价格房源字段包含电梯情况、楼层、户型、区域、装修情况、面积与建筑时间且部分信息存在缺失适合练习缺失值处理与特征工程。资源共1009个文件以1000张jpg人脸图像、4个csv数据表、3个py脚本及2个txt说明为主压缩包约13.47MB训练集、验证集、测试集按17000:3000:3000划分目录结构清晰。目前已有1068人学习下载读者可借此复现完整赛题流程掌握图像分类与回归建模的实战思路。1. 2021年安徽省大数据与人工智能应用竞赛本科组赛题数据一份被低估的实战练手素材如果你正在找一份能同时练大数据处理和人工智能建模的赛题数据2021年安徽省大数据与人工智能应用竞赛本科组的赛题数据值得认真翻一翻。它不像某些竞赛数据那样只给一个CSV就完事而是覆盖了数据清洗、特征工程、模型训练到结果提交的完整链路适合数据科学与大数据技术专业的学生、准备大数据面试题的求职者以及想用真实赛题练手人工智能大作业的工程师。这份数据的价值不在于难度多高而在于它的任务边界清晰、评价标准明确你能在几天内跑通一个完整流程而不是陷在数据理解的泥潭里。下面我从赛题结构、环境搭建、特征处理、模型调参到避坑把这条链路拆开讲清楚。2. 赛题数据长什么样先搞清楚任务边界再动手2.1 本科组赛题的典型任务结构安徽省大数据与人工智能应用竞赛本科组的赛题通常围绕一个具体业务场景展开比如用户行为预测、文本分类或结构化数据回归。2021年的赛题数据一般包含训练集、测试集和提交示例文件训练集带标签测试集不带标签你需要用训练集训练模型对测试集预测后按指定格式提交。常见做法是先看提交示例文件的列名和格式反推任务类型——如果是分类任务标签列通常是离散值如果是回归任务目标列是连续值。这一步看似简单但很多人直接扎进训练集做EDA最后发现提交格式对不上白白浪费时间。我一般会先写一段脚本把三个文件的基本信息打印出来行数、列数、每列的数据类型、缺失值比例、标签分布。这样能在五分钟内判断出这是分类还是回归、有没有严重类别不平衡、哪些列需要特殊处理。对于大数据方向的赛题数据量可能达到几十万行用pandas直接读没问题但如果超过内存就得考虑分块读取或换用更高效的工具。import pandas as pd # 读取训练集和测试集先看基本信息 train pd.read_csv(train.csv) test pd.read_csv(test.csv) sample_submit pd.read_csv(sample_submission.csv) print(训练集形状:, train.shape) print(测试集形状:, test.shape) print(提交示例列名:, sample_submit.columns.tolist()) print(\n训练集各列缺失比例:) print(train.isnull().mean().sort_values(ascendingFalse).head(10)) print(\n标签分布:) print(train[label].value_counts() if label in train.columns else train.iloc[:, -1].value_counts())这段代码的作用是快速建立对数据的整体认知。train.shape告诉你样本量和特征维度isnull().mean()帮你定位缺失严重的列value_counts()让你判断标签是否平衡。如果发现某一类占比不到5%后续建模就要考虑过采样或调整类别权重。参数方面head(10)只展示缺失最多的前10列避免输出刷屏如果标签列名不是label需要根据实际列名调整。2.2 环境准备与依赖版本赛题数据通常对Python版本和库版本有一定要求但不会像生产环境那样严格。我建议用Python 3.8以上pandas 1.3以上scikit-learn 1.0以上LightGBM或XGBoost选一个装。如果你打算用深度学习PyTorch或TensorFlow都可以但本科组赛题一般用树模型就能拿到不错的名次没必要上神经网络。安装命令很简单pip install pandas numpy scikit-learn lightgbm xgboost matplotlib seaborn如果你在Windows上遇到LightGBM安装失败常见原因是缺少Visual C运行库装一下VC_redist.x64.exe即可。另一个坑是pandas版本太老导致read_csv的low_memory参数行为不一致建议直接升级到最新稳定版。对于大数据集群部署策略感兴趣的同学这份赛题数据也可以放到Hive或Spark里做分布式处理但本科组赛题的数据量通常单机就能搞定不必过度设计。3. 从原始数据到特征矩阵清洗、编码与特征交叉3.1 缺失值处理与异常值检测赛题数据里缺失值是常态关键是怎么处理。数值列可以用中位数或均值填充类别列可以用众数或单独标记为缺失类别。我一般先看缺失比例低于5%的列直接填充高于30%的列考虑丢弃或作为特征标记。异常值检测用IQR或Z-score但要注意赛题数据里的异常值可能是真实业务信号不要盲目删除。比如用户年龄出现200岁那肯定是脏数据但订单金额出现极大值可能是大客户删了就丢信息。import numpy as np # 数值列用中位数填充类别列用众数填充 num_cols train.select_dtypes(include[np.number]).columns.tolist() cat_cols train.select_dtypes(include[object]).columns.tolist() for col in num_cols: if train[col].isnull().sum() 0: median_val train[col].median() train[col].fillna(median_val, inplaceTrue) test[col].fillna(median_val, inplaceTrue) for col in cat_cols: if train[col].isnull().sum() 0: mode_val train[col].mode()[0] train[col].fillna(mode_val, inplaceTrue) test[col].fillna(mode_val, inplaceTrue) # 用IQR标记异常值但不删除而是生成指示特征 for col in num_cols: Q1 train[col].quantile(0.25) Q3 train[col].quantile(0.75) IQR Q3 - Q1 lower Q1 - 1.5 * IQR upper Q3 1.5 * IQR train[f{col}_outlier] ((train[col] lower) | (train[col] upper)).astype(int) test[f{col}_outlier] ((test[col] lower) | (test[col] upper)).astype(int)这里的关键决策是用训练集的中位数和众数去填充测试集而不是各自填充否则会造成数据泄露。异常值不删除而是生成指示特征让模型自己决定是否利用这个信息。IQR系数1.5是常规做法如果数据分布偏态严重可以改成3.0。注意fillna的inplace参数在新版pandas中可能被弃用建议写成train[col] train[col].fillna(median_val)。3.2 类别编码与特征交叉类别特征不能直接丢给树模型需要编码。低基数类别用One-Hot高基数类别用Target Encoding或Frequency Encoding。我一般对类别数少于10的用One-Hot多于10的用频率编码因为Target Encoding容易过拟合需要配合交叉验证。特征交叉是提分的关键手段比如把用户ID和商品类别交叉成一个新特征或者把数值列分箱后与类别列组合。from sklearn.preprocessing import LabelEncoder # 低基数类别One-Hot高基数类别频率编码 low_card_cols [col for col in cat_cols if train[col].nunique() 10] high_card_cols [col for col in cat_cols if train[col].nunique() 10] train pd.get_dummies(train, columnslow_card_cols, drop_firstTrue) test pd.get_dummies(test, columnslow_card_cols, drop_firstTrue) # 确保训练集和测试集列对齐 train, test train.align(test, joinleft, axis1, fill_value0) for col in high_card_cols: freq_map train[col].value_counts(normalizeTrue).to_dict() train[f{col}_freq] train[col].map(freq_map) test[f{col}_freq] test[col].map(freq_map) test[f{col}_freq].fillna(0, inplaceTrue) # 特征交叉示例数值列分箱后与类别列组合 train[age_bin] pd.cut(train[age], bins5, labelsFalse) train[age_cat_cross] train[age_bin].astype(str) _ train[category].astype(str) test[age_bin] pd.cut(test[age], bins5, labelsFalse) test[age_cat_cross] test[age_bin].astype(str) _ test[category].astype(str)align函数确保One-Hot后训练集和测试集的列完全一致避免因为测试集出现新类别导致列数不匹配。频率编码用训练集的分布映射到测试集测试集出现新类别时填0。特征交叉后可能产生高基数特征需要再做一次频率编码或Target Encoding。这一步做完你的特征矩阵基本就准备好了接下来可以喂给模型。4. 模型训练与调参LightGBM为什么是赛题首选4.1 用LightGBM跑通第一个Baseline本科组赛题的数据量通常在几万到几十万行特征维度几十到几百LightGBM在这种场景下训练速度快、精度高、调参相对容易是赛题首选。XGBoost也可以但LightGBM在大数据量下优势更明显。第一个Baseline不需要调参用默认参数跑一遍看看交叉验证分数和提交格式是否正确。import lightgbm as lgb from sklearn.model_selection import StratifiedKFold from sklearn.metrics import accuracy_score, f1_score # 准备特征和标签 feature_cols [col for col in train.columns if col not in [label, id]] X train[feature_cols] y train[label] X_test test[feature_cols] # 5折交叉验证 skf StratifiedKFold(n_splits5, shuffleTrue, random_state42) oof_preds np.zeros(len(X)) test_preds np.zeros(len(X_test)) for fold, (train_idx, val_idx) in enumerate(skf.split(X, y)): X_train, X_val X.iloc[train_idx], X.iloc[val_idx] y_train, y_val y.iloc[train_idx], y.iloc[val_idx] model lgb.LGBMClassifier( n_estimators1000, learning_rate0.05, num_leaves31, random_state42, n_jobs-1 ) model.fit( X_train, y_train, eval_set[(X_val, y_val)], eval_metricmulti_logloss, callbacks[lgb.early_stopping(50), lgb.log_evaluation(100)] ) oof_preds[val_idx] model.predict_proba(X_val) test_preds model.predict_proba(X_test) / skf.n_splits # 评估 oof_labels np.argmax(oof_preds, axis1) print(OOF Accuracy:, accuracy_score(y, oof_labels)) print(OOF F1:, f1_score(y, oof_labels, averageweighted))early_stopping(50)表示验证集指标50轮不提升就停止训练避免过拟合。n_estimators1000是上限实际训练轮数由早停决定。num_leaves31是默认值控制树复杂度。learning_rate0.05比默认的0.1更保守通常能带来更稳定的验证分数。test_preds累加每折的预测概率再平均这是标准的Bagging策略。如果任务是回归把LGBMClassifier换成LGBMRegressoreval_metric换成rmsepredict_proba换成predict。4.2 关键参数怎么调学习率、叶子数和特征采样LightGBM的参数很多但真正影响大的就几个learning_rate、num_leaves、min_child_samples、feature_fraction、bagging_fraction。我一般先用默认参数跑一个Baseline然后按以下顺序调先把learning_rate降到0.05num_leaves提到63看验证分数是否提升如果过拟合降低num_leaves或提高min_child_samples如果欠拟合提高num_leaves或降低min_child_samples。feature_fraction和bagging_fraction控制在0.7到0.9之间能提升泛化能力。# 调参后的模型配置 model lgb.LGBMClassifier( n_estimators2000, learning_rate0.03, num_leaves63, min_child_samples20, feature_fraction0.8, bagging_fraction0.8, bagging_freq5, reg_alpha0.1, reg_lambda0.1, random_state42, n_jobs-1 )bagging_freq5表示每5轮做一次Bagging配合bagging_fraction0.8使用。reg_alpha和reg_lambda是L1和L2正则化防止过拟合。如果验证分数波动大把bagging_freq改成1bagging_fraction降到0.7。如果训练集很大min_child_samples可以提到50或100。调参不是越多越好我一般控制在10组以内用Optuna或GridSearchCV自动搜但要注意交叉验证的折数要和最终评估一致。4.3 模型融合与提交格式检查单模型跑通后可以尝试模型融合提分。最简单的是把LightGBM和XGBoost的预测概率加权平均权重按验证分数分配。更复杂的是Stacking用第一层模型的输出作为第二层模型的输入但本科组赛题一般加权平均就够了。提交前一定要检查格式列名是否和示例文件一致行数是否和测试集一致预测值是否在合法范围内。# 加权融合示例 lgb_preds test_preds # LightGBM预测概率 xgb_preds np.load(xgb_test_preds.npy) # XGBoost预测概率 # 按验证分数分配权重假设LGB分数更高 final_preds 0.6 * lgb_preds 0.4 * xgb_preds final_labels np.argmax(final_preds, axis1) # 生成提交文件 submission pd.DataFrame({id: test[id], label: final_labels}) submission.to_csv(submission.csv, indexFalse) print(提交文件形状:, submission.shape) print(标签分布:, submission[label].value_counts())提交前用sample_submission的列名和顺序核对一遍避免因为列顺序不对导致评分失败。如果任务是回归np.argmax换成直接输出预测值。标签分布要和训练集大致一致如果偏差太大可能是模型有问题或测试集分布不同。5. 避坑与排查赛题数据里最容易翻车的五个地方5.1 数据泄露用测试集信息填充训练集现象交叉验证分数很高但提交后分数很低。原因在填充缺失值或编码类别时用了全量数据训练集测试集的统计量导致测试集信息泄露到训练集。解决所有统计量中位数、众数、频率映射必须只在训练集上计算然后应用到测试集。用train[col].median()而不是full_data[col].median()。5.2 类别编码后列不对齐现象训练时特征列有100个预测时只有95个报错feature_names mismatch。原因One-Hot编码后训练集和测试集的类别不一致测试集缺少某些类别或多了新类别。解决用align函数对齐或者用pd.get_dummies后手动补齐缺失列。更稳妥的做法是用sklearn的OneHotEncoder设置handle_unknownignore。5.3 早停指标选错导致过拟合现象训练集AUC到0.99验证集AUC只有0.75。原因早停用的指标和最终评估指标不一致比如用binary_logloss早停但最终看AUC。解决早停指标要和赛题评价指标一致。分类任务用multi_logloss或auc回归任务用rmse或mae。如果不确定赛题用什么指标看提交示例文件的格式分类一般看准确率或F1回归看RMSE。5.4 提交文件行数或ID顺序错误现象提交后系统提示格式错误或分数为0。原因提交文件的行数和测试集不一致或者ID列的顺序和测试集不同。解决生成提交文件时用test[id]而不是重新生成ID确保行数和顺序完全一致。如果测试集没有ID列用索引代替但要在提交示例文件里确认。5.5 忽略数据分布偏移现象训练集和测试集的标签分布差异大模型在测试集上表现差。原因赛题数据可能是按时间划分的训练集是早期数据测试集是后期数据分布发生了变化。解决用时间序列交叉验证代替随机交叉验证或者在特征中加入时间相关特征。如果发现某个特征在训练集和测试集上的分布差异很大考虑删除或做归一化。6. 进阶技巧用伪标签和特征选择再提两个点伪标签是赛题后期提分的常用手段先用训练集训练一个模型对测试集预测把置信度高的预测结果作为伪标签加入训练集重新训练模型。置信度阈值一般设0.9或0.95太低会引入噪声太高则伪标签样本太少。我一般会跑两轮伪标签第一轮用0.9阈值第二轮用0.95阈值观察验证分数是否提升。# 伪标签示例 test_preds_proba model.predict_proba(X_test) high_conf_idx np.where(test_preds_proba.max(axis1) 0.9)[0] pseudo_labels test_preds_proba[high_conf_idx].argmax(axis1) # 把伪标签样本加入训练集 X_pseudo X_test.iloc[high_conf_idx] y_pseudo pd.Series(pseudo_labels, indexX_pseudo.index) X_augmented pd.concat([X, X_pseudo], axis0) y_augmented pd.concat([y, y_pseudo], axis0) # 重新训练 model_pseudo lgb.LGBMClassifier(**best_params) model_pseudo.fit(X_augmented, y_augmented)特征选择方面LightGBM自带feature_importances_可以按重要性排序保留前50或前100个特征。但要注意重要性低的特征不一定没用可能是被其他特征掩盖了。我一般会做两组实验一组用全部特征一组用Top 50特征看验证分数哪个高。如果Top 50更高说明有噪声特征如果差不多就用全部特征避免丢失信息。最后说一个我踩过的坑赛题数据里如果有ID列千万不要把它当特征喂给模型。ID列通常是唯一标识和标签没有因果关系但树模型可能会记住ID和标签的对应关系导致过拟合。我一般会在特征列表里直接排除ID列或者用drop删掉。另一个习惯是每次提交前把提交文件用head和describe看一遍确认没有异常值。这些习惯帮我省了很多后悔药。希望帮到你。本文还有配套的精品资源点击获取
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑