财务舞弊检测实践 · 第 1

问题与数据:AAER 与上市公司舞弊检测

2001 年 12 月,安然公司在递交破产保护前,账面上还显示着 655 亿美元的总资产和 9.79 亿美元的净利润。两年之后,SEC 在第 1821 号会计与审计执法公告里认定,安然 1998 至 2000 年三个会计年度的财务报表存在系统性重大错报,公告编号简称 AAER 1821。这份公告记下的并不是个例。整个 1990 年代到 2000 年代初期,SEC 平均每年发出 30 到 60 份 AAER,标记一批批被认定财务报表造假的上市公司。在这些公告被发出之前,市场上没有人在普通财务数据里看出可疑的迹象,包括那些公司聘请的外部审计师在内。

能不能从 10-K 报表的财务数字本身识别出做假账的公司,是会计学界从 1990 年代开始反复回到的问题。Beneish 在 1999 年提出 M-Score,用八个加权变量给每家公司打分。Dechow、Ge、Larson 和 Sloan 在 2011 年用更系统的变量集训练逻辑回归,得到 F-Score。十年之后,Bao、Ke、Li、Yu 和 Zhang 在 2020 年的 Journal of Accounting Research 上发表了一项研究,把 Random UnderSampling Boosting 这种机器学习方法应用到同样的 AAER 标签上,在 NDCG@k 指标上把传统统计模型甩开了一截。这是会计 ML 文献迄今最有影响力的旗舰论文之一。

这本书只回答一个问题:给定一家美国上市公司一个会计年度的财务数据,能不能在 SEC 处罚之前把它识别为高舞弊嫌疑? 每一章用一种不同的检测方法回答它,最后汇总比较。同一份数据、同一个问题、十种刀法,读者可以亲手看到每种方法的假设、操作和结论有什么差别。

舞弊检测无法用 RCT 的原因

回答因果问题最直接的办法是随机对照试验,简称 RCT。但 RCT 在舞弊问题上不可行。研究者不能随机分配公司 "做假账" 或 "不做假账",伦理和法律都不允许;舞弊本身是隐蔽行为,公司不会自愿参加这样的实验。SEC 的 AAER 制度提供了一个观察性的替代品:当 SEC 经过调查后认定一家公司的某一会计年度财务报表存在重大错报,它会发布一份执法公告,给这家公司的那一年打上一个事后的二元标签。

这种事后标注的标签有两个性质需要在第一章就讲清楚。第一个是标签时滞。SEC 调查从启动到结案平均耗时三到五年,意味着 2014 年的舞弊行为可能要到 2018 年甚至更晚才被记入 AAER 数据库。第二个是选择性遗漏。SEC 的执法资源有限,不可能查每一家公司的每一个年度。被标记为舞弊的公司一定做了假账,但没被标记的公司不一定干净。这两条性质决定了我们手上的标签是 "阳性可信、阴性不可信" 的 noisy positive samples。后续每一章在评估模型表现时都需要把这一点放在心里。

数据概览

本书使用的数据来自 Bao 等人 2020 年公开的复制包,仓库地址 github.com/JarFraud/FraudDetection。数据已经做了两件关键的脏活:从 SEC 的 AAER 公告里抽出舞弊年份,与 Compustat 财务数据按 fyear 对齐。读者拿到手的是一个 firm-year 级别的扁平表,每行代表一家上市公司在某一会计年度的财务画像加二元标签。

library(tidyverse)
set.seed(2026)

d <- read_csv(here::here("data", "bao2020_full.csv"),
              show_col_types = FALSE)

dim(d)               # 146045 行 x 46 列
n_distinct(d$gvkey)  # 18444 家公司
range(d$fyear)       # 1990 - 2014
table(d$misstate)    # 0: 145081, 1: 964
mean(d$misstate)     # 0.006601
结果解读数据规模

全样本 146,045 个 firm-year 观测,覆盖 18,444 家上市公司,时间跨度 1990 到 2014 年。其中标记为舞弊的样本 964 个,全样本舞弊率 0.66%。这是一个典型的极端不平衡分类问题,正样本比例不到 1%。后面会讲为什么这件事会改变所有传统机器学习方法的默认行为。

字段

数据包含 46 列,分四组。3 列标识列:fyear 是会计年度,gvkey 是 Compustat 分配的公司唯一识别号,p_aaer 是 SEC 公告编号且仅在标签为 1 的行非空。1 列标签:misstate,0 表示非舞弊,1 表示舞弊。其余 42 列是财务变量,再分两组。

第一组是 28 个原始 Compustat 报表项目。这是 Bao 论文 Table 1 里列出的变量集,覆盖了资产负债表的主要科目,比如 at 总资产、ceq 普通股权益、lt 总负债;利润表的核心项目,比如 sale 销售收入、ni 净利润、cogs 营业成本;现金流相关的项目,比如 che 现金及等价物、dltis 长期债务发行额。机器学习方法直接吃这 28 个原始数。

第二组是 14 个衍生比率,是从原始项目里算出来的 "会计学家手工特征",比如 ch_roa 是资产回报率的年度变化,soft_assets 是软性资产占总资产的比重,dch_rec 是应收账款变化与销售变化的差额。Beneish 与 Dechow 时代的统计模型主要靠这一组比率,机器学习时代它们更多被当作辅助特征。

时间切分

Bao 论文的时间切分协议把 1991 年起的数据分成三段:训练集 1991–2002,验证集 2003–2008,测试集 2009–2014。这种按年份切分而不是随机切分的做法保证了模型在做出预测时永远没有看过未来。下表列出三段的样本量与舞弊数。

表 1·1 Bao 论文时间切分协议

切分firm-year舞弊数舞弊率
训练 1991–200273,2335760.787%
验证 2003–200835,1662610.742%
测试 2009–201433,0641120.339%

测试期的舞弊率几乎是训练期的一半。这个落差来自 SEC 的执法对最近年份的样本仍在累积,不是抽样误差造成。换句话说,标签会随着时间越来越完整:1995 年的舞弊到 2026 年已经基本全部进入数据库,2014 年的舞弊可能还有相当一部分没被发现。第十章会回到这个问题,讨论它如何引发 "时间外推塌陷"。

极度不平衡分类的根本困难

停下来想一想。 如果你建一个模型,把 33,064 个测试期 firm-year 全部预测为非舞弊,准确率会是多少?翻到下一段之前,先估一下。

测试期舞弊率 0.339%,所以 "全部预测为非舞弊" 的零模型在测试集上的准确率是 99.661%。这个数字看起来无懈可击,可它没有任何识别舞弊的能力。这就是不平衡分类问题的核心矛盾:传统的准确率指标对极端不平衡完全没有判别力。要评估一个真正的舞弊检测模型,必须换一套指标。本书后续每章统一报告四个指标:AUC、NDCG@kk、Recall@1%、Precision@1%。

定义AUC
def:auc

S(x)S(x) 是模型对样本 xx 输出的舞弊得分,P+P_+ 是阳性样本集合,PP_- 是阴性样本集合。AUC 定义为

AUC=Pr(S(X+)>S(X)),\mathrm{AUC} = \Pr\bigl(S(X_+) > S(X_-)\bigr),

即任取一个真实阳性 X+X_+ 和一个真实阴性 XX_-,模型把阳性排在阴性前面的概率。

举一个数字例子。假设模型对 5 家舞弊公司输出的舞弊得分依次是 0.91、0.78、0.62、0.55、0.40,对 5 家非舞弊公司输出的得分是 0.85、0.50、0.45、0.30、0.20。把它们两两配对一共 25 对,"舞弊得分高于非舞弊" 的对数是 21。AUC 等于 21/25 = 0.84。这个指标的好处是它和阈值无关,只看相对排序。零模型给所有样本相同得分,任意配对的概率都是 50%,AUC = 0.500。一个有意义的舞弊检测模型至少要把 AUC 推到 0.65 以上;Bao 论文最终模型的 AUC 在测试期约 0.72。

定义NDCG@k 与 Recall@1%
def:ndcg-recall

把模型在测试集上的预测得分从高到低排序。Recall@1% 是排在前 1% 位置的样本中真实阳性的占比相对于总阳性数的比例。NDCG@kk 是把前 kk 个位置赋以折损权重 1/log2(i+1)1/\log_2(i+1) 后的加权阳性命中之和,再除以理想排序下能达到的最大值。

通俗讲,Recall@1% 回答 "如果我只敢查可疑度排名前 1% 的公司,能挖出多少真舞弊"。在测试集上 1% 对应 331 家公司,假设其中真阳性有 50 家,那 Recall@1% = 50/112 = 44.6%。NDCG@kk 对排名靠前位置赋予更高权重,评价 "模型把真舞弊推得有多前"。这两个指标都是为审计场景量身定制的:监管者和审计师真正在意的,是有限调查资源下能精准命中多少;整张表的准确率反而是次要的。

回到 AAER 数据。 对零模型而言,所有测试样本得分相同,排名是任意打散的。Recall@1% 期望值等于随机命中率 1%,Precision@1% 期望值等于基线舞弊率 0.339%,AUC = 0.500。这就是后续累积对比表的第一行基线,所有真正 "学过东西" 的方法都必须明显跑赢这一行才有资格被讨论。

雷区准确率在不平衡分类下失效

在极端不平衡分类问题中,准确率与误差率两个指标对零模型友好,对有判别力的模型不友好,因此不能作为评估的主指标。一个把所有样本预测为非舞弊的零模型在测试集上准确率 99.661%,但 Recall = 0、Precision 未定义、AUC = 0.500。任何一篇宣称 "准确率 99% 以上" 的舞弊检测论文,如果没有报告 AUC、Recall@kk 或 Precision@kk,结论原则上不可信。

标志性案例公司

为了让累积对比表 "行行可比",从全样本里挑出两家有代表性的舞弊公司,让每章的模型都给它们打分。下表列出选中的两家。

表 1·2 标志性案例公司

案例gvkey舞弊 fyear, 标签 = 1AAER
Enron Corp.61271998, 1999, 20001821
Tyco International107871998, 1999, 2000, 20021839

Enron 在数据中保留了 10 个年度 1990–1996 与 1998–2000,其中 1997 年缺失。下表列出几个关键年度的总资产、销售与净利润。

表 1·3 Enron Corp. 关键年度切片,单位百万美元

fyearat 总资产sale 销售ni 净利润misstate
199616,13713,2895840
199829,35031,2607031
199933,38140,1128931
200065,503100,7899791

总资产从 1996 到 2000 翻了 4 倍,销售翻了 7.5 倍,同期净利润只从 5.84 亿增长到 9.79 亿,看起来增长远不及资产端。表面温和、暗里激进的资产负债表扩张,是后续机器学习方法尝试捕捉的核心信号之一。后面每一章都会回到这两家公司,看不同方法给它们的舞弊概率打多少分、能不能在 SEC 公告之前就把它们排到队列前面。

全书路线图

本书用十种方法回答同一个问题。第 2 章实现 Beneish (1999) 的 M-Score 作为零智能基线。第 3 章把规则升级为带学习的逻辑回归并复刻 Dechow et al. (2011) F-Score。第 4 章引入 LASSO 和 Elastic Net 应对高维变量过拟合。第 5 章跨入非参数世界,从决策树过渡到随机森林。第 6 章引入 XGBoost,体会 Boosting 与 Bagging 的差异。第 7 章是参考论文复刻章,用 RUSBoost 重现 Bao (2020 JAR) 的主结果,讨论它为什么成为会计 ML 的分水岭。第 8 章进入表格深度学习与无监督异常检测。第 9 章把建模数据从财务报表扩展到 MD&A 文本与 Loughran-McDonald 词典。第 10 章用 SHAP 把表现最佳模型的预测打开,整合前九章的累积对比表给出方法选择决策树。

每章末尾会更新一张累积对比表,列出已经登场的所有方法在测试集上的 AUC、NDCG@100、Recall@1%、Precision@1%、训练时间、可解释性、核心假设与局限。下表是这张表的第一行,从零模型开始。

本章累积对比表

表 1·4 第 1 章累积方法对比:零模型基线

方法AUCNDCG@100Recall@1%Precision@1%可解释性局限
全部预测为非舞弊0.500000完全可解释无判别力

这张表目前只有一行。后续每章增加一行,到第 10 章合并为终极版本。

本章知识地图

表 1·5 第 1 章核心概念与常见误解

核心概念核心内容常见误解为什么错
AAERSEC 发布的会计与审计执法公告,对一家上市公司的某一会计年度财务报表认定存在重大错报AAER 等于"该公司一定有罪"AAER 是 SEC 的认定结论,公司可能上诉或和解;阴性样本中也可能藏有未被查处的舞弊
标签噪声方向阳性可信、阴性不可信没有 AAER 的公司就是干净的SEC 执法资源有限,存在选择性遗漏;模型评估时必须意识到阴性是 noisy negative
时间切分按 fyear 分训练 / 验证 / 测试,避免穿越未来随机切分也行,反正样本量够随机切分会让模型在训练时看到未来年份的舞弊样本,严重高估泛化能力
极端不平衡正样本比例 0.66%,零模型准确率即可达到 99.66%报告 "准确率 99%" 就说明模型很好零模型的准确率几乎与最优模型一致;准确率对极端不平衡完全失去判别力
AUC任取一对阳性 / 阴性样本,阳性排在阴性前面的概率;零模型 AUC = 0.500AUC 0.85 的模型一定比 AUC 0.80 的模型实用AUC 衡量整体排序,不反映 "前 1% 排序" 的精准度;审计场景要看 NDCG@kk 和 Recall@kk
NDCG@kk对排名前 kk 的样本按位置折损加权后的阳性命中之和,归一化到 [0,1][0, 1]kk 越大越好kk 取决于审计资源;监管 / 审计场景常取 k=100k = 100 或对应 1% 总体规模
Recall@1%排名前 1% 中真阳性占总阳性数的比例Recall 高就万事大吉Recall 高但 Precision 低意味着虚警泛滥;要联合 Precision@1% 一起看
Bao 时间切分训练 1991–2002 / 验证 2003–2008 / 测试 2009–2014测试期舞弊率低意味着模型表现差是模型问题测试期舞弊标签仍在累积,部分舞弊尚未进入数据库;表现下降部分来自标签缺失