
简介本资源为泰迪杯2021A题《基于Bagging和深度学习的上市公司财务数据造假预测》的完整Python实现面向参加数据挖掘竞赛、研究财务风控与集成学习的学生及算法工程师。项目围绕三个赛题小问展开先按行业分类筛选造假相关财务指标并比较行业差异再分别识别制造业与其他行业第6年造假公司。方案在问题一采用SMOTE过采样后用DecisionTree、RandomForest、ExtraTree、XGBoost四种树模型计算特征重要性均值取前30个特征问题二、三构建DCRN网络融合多层感知机、残差网络与Cross网络并引入BatchNorm、Dropout与提前停止最后以Bagging集成降低方差、缓解样本不均衡。资源包共35个文件含15个csv数据、9个py源码、3张png图表及xlsx、pdf、md等说明文档约37.07MB目录涵盖特征工程、模型训练、交叉验证与预测脚本。已有41人学习适合作为赛题复现与深度学习二分类实战参考。1. 从一份 zip 说起Bagging 加深度学习怎么做财务造假预测上市公司财务造假预测这个方向很多人第一反应是「拿逻辑回归跑一遍财报指标就完事」。真做过就知道单一模型在类别极度不平衡、样本量只有几千条的财务数据集上召回率经常低得没法看——造假样本占比通常不到 5%模型全预测成「不造假」也能有 95% 以上的准确率这种数字毫无意义。这份资源给了一条更务实的路子用 Bagging 集成思想配合深度学习模型把「弱分类器投票」和「神经网络特征提取」两件事拼到一起专门对付高维、小样本、强不平衡的财务数据。资源本身是一个 Python 源码包加项目说明核心是完整的训练与预测流程数据预处理、特征工程、Bagging 集成层、深度学习基分类器、评估指标。适合两类人一类是金融风控、审计方向想找可复现 baseline 的从业者另一类是想拿一个真实不平衡分类场景练手 Bagging 和深度学习结合的算法学习者。下面按「资源是什么 → 怎么跑起来 → 参数怎么调 → 坑在哪」的顺序拆开讲能直接抄的代码和参数我都会给全。2. 拆开源码包Bagging 与深度学习怎么拼在一起2.1 为什么不是单纯 Bagging也不是单纯深度学习先讲清楚选型理由不然调参就是瞎调。财务造假预测的数据特点很明确特征维度高几十到上百个财务比率、正负样本极度不平衡、单条样本噪声大财报本身有盈余管理空间。随机森林这类纯 Bagging 方法对不平衡数据天然不友好因为每棵树的训练子集里造假样本可能只有个位数树学不到规律。纯深度学习呢样本量不够时容易过拟合而且对超参敏感换个数据集就得重调。这份源码的思路是把两者接起来用 Bagging 做样本层面的重采样集成每个基学习器是一个深度学习模型常见做法是 MLP 或一维 CNN最后对多个基学习器的输出做投票或概率平均。这样既缓解了单模型过拟合又通过重采样让每个基学习器都能见到相对均衡的正负样本。我一般会把基学习器数量设在 10 到 20 之间太少集成效果不明显太多训练时间线性上涨而收益递减。2.2 目录结构与核心模块拿到 zip 解压后典型结构大致是这样不同版本文件名可能略有差异以实际为准financial_fraud_bagging_dl/ ├── data/ # 原始财务数据与标签 │ ├── raw_financial.csv │ └── label.csv ├── src/ │ ├── preprocess.py # 缺失值、标准化、SMOTE 过采样 │ ├── bagging_dl.py # Bagging 集成 深度学习基分类器 │ ├── train.py # 训练入口 │ └── evaluate.py # 评估指标计算 ├── config.yaml # 超参与路径配置 ├── requirements.txt └── README.mdpreprocess.py负责把原始财报字段清洗成模型能吃的数值矩阵bagging_dl.py是核心里面同时有 Bagging 的采样逻辑和深度学习基分类器的定义。config.yaml把学习率、基学习器数量、每棵「树」对应的网络层数都抽出来了改参数不用动代码这点对复现很友好。2.3 环境依赖与安装依赖不复杂主要是 PyTorch 或 TensorFlow 二选一源码通常只用一个加上 scikit-learn、pandas、imbalanced-learn。装环境这一步新手最容易翻车建议直接建虚拟环境python -m venv venv source venv/bin/activate # Windows 用 venv\Scripts\activate pip install -r requirements.txt如果requirements.txt里没锁版本我一般会手动确认三件事PyTorch 版本和 CUDA 是否匹配没 GPU 就用 CPU 版、scikit-learn 版本别太老imbalanced-learn对它有版本要求、pandas 读中文列名时编码别出问题。装完先跑一句python -c import torch, sklearn, imblearn验证别等到训练到一半才报缺包。3. 跑通训练流程从数据预处理到模型评估3.1 数据预处理缺失值、标准化与不平衡处理财务数据缺失是常态直接dropna()会丢掉大量样本。源码里常见做法是先用中位数填充数值列再对特征做标准化。不平衡处理是重点Bagging 本身有重采样但预处理阶段通常还会叠一层 SMOTE 或随机欠采样。下面是我按源码逻辑整理的可复现片段import pandas as pd import numpy as np from sklearn.preprocessing import StandardScaler from imblearn.over_sampling import SMOTE # 读取财务数据与标签 df pd.read_csv(data/raw_financial.csv, encodingutf-8) labels pd.read_csv(data/label.csv)[label] # 数值列中位数填充避免 dropna 丢样本 num_cols df.select_dtypes(include[np.number]).columns df[num_cols] df[num_cols].fillna(df[num_cols].median()) # 标准化财务比率量纲差异大必须做 scaler StandardScaler() X scaler.fit_transform(df[num_cols]) # SMOTE 过采样把造假样本比例拉到合理区间 smote SMOTE(random_state42, k_neighbors5) X_res, y_res smote.fit_resample(X, labels) print(过采样后正负样本比:, np.bincount(y_res))逻辑说明中位数填充比均值稳因为财务指标常有极端值标准化不能省否则净利润率这种小数和营业收入这种大数会把网络梯度带偏。k_neighbors默认 5样本特别少时可以降到 3否则 SMOTE 会生成过于相似的合成样本。注意 SMOTE 只能在训练集上做验证集和测试集必须保持原始分布不然评估结果虚高——这是血泪经验很多人栽在这。3.2 Bagging 集成层与深度学习基分类器核心模块把 Bagging 的 bootstrap 采样和深度学习网络绑在一起。每个基学习器拿到一份有放回抽样的子集训练一个独立的小网络最后汇总。下面这段是简化后的结构能看清数据流import torch import torch.nn as nn import numpy as np from sklearn.utils import resample class FraudMLP(nn.Module): def __init__(self, input_dim): super().__init__() self.net nn.Sequential( nn.Linear(input_dim, 64), nn.ReLU(), nn.Dropout(0.3), # 防过拟合财务样本少 nn.Linear(64, 32), nn.ReLU(), nn.Linear(32, 2) # 二分类输出 ) def forward(self, x): return self.net(x) def train_base_learner(X, y, input_dim, epochs30, lr1e-3): # bootstrap 有放回采样 X_s, y_s resample(X, y, replaceTrue, random_stateNone) model FraudMLP(input_dim) opt torch.optim.Adam(model.parameters(), lrlr) loss_fn nn.CrossEntropyLoss() X_t torch.tensor(X_s, dtypetorch.float32) y_t torch.tensor(y_s, dtypetorch.long) for _ in range(epochs): opt.zero_grad() out model(X_t) loss loss_fn(out, y_t) loss.backward() opt.step() return model逻辑说明resample(replaceTrue)就是 Bagging 的 bootstrap 核心每个基学习器看到不同的样本组合。Dropout(0.3)在小样本场景很关键我试过 0.5 会欠拟合、0.1 又压不住过拟合0.3 是比较稳的中间值。epochs30是经验值配合早停更好源码里如果没写早停建议自己加一个验证集监控。集成时把所有基学习器的 softmax 概率平均再取 argmax比硬投票稳。3.3 训练入口与评估指标训练脚本一般会循环训练 N 个基学习器然后统一评估。评估指标千万别只看 accuracy不平衡场景下要看召回率、F1 和 AUCfrom sklearn.metrics import recall_score, f1_score, roc_auc_score def ensemble_predict(models, X_test): probs [] X_t torch.tensor(X_test, dtypetorch.float32) for m in models: m.eval() with torch.no_grad(): p torch.softmax(m(X_t), dim1)[:, 1].numpy() probs.append(p) return np.mean(probs, axis0) # 概率平均 probs ensemble_predict(models, X_test) preds (probs 0.5).astype(int) print(Recall:, recall_score(y_test, preds)) print(F1:, f1_score(y_test, preds)) print(AUC:, roc_auc_score(y_test, probs))参数说明阈值 0.5 不是固定的造假预测里通常会把阈值调低比如 0.3来换更高召回宁可误报也别漏报具体看业务对误报的容忍度。AUC 对阈值不敏感适合用来比较不同集成规模的效果。跑完记得把n_estimators基学习器数量从 5 试到 20画一条 AUC 随数量变化的曲线找到收益拐点。4. 避坑与排查这份源码最容易翻车的五个地方4.1 现象准确率 0.97 但召回率接近 0原因数据极度不平衡模型学会了「全预测成不造假」。解决先确认 SMOTE 只在训练集做再把评估指标换成召回率和 F1最后把分类阈值从 0.5 下调。如果还不行检查 Bagging 的 bootstrap 采样是否真的让每个基学习器见到了正样本。4.2 现象训练 loss 震荡不收敛原因学习率太大或者标准化没做导致梯度爆炸。解决学习率从 1e-3 往下调到 1e-4 试确认StandardScaler是在训练集上 fit、再 transform 测试集别在全量数据上 fit 造成数据泄漏。4.3 现象换一台机器跑结果差很多原因随机种子没固定。Bagging 的 bootstrap 采样、SMOTE、网络初始化都带随机性。解决在config.yaml里统一设random_statenumpy、torch、sklearn 三处都要设否则复现就是玄学。4.4 现象SMOTE 报错 k_neighbors 过大原因少数类样本数少于 k_neighbors1。解决把k_neighbors降到少数类样本数减一或者改用SMOTEENN组合采样。样本极少时干脆放弃 SMOTE靠 Bagging 的类别权重来平衡。4.5 现象测试集 AUC 高但上线效果差原因训练集和测试集来自同一时间段存在时间泄漏。财务造假有滞后性用未来数据预测过去会虚高。解决按年份切分训练测试集用早期数据训练、后期数据验证这才是接近真实的评估方式。5. 进阶技巧把集成规模与阈值调出实用价值跑通 baseline 只是起点真正决定这份源码能不能用在业务里的是两件事集成规模和分类阈值的联合调优。我一般会写一个小网格搜索把基学习器数量、学习率、阈值三个变量一起扫用 F1 或业务加权指标选最优组合。下面这段可以直接套best {f1: 0, cfg: None} for n_est in [5, 10, 15, 20]: models [train_base_learner(X_res, y_res, X_res.shape[1]) for _ in range(n_est)] probs ensemble_predict(models, X_val) for th in [0.2, 0.3, 0.4, 0.5]: preds (probs th).astype(int) f1 f1_score(y_val, preds) if f1 best[f1]: best {f1: f1, cfg: (n_est, th)} print(最优配置:, best)参数说明n_est超过 15 之后 F1 提升通常不到 1 个百分点但训练时间翻倍所以拐点附近就够。阈值下调到 0.3 左右往往能把召回拉高 10 个点以上代价是误报增加这个取舍要跟业务方对齐。验证集一定要用原始分布没经过 SMOTE否则阈值会偏。还有一个容易被忽略的点特征重要性。深度学习基分类器是黑匣子但你可以用 permutation importance 或 SHAP 在集成层面算特征贡献把排名靠前的财务比率比如应收账款周转率、毛利率异常波动拿出来跟审计经验对照既能验证模型合理性也能给业务方一个可解释的交代。我习惯在每次调完参后强制跑一遍特征重要性确认模型没学到无关的噪声特征。从那以后我每次拿到新的财务数据集都先把预处理和评估切分走一遍再谈模型不然调参全是白费功夫。希望帮到你。本文还有配套的精品资源点击获取