Frontier / Text as Data
文本因果推断:用 LLM 与嵌入把文字变成可识别的因果变量
当处理、结果或混淆藏在政策文件、年报、新闻、判决与社交文本里,如何用 AI 测量它们,又不破坏因果识别。
原理图解
一图看懂原理
先看这里
学完这一页你应该会什么
会先判断文本在因果图里的角色:处理 D、结果 Y,还是混淆 X。
会用主题 / 嵌入 / LLM 标注把文本转成数值变量。
知道文本测量误差会造成衰减偏误,需要双标注或信度检验。
理解"用结果 Y 监督学出来的文本表示"会带来过拟合偏差,需要样本分裂。
会避免后处理文本泄漏:只用处理前文本构造处理前变量。
学习路径
学习路径:从文本到可识别的因果变量
按这条路径学习:先定角色,再测量,再分裂防泄漏,再接入设计,最后估计并诚实报告测量风险。
Step 1
Role
判断文本是处理 D、结果 Y 还是混淆 X。
role(text)
Step 2
Measure
用嵌入 / LLM 把文本编码成数值,记录测量误差。
V_hat=f_theta(text)
Step 3
Split
在不同折上学表示与估效应,避免 Y 泄漏。
fold A / fold B
Step 4
Design
把文本变量接入 DiD / IV / DML。
D, Y, X -> design
Step 5
Report
报告信度、衰减处理、overlap 与人工核验。
audit
01 / 直觉
核心直觉
文本因果推断的第一步不是建模,而是画因果图:这段文字到底是 D、Y 还是 X?角色不同,方法完全不同。
把文本变成数值有三条路:可解释的词频 / 主题特征、预训练嵌入、LLM 标注或抽取。越灵活越强,但越容易把结果信息泄漏进表示。
核心风险是"用同一批文本既学表示又估效应":若表示是用结果 Y 监督学出来的,残差里就混入了 Y,估计会偏。解决办法是样本分裂 / 交叉拟合,与 DML 同一思想。
02 / 数学
从文本表示到可识别的处理效应
01 / 文本的因果角色
先确定文本进入因果图的位置:作为处理 D=g(text)、结果 Y=h(text),还是混淆 X=e(text)。识别策略由角色决定,而不是由模型决定。
role(text) ∈ {D, Y, X}02 / 文本测量
用映射 f_theta 把文本编码成数值。可解释特征、嵌入或 LLM 标注都行,但都会引入测量误差 epsilon。
V_hat = f_theta(text) = V_star + epsilon03 / 测量误差与衰减偏误
若把含误差的 D_hat 当处理回归 Y,经典测量误差会把系数往 0 拉(衰减)。需要多次测量、信度校正或把另一独立测量当工具变量。
plim beta_hat = beta · Var(D_star) / (Var(D_star) + Var(epsilon))04 / 文本作为混淆的调整
当同一段文本同时驱动 D 和 Y,用文本表示 e(text) 作为控制做调整:文本匹配,或在 DML 中作为高维 X 的一部分残差化。
tau = E[ E[Y|D=1, e(text)] − E[Y|D=0, e(text)] ]05 / 样本分裂防过拟合
若文本表示是有监督学出来的,必须在与效应估计不同的折上学表示,否则 Y 的信息会进入表示,造成过拟合偏差。
learn f_theta on fold A ; estimate tau on fold B03 / 代码
代码案例:从文本测量到带分裂的因果调整
下面用一个小语料演示:先把文本转成数值特征,再用样本分裂避免泄漏,最后把文本表示当混淆控制估计处理效应。
案例 1:先判断文本是 D、Y 还是 X
同一段年报文本,可能是处理(披露语气)、结果(情绪)或混淆(行业景气)。角色错了,后面全错。
roles = {
"披露是否提到裁员": "D 处理",
"年报情绪得分": "Y 结果",
"行业景气描述": "X 混淆",
}
for text_feature, role in roles.items():
print(f"{text_feature:>16} -> {role}")预期输出
披露是否提到裁员 -> D 处理
年报情绪得分 -> Y 结果
行业景气描述 -> X 混淆怎么读这段代码
- 同一份文本可以抽出不同变量,分别扮演不同因果角色。
- 先画因果图,再决定用哪种识别策略。
- 把"混淆文本"误当处理,会得到完全错误的效应。
案例 2:测量误差导致衰减偏误
文本测出来的处理变量含噪声,直接回归会把真实效应往 0 拉。
import numpy as np
rng = np.random.default_rng(3)
n = 5000
D_star = rng.normal(size=n) # true text construct
Y = 2.0 * D_star + rng.normal(size=n)
for sd in [0.0, 0.5, 1.0]:
D_hat = D_star + rng.normal(scale=sd, size=n) # measurement error
beta = np.polyfit(D_hat, Y, 1)[0]
print(f"noise sd={sd}: estimated beta = {beta:.2f}")预期输出
noise sd=0.0: estimated beta = 2.00
noise sd=0.5: estimated beta = 1.60
noise sd=1.0: estimated beta = 1.00怎么读这段代码
- 测量噪声越大,估计系数越被拉向 0。
- 这就是为什么文本测量需要信度检验或多重测量。
- 一个独立的第二次测量可以当工具变量纠正衰减。
案例 3:样本分裂防止把 Y 泄漏进文本表示
如果用结果 Y 监督学文本表示,再在同一批数据估效应,会过拟合出虚假关系。
# 正确做法:在 fold A 学表示/nuisance,在 fold B 估效应
# 错误做法:同一批数据既调表示又估效应 -> 乐观偏差
print("learn f_theta on fold A")
print("estimate tau on fold B")
print("never reuse outcome-supervised text features in-sample")预期输出
learn f_theta on fold A
estimate tau on fold B
never reuse outcome-supervised text features in-sample怎么读这段代码
- 有监督学到的文本表示会"记住"结果信息。
- 样本分裂 / 交叉拟合让表示与效应估计互不污染。
- 这与 DML 的 cross-fitting 是同一原则。
案例 4:交叉拟合用文本表示扣掉混淆
当文本同时驱动处理与结果,用交叉拟合把文本可解释的部分从 Y、D 中扣掉,再估计效应——朴素回归被文本混淆带偏,调整后接近真值。
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import LinearRegression, LogisticRegression
from sklearn.model_selection import KFold
import numpy as np
X = TfidfVectorizer(max_features=30).fit_transform(docs).toarray()
y_hat, d_hat = np.zeros(n), np.zeros(n)
for tr, te in KFold(5, shuffle=True, random_state=1).split(X):
y_hat[te] = LinearRegression().fit(X[tr], Y[tr]).predict(X[te])
d_hat[te] = LogisticRegression(max_iter=500).fit(X[tr], D[tr]).predict_proba(X[te])[:, 1]
yr, dr = Y - y_hat, D - d_hat
theta = np.sum(dr * yr) / np.sum(dr ** 2)
print("naive:", round(np.polyfit(D, Y, 1)[0], 3))
print("text-adjusted:", round(theta, 3))预期输出
naive: 1.70
text-adjusted: 1.05 # true effect = 1.0怎么读这段代码
- 朴素回归被文本混淆带偏(1.70 远高于真值 1.0)。
- 用文本表示交叉拟合残差化后,估计接近真值 1.0。
- 关键是 nuisance 在折外预测,避免过拟合污染目标参数。
04 / 案例
案例:用政策文本强度评估最低工资改革
- 研究问题:地方最低工资条例的"力度"对就业的动态影响。力度藏在条例文本里,没有现成数值。
- 用编码器或 LLM 把每份条例文本映射成严格度分数 D=g(text),作为连续 DiD 的处理强度——文本只负责测量 D,识别由面板与时点承担。
- 若担心条例措辞同时反映地方经济基本面(混淆),把文本表示 e(text) 作为高维控制放进 DML 残差化,并做 overlap 检查。
- 可信报告需说明:测量口径与信度、处理前后文本是否分离、样本分裂方案、衰减偏误处理,以及人工抽样核验文本标注。
05 / 因果
接入哪种设计:文本变量到识别策略的对照表
文本因果推断不是一种新的"识别魔法",而是把文字测成干净的 D / Y / X,再交给你已经会的设计。下面是常见对应关系。
01 / 文本=处理 → 连续 DiD / 事件研究
把文本强度作为连续处理,用面板与时点识别动态效应;文本只测 D。
D_it=g(text_it) -> Y_it=a_i+b_t+tau·D_it+e_it02 / 文本=混淆 → 文本匹配 / DML
当文本同时驱动 D 与 Y,用文本表示作控制做匹配或在 DML 残差化,并做 overlap 检查。
tau = E[Y|D=1,e(text)] − E[Y|D=0,e(text)]03 / 文本=结果 → 标准设计 + 信度
把文本测成结果变量后接入既有 RCT / DiD / IV,但要报告测量信度与衰减。
04 / 两次独立测量 → 工具变量纠正衰减
用第二次独立的文本测量作为工具,纠正单次测量的衰减偏误。
三条红线:(1) 测量误差→衰减,需信度 / 多重测量 / IV;(2) 严防后处理文本泄漏,只用处理前文本构造处理前变量;(3) 绝不用结果监督的文本表示在同一批样本估效应——必须样本分裂。
06 / 风险
常见误区
配套资源
下载实操资料
参考资料
- Gentzkow, Kelly, and Taddy (2019), Text as Data, Journal of Economic Literaturehttps://doi.org/10.1257/jel.20181020
- Roberts, Stewart, and Nielsen (2020), Adjusting for Confounding with Text Matching, AJPShttps://doi.org/10.1111/ajps.12526
- Veitch, Sridhar, and Blei (2020), Adapting Text Embeddings for Causal Inferencehttps://arxiv.org/abs/1905.12741
- Egami et al. (2022), How to Make Causal Inferences Using Texts, Science Advanceshttps://doi.org/10.1126/sciadv.abg2652
- Ash and Hansen (2023), Text Algorithms in Economics, Annual Review of Economicshttps://doi.org/10.1146/annurev-economics-082222-074352