因果推理中的倾向性评分:用基础概念拆掉异构样本里的偏差陷阱(基础篇)
(1/3)· 当 1000 行数据遇上 18 个变量,精确匹配概率趋近于零,倾向性评分正是为此而生
「用倾向评分看清缠结的因果链」
在 MT5 的策略研究里,很多指标和信号并非独立作用,而是彼此缠结。倾向性评分(Propensity Score)的思路是:把多个混杂变量压缩成一个标量,用来衡量某根 K 线或某笔订单「落入处理组」的概率。 具体做法是对每条样本计算一个介于 0 和 1 之间的分数,再按分数分层或做匹配,从而弱化变量间的相互干扰。2024 年 10 月 16 日某公开交易系统帖文下的互动数为 971 次浏览、3 条讨论,说明这类方法在实盘社群里已有低频但真实的关注。 对外汇与贵金属而言,这种评分能帮助区分「信号本身有效」和「只是凑巧跟趋势同频」。但贵金属杠杆高、跳空频繁,评分模型若只用历史常态数据,遇极端波动可能失真,结论仅代表历史样本下的概率倾向。
维度一高,精确匹配就崩了
在外汇或贵金属行情里做因果推断,训练样本常常是异质的:同一批标记数据里,既有高波动时段的开仓样本,也有低波动时段的,出现频率还参差不齐。若直接假设所有样本接受‘处理’(比如某信号触发)的倾向相同,算出来的平均因果效应(ATE)会有偏;想进一步拆条件平均处理效应(CATE),又容易撞上维数灾难。 匹配法的思路是把处理组和对照组里相似的单位配对,再比因果。文献里有人建议把它当预处理步:先丢掉不匹配的观测,后面接任何估计器(包括之前写过的元学习器)都更稳。但‘相似’这事在多维下极难办——尤其当你有1000行观测、18个变量时,逐行找完全匹配的机会趋近于零。 有研究用 p=0.5 的独立伯努利分布生成纯二分数据做了可视化:X轴是变量数,Y轴是每行至少找到一个完全匹配的概率,蓝线为均值、阴影是±2个标准差。1000次观测下,18维二分集的精确匹配概率基本为0;现实里连续变量一多,映射更麻烦。 下面这段脚本可复现上述结论。它用1000样本×1000次试验,随机二分数据集里统计‘某行全1’当作匹配代理,并画出概率随维度变化曲线。跑一遍你会直观看到:特征数相对于样本量一多,分类器泛化这类数据的能力就受限,数据量越大统计估计才越准(前提是 iid 成立,实盘未必总满足)。外汇贵金属属高风险,这种偏差会让策略回测假象放大。
class="kw">import numpy as np class="kw">import matplotlib.pyplot as plt def calculate_exact_match_probability(dimensions): num_samples = class="num">1000 num_trials = class="num">1000 match_count = class="num">0 for _ in range(num_trials): dataset = np.random.randint(class="num">2, size=(num_samples, dimensions)) row_sums = np.sum(dataset, axis=class="num">1) if any(row_sums == dimensions): match_count += class="num">1 class="kw">return match_count / num_trials def plot_probability_curve(max_dimensions): dimensions_range = list(range(class="num">1, max_dimensions + class="num">1)) probabilities = [calculate_exact_match_probability(dim) for dim in dimensions_range] mean_probability = np.mean(probabilities) std_dev = np.std(probabilities) plt.plot(dimensions_range, probabilities, label=&class="macro">#x27;Exact Match Probability&class="macro">#x27;) plt.axhline(mean_probability, class="type">color=&class="macro">#x27;blue&class="macro">#x27;, linestyle=&class="macro">#x27;--&class="macro">#x27;, label=&class="macro">#x27;Mean Probability&class="macro">#x27;) plt.xlabel(&class="macro">#x27;Number of Variables&class="macro">#x27;) plt.ylabel(&class="macro">#x27;Probability&class="macro">#x27;) plt.title(&class="macro">#x27;Exact Match Probability in Binary Dataset&class="macro">#x27;) plt.legend() plt.show()
◍ 用倾向性评分给混杂维度瘦身
做因果推断时,X 里的混杂变量一多就会撞上维数灾难。倾向性评分(PSM)的思路是:把单位在给定特征 X 下被分进实验组的概率估出来,变成单变量,拿它去匹配而不是拿整串向量去匹配。Rosenbaum 和 Rubin 1983 年证明过,只要阳性假设成立——即处理组和控制组在评分分布上有重叠——给定评分后数据就不混淆。这很直觉:要是两组完全不重叠,就像只拿男性试药却推断女性反应一样危险。 真实评分拿不到,实务里常用逻辑回归估,也能上梯度提升,但要多步防过拟合。用评分做匹配后,平均因果效应可以只在评分相近的子组里算,Nk 是每个匹配格里的样本数。问题在于,降维本身就在丢信息:原特征空间里差很远的两个样本,评分可能一样,硬匹配就偏了。 还有个 PSM 悖论值得在 MT5 外接 Python 验证:二元处理时最优评分是 0.5,若所有观测评分都恰为 0.5,那大家在评分空间里位置全同,匹配失去意义。外汇与贵金属数据做这类匹配前,先画评分重叠直方图,重叠区过窄就别硬推因果,杠杆品种误判风险极高。
「匹配算法怎么挑才不白做」
| 倾向性评分匹配里最常用的是最近邻,把处理组每个样本 i 按评分绝对差最小去配对对照组 j,距离写成 d(i,j)=minj{ | e(Xi)-e(Xj) | }。阈值匹配则先定一个半径 b,只在 | e(Xi)-e(Xj) | <b 内找对子,文献里建议 b 不超过评分的 0.25 个标准差,也有研究认为 0.20 个标准差更稳。 |
|---|
半径匹配是阈值思路的一对多版,允许处理组单元在 b 范围内同时配好几个对照组样本。Mahalanobis 度量另走一条路,按多变量接近度算最近马氏距离再配对,不单看评分标量。 贪婪匹配一旦配对就锁死,每对都是当下最优;最佳匹配允许回头改前面的配对,换全局最小距离。控制组够大时两者结果常一致,但最佳匹配的整体类内距离更小——只想凑出可比群体用贪婪就够了,要配对质量就上最佳。 子分类直接按评分百分位数切层,五层就能吃掉约 90% 的选择偏差;完全匹配是它的最优解版,子类由算法最小化加权距离生成。核匹配把配对和结果估计合一步做一对多。方法再多,效率天花板其实卡在问题定义清不清晰,不在选了哪套算法。
强忽视假设到底卡住了什么
在用倾向性评分做因果效应估计时,「强忽视」是绕不过去的一道门槛。它要求处理分配只跟观测到的基线协变量有关,跟潜在结果独立——说白了,你能拿到的特征里已经包含了所有影响「谁被处理、结果如何」的因素。 拆开看有两条硬约束。一是无未测量混杂:不存在既影响处理分配又影响结果、却没被记下来的变量;只要有这种漏网之鱼,处理效应的估计就会偏。二是积极性:在给定观测协变量的条件下,每个样本接受处理和控制的概率都非零,否则两组根本凑不出可比较的单元。 当这两条都满足,用倾向性评分(即给定协变量后接受处理的估计概率)做条件分析,就能得到平均处理效果 ATE 的无偏估计。ATE 衡量的是处理组与对照组结果的平均差,等价于把处理随机分配时的期望差距。外汇与贵金属市场数据噪声大、混杂因子多,直接套用此假设前应先核查遗漏变量风险。