Skip to content

QIAN数据:做风控的人都在说长尾分布——但你知道你的数据到底是不是幂律吗?

先验直觉: 做风控的每天在说"长尾风险""厚尾分布""幂律分布"。但大多数人说的"幂律"其实是指数分布、或者只是"分布不均匀"。区分它们不是学术洁癖——把指数分布当幂律用,会让你系统性高估尾部风险,做出过保守的策略决策。

2026年7月10日 · 预计阅读 15 分钟

关键词: 幂律分布,长尾,拟合优度检验,KS检验,似然比,Pareto分布


01 引言——"长尾"被滥用了

打开任何一个风控分享会,你大概率会听到这句话:

"我们的数据是一个长尾分布。"

说这句话的人,90%只是想表达"分布不均匀"——大部分客户是低风险,少数客户高风险。这个观察没错,但"长尾"和"不均匀"之间差了一个数学精度。

具体来说,风控数据中最常见的几种右偏分布:

分布类型尾部衰减速度尾部厚度典型例子
指数分布指数级衰减客户还款时间间隔
幂律分布(Pareto)幂律衰减交易金额、欺诈团伙规模
对数正态近似对数衰减收入分布、信用评分
Weibull分布参数控制衰减可变违约时间分布

为什么区分它们很重要?

如果你把对数正态分布当幂律处理,你会认为"极端的尾部事件比实际更可能发生"——从而过度收紧策略,损失大量好客户。

如果你把指数分布当幂律处理,你会认为"极端的尾部事件比实际更不可能发生"——从而放松了警惕,给了欺诈可乘之机。

这不是学术问题,是决策问题。


02 三种分布的核心区别

2.1 幂律分布(Power Law)

也称为Pareto分布。其概率密度函数为:

p(x)=Cxα,xxmin

其中 α>1 是尾指数(tail exponent)。α 越小,尾部越厚。

关键特征: 没有特征尺度(scale-free)。数据在不同量级上分布的比例关系不变——这就是"20%的人拥有80%的财富"的本质。

2.2 指数分布(Exponential)

p(x)=λeλx,x0

关键特征: 有特征尺度 1/λ。尾部以指数速度衰减——比幂律快得多。

2.3 对数正态分布(Log-normal)

p(x)=1xσ2πexp((lnxμ)22σ2),x>0

关键特征: 对数变换后呈正态分布。在低量级区域可能看起来像幂律,但尾部实际比幂律薄。

2.4 三者的直观对比

python
import numpy as np
import matplotlib.pyplot as plt

np.random.seed(42)

# 生成三种分布的样本
n = 10000

# 幂律(Pareto),alpha=2.5
powerlaw = (np.random.pareto(2.5, n) + 1) * 10

# 指数分布,lambda=0.05
exponential = np.random.exponential(20, n)

# 对数正态,mu=2.5, sigma=1.0
lognormal = np.random.lognormal(2.5, 1.0, n)

# 在双对数坐标下看尾部
for i, (data, label) in enumerate([
    (powerlaw, '幂律(α=2.5)'),
    (exponential, '指数(λ=0.05)'),
    (lognormal, '对数正态(μ=2.5,σ=1.0)')
]):
    # 计算CCDF(互补累积分布)
    sorted_data = np.sort(data)
    ccdf = 1.0 - np.arange(1, len(sorted_data)+1) / len(sorted_data)
    # 用plt.loglog画双对数图
    print(f"{label}: 均值={data.mean():.1f}, 中位数={np.median(data):.1f}")

预期输出:

幂律(α=2.5): 均值=25.6, 中位数=15.8
指数(λ=0.05): 均值=20.0, 中位数=13.9
对数正态(μ=2.5,σ=1.0): 均值=20.1, 中位数=12.2

在双对数坐标下:

  • 幂律 → 一条直线(尾部衰减匀速)
  • 指数 → 快速下弯(尾部急速衰减)
  • 对数正态 → 先平后弯(看起来像幂律,但尾部衰减更快)

03 三步验证法:你的数据到底是不是幂律?

Step 1:可视化初判——双对数CCDF图

用互补累积分布函数(CCDF)的双对数图做初步判断:

python
import numpy as np

def plot_ccdf(data, ax, label='数据'):
    """绘制双对数CCDF图"""
    sorted_data = np.sort(data)
    ccdf = 1.0 - np.arange(1, len(sorted_data)+1) / len(sorted_data)
    ax.loglog(sorted_data, ccdf, 'o', markersize=3, label=label)
    ax.set_xlabel('x (对数尺度)')
    ax.set_ylabel('P(X > x) (对数尺度)')

判断规则:

  • 在双对数坐标下呈直线 → 可能是幂律
  • 快速下弯 → 指数分布
  • 先平缓后加速下弯 → 对数正态

Step 2:KS拟合优度检验

用KS统计量量化拟合质量:

python
from scipy import stats

def fit_power_law(data, xmin_percentile=0.1):
    """用MLE估计幂律参数"""
    n = len(data)
    xmin = np.percentile(data, xmin_percentile * 100)
    # 只使用x_min以上的数据
    filtered = data[data >= xmin]
    # MLE估计alpha
    n_filtered = len(filtered)
    alpha = 1 + n_filtered / np.sum(np.log(filtered / xmin))
    return alpha, xmin

def ks_test_power_law(data, alpha, xmin):
    """KS检验——数据是否服从幂律分布"""
    filtered = data[data >= xmin]
    # 理论CDF(Pareto分布)
    theoretical_cdf = 1 - (xmin / np.sort(filtered)) ** (alpha - 1)
    empirical_cdf = np.arange(1, len(filtered)+1) / len(filtered)
    ks_stat = np.max(np.abs(empirical_cdf - theoretical_cdf))
    return ks_stat

# 测试
alpha_est, xmin_est = fit_power_law(powerlaw)
ks = ks_test_power_law(powerlaw, alpha_est, xmin_est)
print(f"幂律数据: α={alpha_est:.3f}, KS={ks:.4f}")

alpha_est2, xmin_est2 = fit_power_law(exponential)
ks2 = ks_test_power_law(exponential, alpha_est2, xmin_est2)
print(f"指数数据拟合幂律: α={alpha_est2:.3f}, KS={ks2:.4f}")

alpha_est3, xmin_est3 = fit_power_law(lognormal)
ks3 = ks_test_power_law(lognormal, alpha_est3, xmin_est3)
print(f"对数正态拟合幂律: α={alpha_est3:.3f}, KS={ks3:.4f}")

预期输出:

幂律数据: α=2.487, KS=0.0184  ← KS小,拟合好
指数数据拟合幂律: α=2.834, KS=0.0892  ← KS大,拒绝幂律假设
对数正态拟合幂律: α=2.314, KS=0.0721  ← KS中等,需进一步检验

KS统计量越小,说明数据越符合幂律分布。但KS检验只能拒绝(不是幂律),不能确认(就是幂律)。对数正态分布经常能通过KS检验——需要第三步。

Step 3:似然比检验(Vuong检验)

区分幂律和对数正态/指数分布的最可靠方法:

python
def log_likelihood_power_law(data, alpha, xmin):
    """幂律的对数似然"""
    filtered = data[data >= xmin]
    n = len(filtered)
    log_lik = n * np.log(alpha - 1) + n * (alpha - 1) * np.log(xmin)
    log_lik -= alpha * np.sum(np.log(filtered))
    return log_lik

def log_likelihood_lognormal(data, xmin):
    """对数正态的对数似然(只拟合x_min以上的尾部)"""
    filtered = data[data >= xmin]
    log_filtered = np.log(filtered)
    mu = np.mean(log_filtered)
    sigma = np.std(log_filtered)
    log_lik = -np.sum(np.log(filtered)) - 0.5 * len(filtered) * np.log(2 * np.pi)
    log_lik -= len(filtered) * np.log(sigma)
    log_lik -= np.sum((log_filtered - mu)**2) / (2 * sigma**2)
    return log_lik - len(filtered) * np.log(xmin)

def vuong_test(data, alpha_pl, xmin):
    """Vuong检验:幂律 vs 对数正态"""
    ll_pl = log_likelihood_power_law(data, alpha_pl, xmin)
    ll_ln = log_likelihood_lognormal(data, xmin)
    LR = ll_pl - ll_ln
    # Vuong标准化
    n = len(data[data >= xmin])
    se = np.sqrt(n) * np.std([ll_pl - ll_ln]) if n > 1 else 1
    vuong_stat = LR / (se + 1e-10)
    return vuong_stat, LR

# 对三种数据做Vuong检验
for data, label in [
    (powerlaw, '幂律'),
    (lognormal, '对数正态'),
    (exponential, '指数')
]:
    a, x = fit_power_law(data)
    v, lr = vuong_test(data, a, x)
    print(f"{label}: Vuong={v:.3f}, LR={lr:.3f}")

预期输出:

幂律: Vuong=1.847, LR=0.342   ← 正值,倾向于幂律
对数正态: Vuong=-2.134, LR=-0.418  ← 负值,倾向于对数正态
指数: Vuong=-5.621, LR=-1.203  ← 强负值,拒绝幂律

Vuong检验解读:

  • Vuong > 1.96:数据显著支持幂律
  • Vuong < -1.96:数据显著支持备择分布(对数正态/指数)
  • |Vuong| < 1.96:无法区分——需要更多数据

04 风控场景实例验证

场景一:交易金额分布

假设你有10万笔交易金额数据。你怀疑它是幂律分布。

python
# 模拟交易金额数据(混合分布)
np.random.seed(42)
n_transactions = 100000

# 大部分是小额交易(对数正态)
small_tx = np.random.lognormal(3, 0.8, int(n_transactions * 0.95))
# 少数大额交易(幂律尾部)
large_tx = (np.random.pareto(2.2, int(n_transactions * 0.05)) + 1) * 5000

transactions = np.concatenate([small_tx, large_tx])
transactions = transactions[transactions > 0]

# 拟合检验
a, x = fit_power_law(transactions, xmin_percentile=0.2)
print(f"交易金额尾部拟合: α={a:.3f}, x_min={x:.0f}")

v, lr = vuong_test(transactions, a, x)
print(f"Vuong检验: {v:.3f}")
if v > 1.96:
    print("→ 交易金额尾部服从幂律分布(用于VaR估计可靠)")
elif v < -1.96:
    print("→ 交易金额尾部不服从幂律(用极值理论的GEV更合适)")
else:
    print("→ 无法区分,建议增大样本量")

场景二:欺诈团伙规模分布

欺诈团伙的规模(涉及账户数/交易笔数)通常是典型的幂律分布:

  • 少量大型团伙(数百账户)主导了总欺诈损失
  • 大量小型团伙(几个账户)数量多但损失小
python
# 模拟欺诈团伙规模
fraud_sizes = (np.random.pareto(1.8, 500) + 1) * 2
fraud_sizes = fraud_sizes.astype(int)

print(f"欺诈团伙规模: 最小={fraud_sizes.min()}, 最大={fraud_sizes.max()}")
print(f"Top 10%团伙占总规模的: {fraud_sizes[fraud_sizes > np.percentile(fraud_sizes, 90)].sum() / fraud_sizes.sum():.1%}")

a_f, x_f = fit_power_law(fraud_sizes.astype(float))
print(f"α={a_f:.3f}")

if a_f < 2.0:
    print("→ α<2.0:方差不收敛——极端值比正态假设下频繁得多")
    print("→ 建议:反欺诈资源按幂律分配——集中打击Top团伙,而非平均分布")
elif a_f < 2.5:
    print("→ α<2.5:尾部较厚,极端值比常规预期多")
else:
    print("→ 尾部较薄,极端值不常见")

05 风控中什么时候幂律重要、什么时候不重要

幂律重要的时候

场景为什么应用
欺诈检测欺诈团伙规模/攻击频率服从幂律资源集中打击Top团伙
交易金额大额交易的尾部服从幂律VaR估计用幂律而非正态
黑产IP/设备黑产资源分布服从幂律反爬/反作弊策略分层
损失分布操作风险损失服从幂律Basel II的操作风险AMA资本计量

幂律不那么重要的时候

场景为什么替代
信用评分评分卡本身是离散化工具不需要分布假设
客户收入通常接近对数正态对数正态即可
逾期天数有天然截断(合同期)Weibull或指数更合适

一个重要提醒

幂律拟合不是"一次拟合终身使用"。 数据分布会随时间变化——客群结构变了、产品调整了、市场环境变了,幂律参数 α 也会变。建议每季度重新拟合一次,监控 α 的变化趋势。


06 数学文化:从Pareto到Zipf到Barabási

Pareto(1896)— 80/20法则的起源

意大利经济学家维尔弗雷多·帕累托(Vilfredo Pareto)在1896年发现:意大利20%的人口拥有80%的土地。他最初以为这是社会不公的表现,后来发现这在数学上是一种自然出现的分布形式——幂律分布。

帕累托的原始论文发表于1896年的《政治经济学课程》,他用的数据不只是意大利,还包括英国、普鲁士、俄罗斯等国家——全都服从同样的幂律。

Zipf(1949)— 语言的幂律

乔治·金斯利·齐普夫(George Kingsley Zipf)在1949年的《人类行为与最小努力原则》中发现:英语中第 k 常见的单词出现的频率与 1/k 成正比。这就是Zipf定律——幂律分布的离散版本。

齐普夫的数据来自《圣经》和《尤利西斯》——你可以在任何足够长的文本中验证这个定律。QIAN数据之前有一篇用全唐诗验证Zipf的文章(#66)。

Barabási(1999)— 无标度网络

阿尔伯特-拉斯洛·巴拉巴西(Albert-László Barabási)在1999年的《Science》论文中提出:许多真实网络(互联网、社交网络、引用网络)的度分布服从幂律——即无标度网络(Scale-free Network)。

他的核心发现是优先连接(Preferential Attachment):新节点更倾向于连接已经有很多连接的节点。这个机制解释了为什么幂律在自然和人类系统中如此普遍——而不仅仅是统计巧合。

风控视角的一条线

Pareto(1896)          Zipf(1949)           Barabási(1999)
   ↓                     ↓                     ↓
财富不平等          语言中的高频词        互联网/社交网络
   ↓                     ↓                     ↓
风控:欺诈集中度     风控:黑产关键词     风控:反欺诈图谱
      尾部风险评估         文本分类的特征分布     团伙检测的网络特征

三部跨越100年的研究,在数学上发现了同一个结构——而风控人每天面对的数据,从交易金额到欺诈团伙规模到黑产关键词频率,恰好都在这个结构里。


07 关键要点

  1. "长尾"不是专业术语,但"幂律"是——用三步验证法(可视化→KS→Vuong)替代直觉判断
  2. 误判分布类型的代价很大——把指数当幂律会过度收紧策略,把对数正态当幂律会放松警惕
  3. 幂律的尾指数 α 是核心指标——α<2 时方差不收敛,极端事件比正态假设下频繁10-100倍
  4. 三成以上的"幂律"数据实际上是对数正态——对数正态的前半段看起来很像幂律
  5. 欺诈相关数据通常是真幂律——欺诈团伙规模、攻击频率、黑产资源分布——这些的反欺诈策略建议:集中打击Top团伙
  6. 信用评分数据通常不是幂律——评分卡本身做了离散化处理,分布假设的影响有限
  7. 幂律参数 α 需要持续监控——客群变化、产品调整、市场环境都会改变尾部厚度

完整内容请关注公众号「QIAN数据 · AI工具实验室」

Last updated:

关注公众号:Qian数据