合成数据与基准 (Synthetic Data and Benchmarks for Causal Discovery)
定位: 合成数据和基准测试是因果发现算法评测的基础。本笔记涵盖常用的合成数据生成器、基准测试协议以及关键参数设置,是系统评测因果发现算法的必备知识。
前置知识: 因果图结构(DAG)、因果发现算法(SHD/SID)、统计检验基础
核心直觉
核心直觉: 因果发现算法的评测需要已知真实因果结构的ground truth数据。由于真实数据往往缺乏ground truth,合成数据生成成为评测的核心手段。设计良好的合成数据应能够:(1)控制真实因果结构;(2)模拟不同类型的数据分布;(3)覆盖典型挑战场景。
合成数据设计的核心挑战是平衡”可控性”与”真实性”。过于人为的数据可能无法反映实际问题的复杂性,而过于复杂的结构又难以准确评估算法的局限性。
数学推导
1. 线性高斯SCM数据生成
结构方程模型(SEM):
数据生成过程:
- 确定DAG
和边系数 - 拓扑排序节点
- 按顺序生成每个节点:
- 计算父节点线性组合:
- 生成噪声:
- 样本:
- 计算父节点线性组合:
示例: 对于DAG
2. 非线性SCM数据生成
非线性函数形式:
常用函数:
- 多项式:
- sigmoid:
- 神经网络:
非线性数据特点:
- 打破线性因果假设
- 检验算法对函数形式的鲁棒性
- 通常更难发现因果关系
3. 离散数据生成
条件概率表(CPT):
数据生成:
- 指定父节点配置的概率
- 根据父节点值查表生成子节点值
常用分布:
- 类别均匀分布
- 条件概率结构(如”与”门、“或”门)
4. 图结构生成模型
随机DAG生成:
- 初始化空的邻接矩阵
- 按拓扑顺序,对每对
( ): - 以概率
添加边 - 确保无环(通过检查拓扑顺序)
- 以概率
- 边系数:
ER随机图:
- 控制边密度
Scale-free图:
- 优先连接机制
- 更符合真实网络特性
5. 常见挑战场景
场景1: 隐藏 confounders
场景2: 选择偏差
某些节点的值依赖于其他节点,导致样本偏差。
场景3: 非平稳性
数据生成过程随时间变化。
基准测试工具
1. Tetrad
Carnegie Mellon大学的因果发现工具:
功能:
- 多种DAG生成模型
- 线性/非线性SCM
- 高斯/非高斯噪声
- 时序数据生成
使用:
// Tetrad Java API示例
IndTestFisherZ test = new IndTestFisherZ(data, alpha);
Pc pc = new Pc(test);
graph = pc.search();2. bnlearn
R语言因果发现库:
功能:
- DAG生成器(集中、分散、混合)
- 参数生成(随机CPT、均匀)
- 数据模拟(Gibbs采样、逻辑采样)
使用:
library(bnlearn)
# 生成随机DAG
dag <- random.graph(nodes = c("X1", "X2", "X3"), method = "melancon")
arcs(dag) <- matrix(c("X1", "X2", "X2", "X3"), ncol = 2, byrow = TRUE)
# 生成数据
data <- rbn(bn.fit(dag, network = "gaussian"), n = 1000)3. causal-learn
Python因果发现库:
from causal_learn.data.DataGenerator import DataGenerator
# 生成线性高斯数据
dg = DataGenerator(num_nodes=10, num_edges=15, n_samples=1000,
data_type='linear_gaussian')
data, true_dag = dg.generate_data()评测协议
1. 数据生成参数
| 参数 | 典型值 | 说明 |
|---|---|---|
| 10, 20, 50, 100 | 评估scalability | |
| 100, 500, 1000, 5000 | 评估样本复杂度 | |
| 边密度 | 0.05, 0.1, 0.2, 0.3 | 控制图复杂度 |
| 边系数范围 | 控制效应大小 | |
| 噪声方差 | 控制信噪比 |
2. 评测指标
对每组参数设置,重复
3. 算法比较协议
标准化设置:
- 固定DAG生成参数
- 固定随机种子
- 对每个算法使用默认/推荐参数
- 报告均值和标准差
统计显著性:
- 使用配对t检验比较算法对
- Bonferroni校正多重比较
关键基准数据集
1. Benchmark 1: 线性高斯
- 节点数: 10, 20
- 边密度: 0.1, 0.2
- 样本数: 500, 1000, 5000
- 系数: 均匀采样
- 噪声:
预期结果:
- PC/GES: 在大样本(
)下SHD < 5 - NOTEARS: 与PC/GES相当
- 高噪声时所有方法性能下降
2. Benchmark 2: 非线性
- 节点数: 10, 20
- 非线性函数:
或 MLP(3层) - 样本数: 1000, 5000
- 边密度: 0.1
预期结果:
- PC: 性能显著下降(偏相关检验线性假设)
- GES: 使用非线性评分可改善
- NOTEARS-MLP: 较好处理非线性
3. Benchmark 3: 离散数据
- 节点数: 10, 20
- 取值数: 3, 5
- 样本数: 1000, 5000
- 条件概率: 随机CPT
预期结果:
- PC with G-test: 性能取决于样本量
- GES with BDeu: 相对稳定
4. Benchmark 4: 时序数据
- 变量数: 5, 10
- 时间长度: 500, 1000
- 滞后期: 1, 3
- 系数: VAR(1)模型
预期结果:
- PCMCI: 优于静态PC
- Granger检验: 作为baseline
优点与局限
合成数据优点
- Ground truth已知: 精确控制真实结构
- 可重复性: 固定随机种子确保可复现
- 参数控制: 可系统研究各因素的影响
- 规模可控: 可生成任意大小的数据集
合成数据局限
- 过度简化: 可能无法反映真实复杂场景
- 特定分布假设: 生成模型可能偏向某些算法
- 缺乏真实噪声: 真实数据中的测量误差、缺失值等难以模拟
- 人工痕迹: 随机生成的图可能不具有真实数据的结构特性
与其他笔记的连接
- 应用: 所有因果发现算法使用这些基准进行评测
- 指标: 因果发现评测指标用于评估合成数据上的算法性能
- 时序: 时序因果数据是重要的基准类型
- 真实数据: 真实数据评测是合成数据评测的补充
可复现性说明
Python数据生成示例
import numpy as np
from scipy.stats import norm
def generate_linear_gaussian_dag(n_nodes, n_samples, edge_prob=0.2,
coef_range=(0.3, 1.0), seed=None):
"""
生成线性高斯DAG数据
参数:
- n_nodes: 节点数
- n_samples: 样本数
- edge_prob: 边概率
- coef_range: 系数范围
- seed: 随机种子
返回:
- data: (n_samples, n_nodes) 数据矩阵
- dag: (n_nodes, n_nodes) 邻接矩阵(边i->j为1)
"""
if seed is not None:
np.random.seed(seed)
# 1. 生成随机DAG
dag = np.zeros((n_nodes, n_nodes))
# 使用-erdos-renyi模型,确保无环(仅上三角)
for i in range(n_nodes):
for j in range(i+1, n_nodes):
if np.random.random() < edge_prob:
dag[j, i] = 1 # i -> j
# 2. 生成边系数
coef_matrix = np.zeros((n_nodes, n_nodes))
for i in range(n_nodes):
for j in range(i):
if dag[i, j] == 1: # j -> i
coef = np.random.uniform(coef_range[0], coef_range[1])
if np.random.random() < 0.5:
coef = -coef
coef_matrix[i, j] = coef
# 3. 生成数据(拓扑顺序)
data = np.zeros((n_samples, n_nodes))
order = np.argsort(np.sum(dag, axis=1)) # 近似拓扑顺序
for node in order:
parents = np.where(coef_matrix[node, :] != 0)[0]
if len(parents) == 0:
data[:, node] = norm.rvs(0, 1, n_samples)
else:
mean = data[:, parents] @ coef_matrix[node, parents]
data[:, node] = norm.rvs(mean, 1)
return data, dag
def compute_shd(true_dag, est_dag):
"""计算SHD"""
n = true_dag.shape[0]
diff = 0
for i in range(n):
for j in range(n):
if true_dag[i, j] != est_dag[i, j]:
diff += 1
return diff
# 测试
data, dag = generate_linear_gaussian_dag(n_nodes=10, n_samples=1000, seed=42)
print(f"Generated {data.shape[0]} samples, {data.shape[1]} nodes")
print(f"DAG edges: {np.sum(dag)}")R bnlearn示例
library(bnlearn)
# 生成多个基准数据集
generate_benchmark <- function(n_nodes, n_samples, edge_density, n_reps=10) {
results <- list()
for (rep in 1:n_reps) {
# 生成随机DAG
dag <- random.graph(nodes = paste0("X", 1:n_nodes),
method = "melancon",
prob = edge_density)
# 生成参数
bn <- bn.fit(dag, data.frame(matrix(rnorm(n_nodes * 100),
ncol = n_nodes)))
# 生成数据
data <- rbn(bn, n = n_samples)
# 运行算法
pc_result <- pc.stable(data)
ges_result <- hc(data)
results[[rep]] <- list(
dag = dag,
data = data,
pc = pc_result,
ges = ges_result
)
}
return(results)
}章节总结
- 合成数据是因果发现算法评测的基础,允许控制ground truth和系统研究参数影响
- 线性高斯SCM是最常用的数据生成模型,结构方程为
- 非线性数据使用tanh、MLP等函数,检验算法对函数形式的鲁棒性
- 离散数据通过条件概率表生成,使用G-test等非参数方法评测
- Tetrad、bnlearn、causal-learn是主要的数据生成工具
- 关键参数:节点数、样本数、边密度、系数范围、噪声方差
- 评测协议包括:重复实验、统计显著性、配对比较
- 基准数据集应覆盖:线性/非线性、连续/离散、静态/时序等场景
- 合成数据局限:可能无法反映真实数据的复杂性,需结合真实数据评测
- 随机种子控制确保实验可复现性,是科学研究的基本要求
关键词: 合成数据, 基准测试, Tetrad, bnlearn, 数据生成, SCM, 线性高斯, 非线性, 离散数据, 评测协议