电路假说验证
1. 概述
电路假说(Circuit Hypothesis)是机制可解释性的核心假设,它声称神经网络的特定行为可以归因于网络中相对局部化、可识别的子电路。然而,验证这一假说需要严格的统计方法。本章介绍电路假说验证的理论框架和实践方法。
2. 电路假说的形式化
2.1 基本定义
给定神经网络 和行为 ,电路假说可以形式化为:
2.2 因果贡献的度量
对于电路 中的组件集合 ,定义其因果贡献为:
其中:
- 是保留电路 的模型输出
- 是将电路 置零的模型输出
3. 完整性充分性框架
3.1 完整性分数
完整性分数(Comprehensiveness Score) 衡量电路对行为的解释程度:
其中 是完整模型相对于基线的效应。
def comprehensiveness_score(model, circuit, test_cases, base_model=None):
"""
计算电路的完整性分数
"""
full_effect = compute_effect(model, test_cases, base_model)
circuit_effect = compute_effect(model, test_cases, base_model, circuit)
return circuit_effect / full_effect3.2 充分性分数
充分性分数(Sufficiency Score) 衡量电路单独能够解释行为的程度:
def sufficiency_score(model, circuit, test_cases):
"""
计算电路的充分性分数
"""
isolated_effects = []
for case in test_cases:
# 仅激活电路组件,其他置零
output = model.forward_with_circuit(case.input, circuit)
score = evaluate_output(output, case.target)
isolated_effects.append(score)
return np.mean(isolated_effects)3.3 组合分数
综合完整性和充分性:
4. 统计假设检验
4.1 检验统计量
定义检验统计量 :
其中 是第 个测试样本的因果效应。
4.2 零假设构造
通过以下方式构造零假设分布:
- 随机化电路:随机选择等大小的组件集合
- 置换测试:随机打乱样本-标签配对
- Bootstrap:从原始分布重采样
class CircuitHypothesisTest:
def __init__(self, model, circuit, test_cases):
self.model = model
self.circuit = circuit
self.test_cases = test_cases
def permutation_test(self, num_permutations=1000):
"""
置换检验验证电路假说
"""
# 计算真实电路效应
observed_effect = self.compute_circuit_effect()
# 生成零假设分布
null_distribution = []
for _ in range(num_permutations):
# 随机置换样本
shuffled_cases = self.shuffle_labels(self.test_cases)
# 计算随机电路效应
random_effect = self.compute_effect_with_cases(shuffled_cases)
null_distribution.append(random_effect)
# 计算p值
p_value = np.mean([
null >= observed_effect
for null in null_distribution
])
return {
'observed_effect': observed_effect,
'p_value': p_value,
'significant': p_value < 0.05
}
def shuffle_labels(self, cases):
"""置换样本标签"""
inputs = [c.input for c in cases]
targets = [c.target for c in cases]
shuffled_targets = targets.copy()
np.random.shuffle(shuffled_targets)
return [TestCase(inp, tgt) for inp, tgt in zip(inputs, shuffled_targets)]4.3 多重比较校正
当检验多个组件时,需要进行多重比较校正:
from scipy import stats
def bonferroni_correction(p_values, alpha=0.05):
"""
Bonferroni校正
"""
n_tests = len(p_values)
corrected_alpha = alpha / n_tests
significant = [p < corrected_alpha for p in p_values]
return significant
def fdr_correction(p_values, q=0.05):
"""
FDR (False Discovery Rate) 校正
"""
sorted_indices = np.argsort(p_values)
n = len(p_values)
for i, idx in enumerate(sorted_indices):
threshold = (i + 1) / n * q
if p_values[idx] > threshold:
break
significant_indices = sorted_indices[:i + 1]
return [i in significant_indices for i in range(n)]5. 因果效应估计
5.1 平均处理效应
5.2 方差估计
def estimate_variance(effects, bootstrap_samples=1000):
"""
Bootstrap方差估计
"""
n = len(effects)
bootstrap_means = []
for _ in range(bootstrap_samples):
indices = np.random.choice(n, size=n, replace=True)
bootstrap_mean = np.mean([effects[i] for i in indices])
bootstrap_means.append(bootstrap_mean)
return np.std(bootstrap_means)
def confidence_interval(effect, std_err, confidence=0.95):
"""
计算置信区间
"""
z = stats.norm.ppf((1 + confidence) / 2)
margin = z * std_err
return (effect - margin, effect + margin)6. 实验设计
6.1 样本选择
def select_test_samples(model, task, num_samples=100):
"""
选择具有区分性的测试样本
"""
samples = []
for _ in range(num_samples * 2): # 预留筛选
sample = generate_sample(task)
prediction = model.predict(sample.input)
# 选择模型确实学习的样本
if prediction == sample.target:
samples.append(sample)
if len(samples) >= num_samples:
break
return samples6.2 对照实验
def controlled_experiment(model, circuit, test_cases):
"""
设计对照实验
"""
conditions = {
'full_model': test_cases, # 完整模型
'circuit_only': test_cases, # 仅电路
'no_circuit': test_cases, # 无电路
'random_circuit': test_cases, # 随机电路
}
results = {}
for name, cases in conditions.items():
if name == 'full_model':
outputs = [model.predict(c.input) for c in cases]
elif name == 'circuit_only':
outputs = [model.forward_circuit_only(c.input, circuit) for c in cases]
elif name == 'no_circuit':
outputs = [model.forward_without_circuit(c.input, circuit) for c in cases]
else: # random_circuit
random_circuit = sample_random_circuit(circuit)
outputs = [model.forward_circuit_only(c.input, random_circuit) for c in cases]
results[name] = {
'accuracy': compute_accuracy(outputs, cases),
'effect': compute_effect_from_outputs(outputs, cases)
}
return results7. 与其他方法的对比
7.1 与SAE的对比
| 维度 | 电路假说验证 | Sparse Autoencoders |
|---|---|---|
| 目标 | 验证特定行为的因果机制 | 发现通用的语义特征 |
| 方法 | 统计假设检验 | 无监督字典学习 |
| 输出 | 行为归因 | 特征分解 |
| 可验证性 | 直接验证 | 间接验证 |
7.2 与传统归因方法的对比
def compare_methods(model, input_data, target, methods=['integrated_gradients', 'circuit', 'shap']):
"""
比较不同归因方法的输出
"""
results = {}
for method in methods:
if method == 'integrated_gradients':
attr = integrated_gradients(model, input_data)
elif method == 'circuit':
attr = circuit_attribution(model, input_data, target)
elif method == 'shap':
attr = shap_values(model, input_data)
results[method] = attr
# 计算方法间的一致性
correlations = compute_method_correlations(results)
return results, correlations8. 实践指南
8.1 最佳实践
- 多样化测试集:确保测试样本覆盖不同情境
- 控制混淆变量:确保实验条件一致
- 报告不确定性:给出置信区间和p值
- 可复现性:记录随机种子和实验设置
8.2 常见陷阱
- 过拟合测试集:使用独立的验证集
- 忽略方差:报告置信区间而非点估计
- 多重比较:使用适当的校正方法
- 虚假因果:注意相关不等于因果
9. 总结
电路假说验证为机制可解释性提供了严格的统计基础。通过完整性-充分性框架、假设检验和对照实验,我们可以:
- 量化电路对行为的因果贡献
- 验证电路假说的统计显著性
- 比较不同电路结构的解释力
这些方法对于构建可靠的、可解释的AI系统至关重要。