第 2 章用 Beneish 八变量 M-Score 在测试集上跑出 AUC = 0.5399,前 100 名零命中。那个模型把每个公司的 8 个比率打分后线性加权,权重是 Beneish 1999 论文用 1982–1992 年 74 家被 SEC 处罚公司样本拟合出来的常数。常数权重的好处是简洁,坏处也明显:换一份新数据,权重永远不会自动调整。要让权重根据样本"学"出来,就要把规则模型升级为统计模型。这一章引入会计学界用了三十年的工具:逻辑回归。配合 Dechow 等人 2011 年发表在 Contemporary Accounting Research 上的那篇 65 页长论文,我们要复刻 F-Score 的原始设计,看看它在 Bao 复制包上的判别力还剩多少。
逻辑回归在会计 ML 文献里有特殊地位。它既是 1980 年代以来银行违约预测、破产预测、舞弊检测的工作母机,也是 2010 年代以后被树模型与神经网络逐步取代的"经典基线"。把它放在第 3 章,是要让读者亲手感受一件事:在固定特征集和无正则的 MLE 设定下,逻辑回归能给出一个排序得分,比恒预测多数类的零模型好得多,但离机器学习时代的 AUC 上限还隔着相当一段距离。
从规则到概率
第 2 章 M-Score 的输出是一个连续的实数分数,没有概率含义;它落在哪个区间,全靠 Beneish 经验切的阈值 。逻辑回归不一样,它直接输出"这家公司在这一年被记为舞弊的概率"。要让模型输出概率,需要一个把任意实数压缩到 区间的函数,这个函数叫 sigmoid 函数,简称 logistic 函数。
举一个数字例子。假设我们用一个简化模型:只用 ch_roa,也就是资产回报率年度变化,作为唯一变量预测舞弊。某家公司的 ch_roa 是 ,模型估计的截距是 、斜率是 。把数字代进线性部分得到 。这个 没有概率含义,它叫 log-odds。把 log-odds 通过 sigmoid 变换:,得到这家公司被舞弊的预估概率 0.062%。
设 是二元结局, 是协变量向量,。逻辑回归假设
其中 是待估系数向量, 是截距。 称为 log-odds,它把 上的概率映射到全实数轴。
公式背后的会计直觉是:模型给每个特征一个权重,把所有特征按权重加起来得到 log-odds,再用 sigmoid 把 log-odds 翻译回概率。系数 的解释是"特征 每增加一个单位,log-odds 增加 ",等价于"舞弊优势比 odds ratio 乘以 "。这种"权重 + 加和 + 压缩"的结构和 M-Score 的"权重 + 加和"只差最后一步压缩,但因为权重是从数据里学出来的而不是查表查来的,模型可以适配新样本。
图 3·1 Dechow F-Score 逻辑回归的整体管道:七个会计比率分别度量应计质量、绩效压力与融资动机;权重 由 Bao 训练集 1991–2002 用 MLE 估出,线性组合得到 log-odds ;sigmoid 函数把 压回 得到预测舞弊概率 ;F-Score 等于 除以训练期无条件舞弊率 ,本数据 ,下节实证给出。完整 TikZ 结构图详见 PDF 全文。
逻辑回归用最大似然估计拟合,简称 MLE。给定训练样本 ,参数选择让对数似然函数取最大值。这个优化是凸的,没有局部最优解,迭代算法收敛快,是它能在 1980 年代低算力时代普及的根本原因。R 的 glm 默认用 IRLS 算法解 MLE,Python 的 sklearn 默认带 L2 正则,要逼近 R 的解需要把惩罚强度参数 设成一个极大值,并换用 newton-cg 解算器。这一节的代码会演示这件事。
Dechow F-Score 的设计
Dechow、Ge、Larson 和 Sloan 在 2011 年的论文里做了一件事:把当时已知的舞弊先行指标整理成一个更系统的特征集,用 1982–2005 年 SEC 发布的 AAER 标记的 676 家舞弊公司样本训练逻辑回归,得到一个被后来文献广泛引用的得分函数。这套特征集分三类:应计质量、绩效压力、融资动机。
应计质量类有三个变量。第一个是 RSST 应计的同比变化,对应 Bao 字段里的 ch_rsst。Richardson、Sloan、Soliman、Tuna 在 2005 年发现,把传统总应计扩展到包含非现金净营运资本、非流动经营资产和非流动经营负债三块后的"全口径"应计与未来盈余反转更相关。应计金额本身越大,公司在收入确认与费用资本化上动用的会计估计弹性越大,越容易给舞弊提供操作空间。第二个是应收账款的同比变化 dch_rec。应收账款相对于销售异常增长,是收入虚增的经典信号:卖了货但收不到钱,往往意味着收入是用客户授信硬撑出来的。第三个是存货的同比变化 dch_inv。存货相对于销售异常累积,是销货成本被压低的嫌疑信号;公司把本该结转的成本留在存货账户里,当期净利润就被人为推高。
绩效压力类有两个变量。soft_assets 衡量软性资产占总资产的比例,软性资产是除现金、PPE 之外的中间科目,比如应收、存货、商誉等。这些科目的账面价值依赖会计估计,估计弹性越大,操纵空间越大。ch_roa 是资产回报率的年度变化。Dechow 等人发现,舞弊公司在被处罚年度往往伴随 ROA 的同比下滑,反映"业绩压力催生造假动机":公司越是经营不下去,越有动机美化报表。这个方向让 ch_roa 的回归系数应当为负。
融资动机类有两个变量。ch_cs 是现金销售相对于销售总额的年度变化,反映收入结构里"硬通货"占比的变动;issue 是个 0/1 哑变量,标记公司当年是否新发权益或债务。当年要发新股发新债的公司,有强烈动机把当期报表做得好看,让市场愿意以较高价格接盘。
七个变量加起来是 Dechow 2011 论文 Table 7 Model 1 的预测器集合。原文的回归系数被用来构造 F-Score:把模型预测的舞弊概率除以样本无条件舞弊率,得到一个相对放大倍数。F-Score 大于 1 意味着这家公司的预测舞弊概率高于平均,大于 1.85 是 Dechow 给出的"高风险"经验阈值,大于 2.45 是"非常高风险"阈值。这套阈值在 Bao 数据上是否仍然合用,下一节用代码检验。
在 Bao 数据上的实现
我们先按 Bao 协议切训练 / 验证 / 测试三段,然后分别拟合 Model A 和 Model B。Model A 把 28 个原始 Compustat 变量与 14 个衍生比率全放进右边,共 42 个特征;Model B 只用 Dechow 七变量。两个模型都在切分前先做 NA 过滤,因为一行只要任一特征缺失,逻辑回归无法处理这一行。这是逻辑回归相对树模型的明显短板,第 5 章会讨论。
library(tidyverse)
library(pROC)
set.seed(2026)
d <- read_csv(here::here("data", "bao2020_full.csv"),
show_col_types = FALSE)
raw_vars <- c("act","ap","at","ceq","che","cogs","csho","dlc","dltis",
"dltt","dp","ib","invt","ivao","ivst","lct","lt","ni",
"ppegt","pstk","re","rect","sale","sstk","txp","txt",
"xint","prcc_f")
ratio_vars <- c("dch_wc","ch_rsst","dch_rec","dch_inv","soft_assets",
"ch_cs","ch_cm","ch_roa","issue","bm","dpi","reoa",
"EBIT","ch_fcf")
all_vars <- c(raw_vars, ratio_vars)
dechow_vars <- c("ch_rsst","dch_rec","dch_inv","soft_assets",
"ch_cs","ch_roa","issue")
# Model A:42 特征全集,先丢有 NA 的行,再切
d_full <- d %>% drop_na(all_of(all_vars))
trA <- d_full %>% filter(fyear >= 1991, fyear <= 2002)
teA <- d_full %>% filter(fyear >= 2009, fyear <= 2014)
mA <- glm(reformulate(all_vars, "misstate"),
data = trA, family = binomial)
predA <- predict(mA, newdata = teA, type = "response")
# Model B:Dechow 七变量
d_dech <- d %>% drop_na(all_of(dechow_vars))
trB <- d_dech %>% filter(fyear >= 1991, fyear <= 2002)
teB <- d_dech %>% filter(fyear >= 2009, fyear <= 2014)
mB <- glm(reformulate(dechow_vars, "misstate"),
data = trB, family = binomial)
predB <- predict(mB, newdata = teB, type = "response")
Model A 全集 42 特征至少有 19,562 行存在缺失,丢掉后剩下 126,483 行;按 Bao 协议切分得到训练 63,930 行含舞弊 537、验证 30,777 行含舞弊 250、测试 27,628 行含舞弊 107。Model B 七变量缺失少一些,丢 16,613 行,剩 129,432 行,测试 28,636 行舞弊数同样为 107。两边测试集的阳性数都是 107,比第 1 章原始 112 少 5 例,差异来自这 5 家公司在所选特征上有缺失。后面的 AUC 是基于这 107 个真阳性的可比较结果。
系数符号方向的会计直觉检查
Model B 七变量在 Bao 训练集上的拟合系数列在下表。每个系数的会计直觉方向都可以预先写下来,再去和 R 输出对照。
表 3·1 Dechow 七变量在 Bao 训练集 1991–2002 上的逻辑回归系数
| 变量 | 估计 | Std. Error | 预期方向 | ||
|---|---|---|---|---|---|
| (Intercept) | 0.270 | — | |||
| ch_rsst | 0.142 | + | |||
| dch_rec | 0.478 | + | |||
| dch_inv | 0.643 | + | |||
| soft_assets | 0.198 | + | |||
| ch_cs | 0.030 | + | |||
| ch_roa | 0.147 | ||||
| issue | 0.241 | + |
七个变量的符号方向全部与会计直觉一致。soft_assets 是数值上最强的预测器,系数 对应优势比 ;软性资产占比每提高一个百分点,舞弊优势比放大 8 倍。issue 与 ch_rsst 紧随其后,对应"当年发新股发新债"和"全口径应计大幅增长"两条经典舞弊路径。ch_roa 系数为负且显著,确认"业绩压力催生造假"的方向。两个边缘信号是 dch_inv,不显著,与 ch_cs,。dch_inv 的不显著有点意外,可能与 Bao 数据样本期与 Dechow 原文不重叠有关;2008 年以后零售与制造业存货管理普及 ERP,存货异常增长作为舞弊信号的判别力被自然削弱。
停下来想一想。 如果你要在审计场景里用 F-Score 做风险筛查,你会更信任系数的方向,还是它的具体数值?把训练样本期 1991–2002 和应用期 2009–2014 之间发生的所有制度变化、技术变化、行业结构变化都算进来,答案就清楚了:方向比数值更稳健。这也是为什么 Dechow 论文给 F-Score 设的两个阈值,1.85 对应高风险,2.45 对应非常高风险,一直被后续文献沿用,但具体的回归系数随每篇复刻论文样本变动而漂移。
性能评估与案例公司打分
Model A 与 Model B 在测试集 2009–2014 共 107 例舞弊上的四指标列在下表。
表 3·2 两种逻辑回归模型在测试集 2009–2014 上的性能
| 模型 | AUC | NDCG@100 | Recall@1% | Precision@1% |
|---|---|---|---|---|
| Model A 全 42 特征 | 0.6966 | 0.0510 | 0.0561 | 0.0217 |
| Model B Dechow 7 | 0.6752 | 0.0000 | 0.0093 | 0.0035 |
两个模型都明显跑赢第 1 章零模型基线 AUC = 0.500 和第 2 章 M-Score 的 AUC = 0.5399。Model A 加了 35 个原始与衍生变量后,AUC 提升 0.021 个点;前 1% 名额共 277 行里命中 6 个真舞弊,Recall@1% 达 5.61%。Model B 在 AUC 上只低 0.021,但 NDCG@100 = 0 暴露一个严重问题:前 100 名里没有任何一个真舞弊。换句话说,Dechow 七变量在 Bao 测试期上对最顶端的排序毫无判别力。这一点和原文报告的训练集表现差距很大,是后续章节 LASSO 与树模型必须解决的痛点。
两家标志性案例公司在 Model A 和 Model B 下的得分列在下表。Model B 的预测概率乘以无条件舞弊率倒数后就是 F-Score。
表 3·3 Enron 2000 与 Tyco 2000 在两种逻辑回归下的打分
| 案例 | 真实标签 | Model A | Model B | F-Score |
|---|---|---|---|---|
| Enron 2000 (gvkey=6127) | 1 | 0.9368 | 0.0180 | 2.17 |
| Tyco 2000 (gvkey=10787) | 1 | 0.1584 | 0.0135 | 1.63 |
Enron 2000 在 Model A 下被判定为高度可疑,预测概率 0.937,远超审计场景的任何合理阈值;Model B 给的预测概率虽然只有 1.8%,但 F-Score = 2.17 落在 Dechow 1.85 阈值之上,按原文标准属于"高风险"区间。两个模型对 Enron 都给出了"该查"的结论。Tyco 2000 的情况更复杂:Model A 只给 0.158,Model B 给 0.014,对应 F-Score = 1.63 低于 1.85 阈值。Tyco 是规模化连环并购公司,被处罚的舞弊主要是高管私人开支报销与并购溢价分摊扭曲,纯财务比率信号对这类舞弊的敏感度天然较低。这件事呼应第 1 章的 noisy positive 讨论:模型识别不出 Tyco,不一定是模型错,可能是 Tyco 的舞弊信号根本不在七个比率覆盖的维度里。
逻辑回归在极度不平衡数据上有一个退化倾向:MLE 优化目标是平均对数似然,而样本里 99.34% 的观测都是阴性,损失函数的主要项来自把阴性样本预测为阴性。模型最优解会把所有样本的预估概率压在无条件舞弊率附近,本数据约 0.66%–0.83%,即使最显著的特征对应的优势比已经达到 8 倍。结果是排序仍然有判别力,AUC 高于 0.5,但绝对预测概率被系统性低估,无法直接拿来做"是否调查"的二元决策。Python 里把 class_weight 设成 'balanced' 是常见的部分修正,但实测对 AUC 与 NDCG 几乎无影响,本章数据上 AUC 从 0.6752 变到 0.6747。真正解决这个问题要等第 7 章的 RUSBoost:欠采样多数类后再做提升,把训练分布人为推向平衡。
R 与 Python 在两个模型上的所有数字一致到小数点后 4 位。Python 的 sklearn 默认带 L2 正则,要逼近 R 的 MLE 解需要把惩罚强度参数 设成 并换用 newton-cg 解算器;如果继续用默认 lbfgs 解算器,42 特征的量纲差异会让 lbfgs 不收敛,最终给出一个明显劣于 R 的解。这里的量纲差异指原始 Compustat 字段从几个数量级到亿美元,衍生比率多在 区间。这是 Python 实现里最容易踩的坑。
本章累积对比表
表 3·4 第 3 章累积方法对比
| 方法 | AUC | NDCG@100 | Recall@1% | Precision@1% | 可解释性 | 局限 |
|---|---|---|---|---|---|---|
| 全部预测为非舞弊 | 0.500 | 0.000 | 0.000 | 0.000 | 完全可解释 | 无判别力 |
| Beneish M-Score, 第 2 章 | 0.5399 | 0.000 | 0.0110 | 0.0049 | 高,八变量加权 | 权重 1992 年固定,无学习能力 |
| 逻辑回归 Model A 全 42 特征 | 0.6966 | 0.0510 | 0.0561 | 0.0217 | 中,系数可读但变量多 | 对量纲敏感、共线性、需手工 NA 处理 |
| 逻辑回归 Model B Dechow 7 | 0.6752 | 0.0000 | 0.0093 | 0.0035 | 高,七变量会计直觉清晰 | 顶端排序失灵;样本期外漂移大 |
第 4 章把 Model A 的 42 特征加上 LASSO 与 Elastic Net 正则化,看看自动特征选择能不能在 AUC 不下降的前提下,把模型缩到一个 7 到 12 个变量、可解释性接近 Dechow 七变量、判别力接近 Model A 的紧凑版本。
本章知识地图
表 3·5 第 3 章核心概念与常见误解
| 核心概念 | 核心内容 | 常见误解 | 为什么错 |
|---|---|---|---|
| 逻辑回归 | 通过 sigmoid 把线性组合的 log-odds 映射回概率;用 MLE 拟合系数 | 逻辑回归是分类器,输出 0/1 标签 | 逻辑回归输出的是连续概率,二元化要靠用户选阈值;阈值选择本身是单独的决策 |
| log-odds | ,把 概率映射到全实数轴 | log-odds 增加 1 等于概率增加 1 | log-odds 与概率是非线性关系;同样增加 1 个单位的 log-odds,在 附近概率变化大,在 附近变化小 |
| 优势比 odds ratio | ,特征 增加一个单位对应优势比的乘数 | 优势比就是相对风险 | 优势比与相对风险只在 接近 0 时近似相等;舞弊问题里 ,两者数值确实接近,但概念上不同 |
| F-Score | Dechow 七变量逻辑回归预测概率除以无条件舞弊率得到的相对放大倍数 | F-Score 越高一定越可疑 | F-Score 阈值 1.85 / 2.45 是基于 Dechow 原文 1982–2005 样本得到的,迁移到新样本期阈值需要重校准 |
| 最大似然估计 MLE | 选择参数让训练样本的对数似然最大化;逻辑回归的 MLE 是凸优化 | R 的 glm 与 Python 的 sklearn 给出相同的解 | Python 默认带 L2 正则;要逼近 R 的无正则 MLE,需要 设为极大值并换 newton-cg 解算器 |
| 极度不平衡退化 | 舞弊率 时,逻辑回归的预测概率被系统性压低到无条件舞弊率附近 | 设 class_weight='balanced' 就能解决 | 重加权能改变绝对概率水平,但对排序型指标 AUC、NDCG 几乎无影响;真正的解需要 RUSBoost 这类欠采样 + boosting 方法 |
| Model A vs Model B | 特征集越大测试集 AUC 越高,但顶端排序的变化更复杂 | 特征多一定更好 | Model A 多用 35 个变量,AUC 只提升 0.021;过拟合风险与解释性损失需要正则化或变量选择来平衡 |
| 样本期漂移 | Dechow 1982–2005 训练,Bao 2009–2014 测试,七变量符号方向稳定但数值漂移 | 原文报告的高风险阈值可以原封不动用 | 审计制度变化、行业结构变化、ERP 普及让某些变量的判别力随时间衰减;阈值需要在新样本上重校 |