新闻详情

新闻详情

首页 / 资讯中心 / 详情

结合Bagging与深度学习的上市公司财务造假预测完整方案

发布时间:2026/9/25 9:28:53来源:尧图网络
结合Bagging与深度学习的上市公司财务造假预测完整方案
简介面向金融风控与机器学习研究者这是一套基于Bagging与深度学习的上市公司财务数据造假预测完整项目。方案先用SMOTE过采样结合DecisionTree、RandomForest、ExtraTree、XGBoost四种树模型计算特征重要性权重均值筛选出制造业与其他行业前30个关键特征随后构建融合多层感知机、残差网络与Cross网络的DCRN模型依靠短路机制缓解梯度消失通过类似外积的运算增强特征交互并引入Batch Normalize层加速收敛、防止过拟合最后以Bagging集成进一步降低方差。压缩包共33个文件、35.46MB含9个Python脚本数据预处理、特征工程、模型训练、预测与交叉验证、15个CSV数据文件附件及预处理结果、1份Excel原始表和1份PDF方案说明另附运行指南与依赖列表代码模块清晰可直接复现实验。已有191人学习下载适合对财务造假检测、集成学习及深度学习特征交叉感兴趣的读者参考。1. 财务数据造假预测一份能直接跑的 Bagging深度学习完整方案上市公司财务造假预测这类任务最尴尬的点在于论文方案一抓一大把但真正能把数据预处理、特征筛选、模型训练、集成推理串成一条能跑通流水线的资源少之又少。这份基于 Bagging 和深度学习的上市公司财务数据造假预测资源包恰好补上了这个缺口。它不是一个教学 demo而是把「制造业」和「其他行业」两套数据分别建模、特征筛选、DCRN 网络训练、Bagging 集成、ROC 曲线绘制串成了完整闭环的真实项目。源码包含 main.py、DCRN.py、bagging.py、feature_eng.py 等模块数据则包含附件1、附件2、附件3 以及预处理后的 preprocessed_data.csv。适合正在做财务造假识别、信用风险评估、或者想拿真实表格数据练手深度学习和集成学习的从业者——拿到手不是看热闹是可以直接对照着改参数、换数据集、跑出自己的结果。2. 从原始表格到训练样本特征工程与四模型筛选链路2.1 原始数据长什么样附件1/2/3 与 preprocessed_data.csv 的关系这份资源包里的数据分两层。第一层是原始数据附件1.csv、附件2.csv、附件3.xlsx。其中附件1 和附件2 是不同来源的财务指标表附件3 则是对应的标签和样本划分信息。第二层是预处理产物preprocessed_data.csv。这个文件是 feature_eng.py 跑完之后的输出也是后面 DCRN 模型直接依赖的输入。我第一次打开附件1.csv 时直观感受是列非常多但空值比例不低而且不同列的数值量纲差异很大有的字段是比率比如资产负债率有的字段是绝对数比如营收、利润总额。这种数据不能直接喂给神经网络原因有两个一是空值会被 pandas 默认处理成 NaN进入模型后要么报错要么被当 0 处理二是绝对数字段量纲动辄上亿和比率字段放在一起会让梯度更新被大数值列主导。preprocessed_data.csv 就是在解决这两个问题。它做的事包括缺失值填充常见做法是中位数填充因为财务数据通常右偏均值容易被极端值拉偏、异常值截断、标准化/归一化。这里有个关键点标准化是在整个数据集上做的但在真实落地时我习惯先用训练集拟合 scaler再用同一个 scaler 转换验证集和测试集避免数据泄露。2.2 SMOTE 过采样与四树模型特征重要性加权制造业和其他行业分开算这份资源在特征筛选阶段没有直接用深度学习而是先回到传统树模型。原因很实在树模型对特征重要性的估计有现成实现且对非线性关系敏感度高计算代价远低于深度学习。它选用了四种树模型——DecisionTree、RandomForest、ExtraTree、XGBoost——分别计算特征重要性权重值然后综合这几种树模型的结果计算均值最终选出制造业和其他行业各自权重排名前 30 的特征。为什么用四种而不是一种单一模型的特征重要性有偏。决策树容易过拟合训练集对噪声特征给出虚高的重要性RandomForest 通过 bagging 和随机特征子空间缓解了这个问题但在特征高度相关的财务数据上会把重要性分散到一组相关特征上ExtraTree 的随机切分进一步去相关性但对弱特征的评估偏保守XGBoost 在 boosting 框架下更关注难分样本重要性分布又不一样。四者取均值比任何单一模型都稳。另一个容易被忽略的细节是制造业和其他行业是分开建模的。制造业的重资产特征固定资产周转率、存货周转率和其他行业比如服务业、信息技术业差异巨大混在一起建模会让模型学到的模式两边都不讨好。所以资源包里 features_model 目录下分成「制造业」和「其他行业」两个子目录各自的特征重要性文件和筛选结果互不干扰。2.3 特征筛选脚本怎么跑feature_eng.py 与 config.py 的参数设置在动手跑之前先看配置文件 config.py它控制了整条链路的关键参数。我先给出一份典型的 config 内容按资源包场景还原的常见配置结构# config.py DATA_PATH { raw_1: data/附件1.csv, raw_2: data/附件2.csv, raw_3: data/附件3.xlsx, output: data/preprocessed_data.csv } FEATURE_SELECT { n_features: 30, models: [dt, rf, et, xgb], use_smote: True, smote_k_neighbors: 5, random_state: 42 } TRAIN_CONFIG { batch_size: 64, epochs: 100, learning_rate: 0.001, early_stopping_patience: 10, device: cuda }关键参数说明use_smote只影响特征筛选阶段不影响 DCRN 训练阶段——这一点后面第 3 章会细说。smote_k_neighbors5是 SMOTE 的默认近邻数对于财务造假这种典型不平衡数据造假样本通常只占 5%-15%k 值太小容易合成出和原始样本几乎一样的点k 值太大会跨过类别边界产生噪声样本5 是比较折中的选择。n_features30是最终保送进 DCRN 的特征个数这个值来自四模型重要性均值的 Top 30。跑特征筛选只需要一条命令python feature_eng.py --config config.py脚本内部执行顺序是读取附件1/2/3 → 合并原始字段 → 处理缺失值和离群值 → 按行业分组 → 对每组做 SMOTE 过采样 → 分别跑四个树模型 → 汇总特征重要性并取均值 → 输出 preprocessed_data.csv 和 features_model/{行业}/ 下的重要性文件。跑完你会看到终端输出每个模型的迭代进度以及最终选出的特征名称和权重值。建议重点看一眼features_imp目录下的文件里面同时保留了权重均值和每个单模型的权重方便你核对是不是真的取了四者均值。3. DCRN 网络结构与训练配置用深度学习替代树模型的二分类建模3.1 DCRN 的三条子网络全连接、残差短路与 Cross 外积交互特征筛选完成后建模阶段换成 DCRNDeep-Cross-Residual-NetWork。从名字就能看出来它把三类网络结构拼在了一起多层感知机负责基础的非线性映射多层残差网络通过短路操作解决梯度消失Cross 网络通过类似外积的运算增加特征之间的交互力度。只看文字描述容易觉得玄拆开看每条子网络的职责就清楚了子网络核心操作要解决的问题多层感知机MLP标准全连接 激活函数提供基础的特征非线性变换能力多层残差网络ResNet 风格跳跃连接输出 输入 F(输入)网络层数加深后的梯度消失问题Cross 网络特征外积交互x_{l1} x_0 * x_l^T * w b x_l显式建模高阶特征交叉挖掘财务指标之间的联合异常信号这里最值得展开的是 Cross 网络。传统 DNN 的特征交叉是隐式的需要靠深层网络逐层组合效率低而且在财务数据这种特征含义明确的场景下交叉的方向是不受控的。Cross 网络的做法是把每一层的输出都和初始输入 x0 做外积再经过权重矩阵映射后加回当前层——相当于每一层都在显式地强化「初始特征和当前组合特征」的交互。以营收增长率和应收账款增长率为例单独看任何一个指标造假信号都不明显但两者同时异常增长就是典型的提前确认收入信号。Cross 网络的外积交互可以让模型在浅层就捕捉到这个组合信号而不是等深层网络自己去碰运气。DCRN.py 的核心结构大致是这样# DCRN.py 结构示意 import torch import torch.nn as nn class CrossLayer(nn.Module): def __init__(self, input_dim): super().__init__() self.weight nn.Parameter(torch.Tensor(input_dim, input_dim)) self.bias nn.Parameter(torch.Tensor(input_dim, 1)) nn.init.xavier_uniform_(self.weight) def forward(self, x): # x: [batch, input_dim] x0 x.unsqueeze(2) # [batch, dim, 1] xl x.unsqueeze(1) # [batch, 1, dim] cross torch.matmul(x0, xl) # [batch, dim, dim] out torch.matmul(self.weight.unsqueeze(0), cross.view(-1, 1, input_dim*input_dim)).squeeze(1) # 此处为示意实际实现会做了维度压缩与残差连接 return out self.bias.squeeze(1) x class DCRN(nn.Module): def __init__(self, input_dim, hidden_dim128, num_residual_layers4): super().__init__() self.mlp nn.Sequential( nn.Linear(input_dim, hidden_dim), nn.ReLU(), nn.Linear(hidden_dim, hidden_dim) ) self.residual_layers nn.ModuleList([ nn.Linear(hidden_dim, hidden_dim) for _ in range(num_residual_layers) ]) self.cross_layer CrossLayer(input_dim) self.bn nn.BatchNorm1d(hidden_dim) self.classifier nn.Linear(hidden_dim, 1) def forward(self, x): # 残差分支每个残差层输出 relu(linear(relu(linear(x)))) x res self.mlp(x) for layer in self.residual_layers: res torch.relu(layer(res)) res res self.bn(res) # Cross 分支单独走外积交互 cross_out self.cross_layer(x) # 合并两分支后接分类头 combined res cross_out[:, :hidden_dim] # 维度对齐示意 return torch.sigmoid(self.classifier(combined))上面是示意性结构实际 DCRN.py 里的维度对齐和残差短路会处理得比这个例子更细致。逻辑要点有两个第一残差分支的每一层都保留了输入信息网络加深时不会出现梯度消失导致的训练停滞第二Cross 分支和残差分支在最后合并让模型同时拥有「深层次非线性」和「显式特征交叉」两种能力。3.2 Batch Normalize 与舍弃过采样训练策略为什么这么定资源里有两个反直觉的设计一是引入了 Batch Normalize 层二是舍弃了过采样机制。Batch Normalize 的作用是让每一层的输入分布保持稳定。财务数据经过标准化后整体分布是稳定的但每一批 batch 内的分布会有波动。如果不做 BN前面几层参数的微小变化会被放大到后面的层导致 loss 曲线震荡。加了 BN 之后每层输入被拉回单位方差附近收敛速度明显加快同时它也带了正则化效果能缓解过拟合。舍弃 SMOTE 这个决策更有意思。特征筛选阶段用 SMOTE 是因为树模型对少数类不敏感需要合成样本来帮助树模型学到造假模式。但 DCRN 是梯度下降训练过采样会带来两个副作用第一合成样本是 K 近邻插值产生的本身携带噪声标签神经网络会花费大量容量去拟合这些不真实的样本第二过采样会放大少数类在 loss 中的权重导致模型在多数类上的误报率飙升。资源里的做法是依靠神经网络强大的学习能力直接对少量样本的特征进行捕捉配合类别权重常见做法是 pos_weight 或 class_weight来平衡。训练时的类别不平衡处理在代码里体现为损失函数侧的调整而不是数据侧的合成。实践中我一般会在 BCELoss 里加上 pos_weight 参数让少数类的梯度贡献大一些但又不会像 SMOTE 那样引入虚假样本。3.3 从 config.py 到 main.py训练启动与超参数对照训练入口是 main.py它会加载 preprocessed_data.csv按行业拆分初始化 DCRN 模型开始训练并把最优权重存到 model 目录。启动命令python main.py --config config.py --industry manufacturing python main.py --config config.py --industry others--industry参数指定训练哪个行业分支两个行业分开训练、分开保存模型权重推理时也要对应加载。训练过程中的关键超参数和它对结果的影响列成一张表方便对照超参数典型值设置过大设置过小batch_size64GPU 显存压力大BN 统计不稳定梯度更新频繁收敛慢且震荡learning_rate0.001loss 直接发散或震荡训练进展缓慢容易停在局部最优epochs100过拟合风险上升需配合早停模型未收敛AUC 偏低early_stopping_patience10训练时间过长模型还没学好就被打断hidden_dim128参数增多小数据集上过拟合表达能力不够AUC 上不去num_residual_layers4训练变慢残差也救不了过深非线性能力不足训练时终端会输出每个 epoch 的训练 loss 和验证 AUC。正常情况下前 20 个 epoch loss 会快速下降AUC 逐步爬升到 0.8 以上如果 loss 在前 5 个 epoch 内没有明显下降优先检查 learning_rate 是不是设置过大或者特征是否没有做标准化。训练完成后model 目录下会出现制造业和其他行业各自的权重文件。不要急着删训练日志后面 Bagging 集成和 ROC 曲线绘制都要用到这些中间产物。4. 复现避坑与常见问题从路径缺失到显存溢出的排查记录4.1 现象predict.py 报 pandas 找不到列第一次跑 predict.py 时报错信息是 KeyError提示某个列名不存在。核对后发现feature_eng.py 输出的 preprocessed_data.csv 里列名已经经过了标准化处理列名统一为英文或拼音缩写而 predict.py 里硬编码的列名还是从附件1.csv 里看来的中文列名。原因是资源包里的列名映射分散在不同脚本里predict.py 读取模型权重时需要和训练时的特征顺序严格一致否则权重和特征对不上。解决方式不要手动改 predict.py 里的列名。先读一遍 features_model/{行业}/ 目录下的特征重要性文件确认最终选出的 30 个特征列名再写个简短的列名比对脚本确保 preprocessed_data.csv 的列顺序和模型输入顺序一致。从那以后我每次都强制走一遍列名对齐检查——用脚本输出训练时特征列表和预测时输入特征列表的差异而不是肉眼比对。4.2 现象loss 不降反升AUC 在 0.5 附近徘徊训练 DCRN 时遇到 loss 在前 20 个 epoch 完全不动后面反而缓慢上升。检查数据没有发现问题最后定位到 Cross 层的初始化方式。Cross 网络的权重如果直接用默认初始化外积运算产生的数值范围会很大加上残差连接之后激活值可能直接溢出。常见做法是换成 Xavier 均匀初始化让权重方差匹配输入维度。另外Cross 层输出和残差分支合并时如果两个分支的量纲不一致一个在 0-1 范围一个在 -5 到 5 的范围也会导致 loss 震荡。解决方式保持资源包里 DCRN.py 的初始化方式不变不要自己「优化」成 kaiming 初始化或者什么都不做。如果确实要调先把 Cross 层输出做一次 LayerNorm 再合并这是改动最小且有效的方式。4.3 现象制造业模型 AUC 明显高于其他行业资源包里两个行业模型最终效果有落差制造业的 AUC 通常能到 0.9 以上其他行业可能只有 0.8 左右。这不是 bug而是制造业的财务造假模式更集中在少数几个高频特征上——存货、应收账款、固定资产这类重资产科目造假信号强烈其他行业包含的子行业太多服务业、信息技术业、房地产业的造假模式差异很大混在一起训练等于让模型同时学多种不同规律。解决方式有两个方向。第一直接接受这个结果在汇报时分开报告两个行业的指标不要合在一起算平均。第二如果其他行业的样本量足够可以在资源包的基础上按子行业进一步拆分比如把信息技术业单独拎出来训练一个模型经常能看到 AUC 提升 3-5 个点。4.4 现象k_fold_cross_valid.py 跑得很慢GPU 占用却不高这个脚本是资源包里的交叉验证模块用于评估模型稳定性。慢的原因不是单次训练慢而是 Bagging 和交叉验证叠加之后模型数量翻了好几倍。K 折交叉验证本身就是 K 次完整训练Bagging 每次训练又要训多个子模型两者相乘训练次数直接爆炸。解决方式是先缩小验证规模。把 K 折从 10 折改成 5 折Bagging 的子模型数量从 11 个减到 5 个先用小规模跑通流程确认代码没问题后再逐步恢复。另一个建议是不要把交叉验证和 Bagging 同时跑。先单独跑交叉验证确认模型稳定性再单独跑 Bagging 看集成增益最后再合起来做最终评估。4.5 现象requirements.txt 里的 torch 版本装不上资源包里的 requirements.txt 如果直接pip install -r requirements.txt在部分环境下会失败常见原因是 PyTorch 版本和 CUDA 版本不匹配。比如 requirements.txt 里写的是 torch 2.x但机器 CUDA 是 10.2就会报找不到对应 wheel。解决方式是改用官方安装命令先确认 CUDA 版本再安装对应匹配的 PyTorch。CPU 环境的话直接装 CPU 版即可这个规模的模型 CPU 也能跑就是慢一些。不要在一开始就强上 GPU 环境先确保代码逻辑是对的。5. Bagging 集成后的推理验证把预测结果落到特征重要性与 ROC 曲线5.1 多模型投票与平均概率bagging.py 里做了什么Bagging 的核心逻辑在 bagging.py 里。它做的事可以概括为用不同的随机种子和数据子集训练多个 DCRN 模型推理时把所有模型的输出概率做平均用平均概率作为最终预测。# bagging.py 逻辑示意 import numpy as np import torch from DCRN import DCRN def predict_bagging(models, x): models: 训练好的 DCRN 模型列表 x: 输入特征shape 为 [batch, n_features] prob_list [] for model in models: model.eval() with torch.no_grad(): prob model(torch.tensor(x, dtypetorch.float32)) prob_list.append(prob.numpy().ravel()) # 对所有子模型的概率取均值作为最终预测 final_prob np.mean(np.array(prob_list), axis0) return final_prob这里的关键设计是「取平均概率」而不是「投票」。投票只保留离散的 0/1 标签会损失概率置信度信息平均概率保留了每个子模型的置信度最终结果会更平滑。而且对于财务造假这种需要输出风险等级的落地场景平均概率可以直接当风险分数用阈值可以业务方自己定。参数层面bagging.py 里子模型的数量、随机种子列表、每个子模型用多少比例的数据都可以调。子模型数量通常设在 5-11 个之间太多会显著拉长训练时间增益却会逐渐递减。5.2 用 features_imp 和 roc_curve 验证模型行为集成完成后有两件事必须做第一看特征重要性文件确认模型学到的规律和业务常识一致第二画 ROC 曲线确认模型在造假识别上的综合表现。# 绘制 ROC 曲线的核心代码 from sklearn.metrics import roc_curve, auc import matplotlib.pyplot as plt def plot_roc(y_true, y_score, save_pathroc_curve/manufacturing.png): fpr, tpr, _ roc_curve(y_true, y_score) roc_auc auc(fpr, tpr) plt.figure(figsize(6, 5)) plt.plot(fpr, tpr, labelfAUC {roc_auc:.4f}) plt.plot([0, 1], [0, 1], linestyle--, colorgray) plt.xlabel(False Positive Rate) plt.ylabel(True Positive Rate) plt.legend() plt.savefig(save_path, dpi150)ROC 曲线不要只看 AUC 数值重点看曲线的左上角——在低误报率区间模型的召回率是否陡峭上升。挑选阈值时可以在曲线上找到 Youden Index 最大的点TPR - FPR 最大但财务造假场景通常更保守建议阈值向低误报方向偏移宁可漏报也不要让大量正常公司被标记为造假否则风控团队会浪费大量人力去复核。至于特征重要性验证做法是读 features_imp 目录下每个行业的特征排序核对前几个特征是否符合财务审计常识。比如「应收账款周转率」「存货周转率」「经营现金流与净利润之比」这类指标出现在前列说明模型学到的是真实造假信号而不是噪声如果排在最前面的是「公司员工人数」「注册年份」这类无关变量说明特征筛选环节出了问题需要回头检查树模型的重要性计算是否被异常值干扰。我自己的习惯是跑完 Bagging 集成后强制做一遍特征重要性人工核对把 Top 10 特征列出来和财务人员过一遍。那一趟下来往往能发现一两处数据泄露——比如模型拿到了「是否被审计调整」这个事后变量得出的高 AUC 是假象去掉之后才是真实水平。希望这份拆解能帮你把整个资源跑通少走我当初翻车的弯路。本文还有配套的精品资源点击获取
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

把 Claude Code 接进 SoC 验证流水线:TaoToken 统一 Key 的 Agent 提效实践 2026/9/25 9:58:47

把 Claude Code 接进 SoC 验证流水线:TaoToken 统一 Key 的 Agent 提效实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
OpenClaw 可视化安装全流程演示:用 TaoToken 统一 Key 打通本地智能办公助手 2026/9/25 9:58:41

OpenClaw 可视化安装全流程演示:用 TaoToken 统一 Key 打通本地智能办公助手

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
中望CAD批量打印插件实战:从手动逐张出图到自动化PDF交付 2026/9/25 9:58:41

中望CAD批量打印插件实战:从手动逐张出图到自动化PDF交付

干我们这行的,天天跟中望CAD打交道,最烦的一件事就是把图纸转成PDF交出去。尤其是成套施工图,三五十张起步,大项目上百张也有,以前我都是开着一级“窗口”、二级“窗口”一个个框选图框,设置打印参数&#…

阅读更多 →
大语言模型智体的智体驾驭:综述(下)——TaoToken 统一 Key 接入 Agent 工具链的配置骨架 2026/9/25 9:58:40

大语言模型智体的智体驾驭:综述(下)——TaoToken 统一 Key 接入 Agent 工具链的配置骨架

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
告别命令行!在VSCode中直接使用Claude Code编程:TaoToken统一Key接入settings.json配置指南 2026/9/25 9:58:34

告别命令行!在VSCode中直接使用Claude Code编程:TaoToken统一Key接入settings.json配置指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
ChatGPT 5.6 发布传闻背后:用 TaoToken 统一 Key 打通 AGI 智能体配置链路 2026/9/25 9:58:34

ChatGPT 5.6 发布传闻背后:用 TaoToken 统一 Key 打通 AGI 智能体配置链路

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉