← 返回蜂巢洞察

大规模产品实验:Airbnb、Netflix、Lyft和Uber是如何针对基于大语言模型的AI功能进行因果分析的

对于基于大语言模型的AI功能而言,因果推断已不再是理论上的概念。Airbnb、Netflix、Lyft和Uber都发布了详细的工程博客文章,详细说明了他们是如何衡量产品变更对用户行为的因果影响的。 他们所使用的技术方法(如差异分析法、回归不连续性分析以及双重稳健估计等)都是标准工具。 值得关注的是,这些团队是如何在大规模应用中运用这些技术的:在哪些情况下这些方法在实际操作中会失效,他们又是如何通过补充措施来确保估算结果的可靠性,以及他们是如何将这些数据与实际的产品决策联系起来的。 如果你正在开发基于大语言模型的功能,并且是根据用户点赞率和会话时长来做出产品决策的,那么这些文章一定会改变你对测量

对于基于大语言模型的AI功能而言,因果推断已不再是理论上的概念。Airbnb、Netflix、Lyft和Uber都发布了详细的工程博客文章,详细说明了他们是如何衡量产品变更对用户行为的因果影响的。

他们所使用的技术方法(如差异分析法、回归不连续性分析以及双重稳健估计等)都是标准工具。

值得关注的是,这些团队是如何在大规模应用中运用这些技术的:在哪些情况下这些方法在实际操作中会失效,他们又是如何通过补充措施来确保估算结果的可靠性,以及他们是如何将这些数据与实际的产品决策联系起来的。

如果你正在开发基于大语言模型的功能,并且是根据用户点赞率和会话时长来做出产品决策的,那么这些文章一定会改变你对测量方法的认知。

目前大多数团队仍然使用30天的A/B测试和点赞率来评估功能的影响。但当你需要确定某个指标的变化究竟是由于你的功能导致的,还是由于那周发生的其他众多因素造成的时,这种方法就不再适用了。

下面提到的四家团队,在大多数团队还尚未开始使用大语言模型进行开发之前,就已经遇到了这个问题。他们所总结出的经验教训,对于避免你犯同样的错误来说,是非常有价值的。我曾见过有些团队花费数周时间开发出一个功能,却后来又花了数周时间来争论那些数据是否真实可靠。其实这是完全可以避免的。

对这些企业而言,因果测量并不是一种事后才考虑的因素,而是产品测试的基础组成部分,它们直接被纳入到了产品的部署架构中。本文介绍的综合工具包,为那些传统A/B测试方法与部署模型不兼容的人工智能产品测试提供了有效的解决方案。

无论你是负责管理全球范围内的模型切换、基于阈值的路由分配、分阶段的产品发布,还是处理观察性数据收集工作,每种情况都需要采用特定的方法论。如果不使用这个工具包,带来的后果将不仅仅是数据结果的模糊不清,更严重的是,产品决策将会被那些受到各种干扰因素影响的数据所左右,而这种情况比完全没有测量数据要糟糕得多。

目录

本文中提到的每个代码块都可以在配套的笔记本中端到端运行,该笔记本的链接为:product-experimentation-causal-inference-genai-llm/tree/main/13_case_studies/。笔记本文件名为:case_studies_demo.ipynb

先决条件

您需要满足以下要求:

  • Python 3.11或更高版本

  • 熟练掌握pandas、scikit-learn以及基本的回归分析方法

  • 无需事先了解因果推断的相关知识:每篇案例研究都会直接解释所使用的技术

请安装本文中所需的软件包:

pip install numpy pandas scikit-learn scipy matplotlib

克隆配套的代码仓库并生成共享数据集:

git clone https://github.com/RudrenduPaul/product-experimentation-causal-inference-genai-llm.git
cd product-experimentation-causal-inference-genai-llm
python data/generate_data.py --seed 42 --n-users 50000 --out data/synthetic_llm_logs.csv

本文中的四个案例研究代码块都会使用pd.read_csv("data/synthetic_llm_logs.csv")来加载这个数据文件。该数据集包含50,000行数据,共16列,涵盖了用户身份、会话行为以及模型相关元数据,这些字段包括user_idsession_minutestask_completedmodel_usedlatency_msquery_complexity等。

为什么生产环境中的AI效果评估比看起来更困难

关于如何衡量AI功能的效果,人们通常会采用这样的方法:进行A/B测试并记录实验结果。如果p值低于0.05,就认为该功能是成功的,然后将其正式推出。但实际上,这种做法存在三个问题。

首先,并不是所有情况下都能实现随机化处理。企业级SaaS产品会分阶段将AI功能推送给不同的工作区用户,而A/B测试所假设的“每个用户都被随机分配到实验组或对照组”这一条件在现实中并不存在。消费类产品则会根据地区、用户群体或平台的不同逐步推出新功能;对于那些涉及安全性的功能,只有那些风险评估结果符合特定标准的用户才能率先使用这些功能。

当无法进行随机化处理时,A/B测试的方法就不再适用了。对非随机化数据重新应用同样的分析方法所得到的结果根本没有任何参考价值。那些同时影响哪些用户会使用某项功能以及他们如何使用该功能的因素,都会导致计算出的各种系数出现偏差,而且这种偏差往往会使该功能的效果看起来更加显著。

其次,短期指标并不总能预测长期效果。例如,如果某个功能的调整使得今天的用户满意度评分提高了8分,那么三个月后这种改变可能会增加用户对这一AI功能的依赖程度,从而导致用户流失。同样地,如果本周某种模型调度方式的改变使任务完成效率有所提升,但下个季度随着查询需求的变化,这种改进效果可能会消失。

我最初认为,短期指标能够可靠地反映长期发展趋势,但实际上它们并不能始终做到这一点。短期A/B测试的局限性在于:它只关注那些即时的数据变化,而完全忽视了用户行为方面的变化——而这些变化才是真正关键的因素。

最后,观察性数据是不可避免的。A/B测试只能涵盖产品决策中非常有限的一部分内容。比如六个月前实施的路由规则变更、第三季度进行的模型版本更新,或者那些在相关机制关闭之前选择了某种使用模式的用户——这些情况都无法在事后来进行实验验证。

对于任何需要回顾过去的数据进行分析的问题,或者对于那些其路由决策在伦理上无法被随机化的系统来说,人们只能依靠观察性数据来进行分析,而没有任何实验设计可以作为依据。

观察性因果推断并不是一种备选方案,而是一项核心能力。那些将这种方法视为可有可无的团队,往往会在利益相关者质疑“上个季度推出的措施为什么经不起仔细推敲”时,才意识到自己的错误。

下面的四个团队都构建了用于解决这些问题的系统。

案例研究1:Airbnb的未来价值框架

短期A/B测试无法捕捉到真正重要的行为变化

正如Jenny Chen在Airbnb技术博客文章《如何通过衡量未来价值来标准化各种权衡》中所描述的那样,Airbnb的工程团队遇到了他们的实验基础设施存在的一个根本性问题。标准的A/B测试通常会在实验期结束后的14到30天内测量结果。

对于那些会影响用户行为数月甚至数年的功能而言,这样的时间跨度显然太短了。例如,某个功能如果使30天内的预订量增加,那么它可能是加速了用户本来就会产生的行为,或者是真正增加了用户的长期参与度;但30天的指标无法区分这两种情况。

在大型语言模型的应用场景中,这个问题表现为“助手依赖性”现象。如果对助手的提示语进行重新设计,使其表达更加简洁、更自信,那么用户的评分和任务完成率通常会立刻上升。用户确实更喜欢这类直接、可靠的回答方式;但如果你这种 redesign同时也导致用户不太可能自行验证这些答案的准确性,那么你可能会在改善短期体验的同时,牺牲了系统的校准效果以及用户的长期信任度。

等到用户因为助手给出了两次错误的、但听起来却很自信的回答而开始流失时,提示语的变更早已被应用到了实际系统中,而其与用户流失现象之间的关联也变得难以察觉了。我见过很多团队花费数月时间进行诊断分析,试图区分是提示语的变更导致了问题,还是模型更新或季节性因素在起作用。

这个框架

你不需要等到长期结果出现才能采取行动。你需要根据之前的数据样本,判断哪些短期指标能够可靠地预测用户的长期留存率和收入情况。Airbnb的解决方案就是利用基于历史数据训练出的预测模型,将这些短期指标转化为预计的长期价值。

在特定的使用场景中,这一指标实际上是一种“未来价值”评分,它根据用户当前的行为模式来估算其未来的预订贡献。一旦建立了这样的模型,就可以通过该模型预测任何实验对未来价值的影响来进行评估,而30天内的数据就是其中重要的输入因素之一。实验的时间跨度通常较短,但评估的范围则会延伸到你的预测模型所能覆盖的整个时间范围。

在参考实现方案中,进行差异分析时需要满足一个前提假设:即两组用户在实验开始前的行为发展趋势应该是相同的。如果在功能上线之前,这两组用户的行为轨迹就已经存在差异,那么在进行差异分析时,这些原有的差异就会与新添加的功能所带来的影响混在了一起。大多数团队都会忽略这个假设的验证,因为验证这个假设需要绘制实验前各组用户的行为发展趋势图,而这通常需要花费20分钟的时间;而且,在没有看到明显的实验结果之前,人们往往会认为这种验证是没有必要的。

对于开发大语言模型的团队来说,实现这一目标需要满足两个条件。首先,你需要一些能够反映用户长期价值的指标,比如第7周的留存率和用户再次使用该服务的频率;其次,你还需要历史数据来将这些指标与你真正关心的长期结果(比如收入和用户的生命周期价值)联系起来。这种关联模型可以在历史数据集上训练一次,之后就可以用于新的实验中。

参考实现方案

下面的代码展示了具体的实现步骤:首先利用用户的短期行为数据来计算出他们的“未来价值”评分,然后将其作为差异分析或干预效果评估中的结果指标,从而替代原有的即时任务完成情况指标。

import pandas as pd
import numpy as np
from sklearn.linear_model import LinearRegression

# 合成的大语言模型监控数据,其中包含用户的留存信息
df = pd.read_csv("data/synthetic_llm_logs.csv")

# 第一步:在历史数据集上训练“未来价值”预测模型。
# 在实际应用中,这个模型会用在那些长期结果已经明确的用户身上进行训练。
historical = df[dfsignup_week < 10].copy()

feature_cols = ["task_completed", "thumbs_up", "session_minutes"]
X_hist = historical[featurecols].fillna(0)
yHist = historical["retained_7d"].values  # 用7天留存率作为长期价值的代理指标

fv_model = LinearRegression().fit(X_hist, y_hist)
# 这里计算的是在训练数据集上得到的R²值;在实际应用中应该使用保留样本进行验证
print("未来价值预测模型的R²值:", round(fv_model.score(X_hist, yHist), 3))

# 第二步:用“未来价值”预测模型为所有用户评分。
X_all = df[feature_cols].fillna(0)
df["future_value_score"] = fv_model.predict(X_all)

# 第三步:按实验组别来比较用户的“未来价值”评分。
print("\n各实验组别的平均‘未来价值’评分:")
print(df.groupby("wave").future_value_score.mean().round(4))

# 第四步:分析不同干预措施对用户“未来价值”的影响。
# 这里需要将“未来价值”评分作为自变量放入差异分析模型中。
analysis = df[df.signup_week < 30].copy()
analysis["post"] = (analysissignup_week >= 20).astype(int)
analysis["treated"] = (analysis.wave == 1).astype(int)

cells = analysis.groupby(["treated", "post")).future_value_score.mean()
did_fv = (
    (cells.loc[(1, 1)] - cells.loc[(1, 0)])
    - (cells.loc[(0, 1)] - cells.loc[(0, 0)))
)
print(f"\n不同干预措施对‘未来价值’评分的影响:{did_fv:+.4f}")
预期输出:
未来价值模型的R²值为0.024

按阶段划分的平均未来价值得分:
阶段      得分
1         0.6325
2         0.6271
变量名:future_value_score,数据类型:float64

差异分析对未来价值得分的影响:+0.0059

具体操作过程如下:你使用一个历史数据集来训练一个简单的线性模型,这些数据集中已经包含了用户的长期结果;该模型会将可观测的短期行为指标与7天留存率联系起来,从而间接反映用户的未来价值。

你用这个模型对所有用户进行评分,然后将得到的未来价值得分作为差异分析中的输出变量。虽然7天留存率并不是一个完美的指标,但它能迫使分析者重视那些与长期价值具有显著相关性的短期行为,而这种关注度是单纯通过用户点赞率无法实现的。

R²值仅为0.024,这一设计是有意为之的——因为这样就能突出在将即时行为数据与7天留存率关联起来时所存在的固有误差。虽然理想情况下,生产系统应该使用预测能力更强的指标(如用户复访率或查询深度),但即使是一个精度较低的关联模型,也能提供有用的信息。

我们的主要目标是要确定调整方向的正确性,而不是追求绝对的精确度。

为那些在第二周表现良好、但在第四个月却失败的长期价值评估实验建立监测机制

Airbnb所采用的框架正是为了解决“测量时间范围的选择问题”。当你在一个30天或14天的时间窗口内评估人工智能功能时,你往往会奖励那些能快速推动用户行为变化的功能,而不管这些变化最终会将用户引向何处。

要评估那些能够预示长期价值的指标,并不需要进行更长时间的实验,而是需要一个更加完善的测量模型。那些具备这种分析能力的团队,进行的实验数量会更少,因此他们也就不会遇到那些在初期表现良好、但最终却失败的项目。

如果你的基础设施中还没有这样的关联模型,那么开发这样一个模型应该成为你的首要任务,而不是继续扩充评估工具面板。

案例研究2:Netflix的准实验分类体系

部署结构决定了采用的方法

Netflix技术博客上发布的文章《Netflix在开展准实验时面临的关键挑战》(链接:"Key Challenges with Quasi Experiments at Netflix")对于产品团队来说,是一篇非常实用的文章。这篇文章的核心贡献在于建立了一个分类体系:针对每种部署场景,都对应着一种特定的因果分析方法,文章还指出了与这些方法相关的关键假设及可能导致的失败原因。

这种分类方式非常重要,因为大多数团队在选择分析方法时,并不会考虑部署结构的要求,他们往往只会选择自己熟悉的方法,而这样的选择往往会导致错误的结论。

该方法选择示意图包含四行,每行对应一个案例研究团队:Airbnb(蓝色,分阶段实施;处理前趋势呈现平行变化,采用差分法进行因果分析);Uber(红色,基于阈值来决定路由方式,未对任何运行中的变量进行人为干预,使用RDD方法进行分析);Netflix(绿色,对所有用户同时实施升级措施;在研究前期数据与实际结果之间的吻合度较高,因此采用了合成控制法进行分析);Lyft(橙色,采用自愿参与式的观察性研究方法,确保研究结果不受其他因素的干扰,同时使用了IPW/AIPW方法进行数据分析)。每行都通过箭头将相应的部署方案、假设条件与所采用的因果分析方法联系起来。

图1:部署结构决定了哪种识别方法才是合理的。对于基于阈值的分配机制,需要使用差分分析法;而对于自愿参与的情况,则应采用倾向得分法。选择哪种方法最终取决于团队的偏好,而团队首选的估计方法通常排在第二位。

Netflix制定的分类体系涵盖了四种情况,这些情况与大型语言模型团队实际遇到的情形几乎完全吻合:

分阶段推出新功能(对应的识别方法是差分分析法):当您先向A组用户推出人工智能功能,再向B组用户推出时,就会自然形成对照组和实验组。这种识别方法通过从结果差异中剔除共同的时间趋势因素来进行分析。

关键的前提是,这两组用户在实验开始前的发展趋势必须相同。如果其中一组用户在实验开始前就已经呈现出上升趋势,那么这种方法就无法区分这一趋势是与实验效果相关的,还是其他原因造成的。

基于阈值的分配机制(对应的识别方法是回归不连续性分析):当一个连续的评分标准决定了用户会使用哪种模型或功能时,处于阈值上下两侧的用户在除实验处理以外的所有方面几乎都是相同的。

在阈值点出现的差异能够反映出“局部平均处理效应”——即仅针对处于阈值附近的用户的因果效应,而对于所有不在这一范围内的用户而言,则体现的是整体平均处理效应。关键的前提是,用户无法人为地操纵自己的评分结果。

全范围升级(对应的识别方法是合成控制设计):当所有用户同时获得新功能时,由于没有对照组,就可以通过结合历史数据或构建合成反事实情景来估算如果没有进行这次升级,会发生什么情况。

关键的前提是,这种合成控制方法必须能够很好地拟合实验前的数据分布。如果拟合效果不佳,那么整个反事实分析就会失效。

自愿参与式的比较(对应的识别方法是倾向得分法):当用户主动选择使用某种人工智能功能时,可以通过重新加权或重新匹配对照组,来模拟在可观测变量上实现随机分配的情况。

关键的前提是,所有相关的混杂因素都必须被纳入分析范围。如果那些自愿参与使用的用户在某些你尚未测量的方面也属于高频率使用者,那么你的混杂因素调整就会不完整,从而导致估计结果出现偏差,而这种偏差在事后往往很难被发现。

这套分类体系使得方法的选择变得有条理:只需描述你的部署结构,就能找到最适合你当前情况的方法。

我见过有些团队跳过了这个步骤,而是花费了两周时间去对明明属于基于阈值分配机制的问题进行差分分析法分析,结果得到的估计值相差了40%。不过这两种方法都没有错,只是它们回答的是不同的问题而已。

参考实现方案

以下代码将这种分类方法实现为一种决策函数:给定一个部署场景描述,该函数会输出相应的方法及其关键假设。
TAXONOMY = {
    "staged_rollout": {
        "method": "差异分析法",
        "assumption": "实验组与对照组在处理前的发展趋势是平行的",
        "check": "在处理开始前,按组别绘制每周的平均值;"
                 "进行处理前的安慰剂回归分析",
        "failure_mode": "如果处理前的发展趋势不平行,或者存在随时间变化的混杂因素,"
                        "或者在采用新方法时没有应用Callaway-Sant'Anna校正方法,就会导致这种方法的失效",
    },
    "thresholdrouting": {
        "method": "回归间断设计法",
        "assumption": "用户无法精确地调整自己的得分,使其落在分界点上",
        "check": "进行McCrary密度检验;测试该方法对不同带宽的敏感性;"
                 "验证该方法的二次规格稳健性",
        "failure_mode": "如果用户可以操纵自己的得分,或者其他政策也在同一分界点上生效,"
                        "或者在分界点附近进行外推分析时会出现偏差,就会导致这种方法的失效",
    },
    "full_population_upgrade": {
        "method": "合成控制法",
        "assumption": "实际数据与合成反事实数据在处理前的拟合效果要好",
        "check": "需要进行实时的安慰剂检验;还需要在相同条件下进行其他对比分析;"
                 "绘制处理前各组的拟合曲线",
        "failure_mode": "如果处理前各组的拟合效果不佳,或者不同实验组之间存在干扰,"
                        "或者在处理后数据出现结构性的变化,就会导致这种方法的失效",
    },
    "opt_in_feature": {
        "method": "倾向得分法(IPW/匹配算法)",
        "assumption": "所有影响用户选择参与实验以及最终结果的混杂因素都能被观察到",
        "check": "在加权处理前后,计算标准化平均差异;"
                 "绘制倾向得分的重叠直方图",
        "failure_mode": "如果存在未被测量的混杂因素,或者倾向得分模型的设定有误,就会导致这种方法的失效",
    },
}

def select_method(scenario: str) -> None:
    if scenario not in TAXONOMY:
        valid = ", ".join(TAXONOMY.keys())
        print(f"未知的部署场景。有效选项:{valid}")
        return
    entry = TAXONOMY[scenario]
    print(f"部署场景:      {scenario}")
    print(f"使用的方法:        {entry['method']}")
    print(f"关键假设:    {entry['assumption']}")
    print(f"需要进行的检查:    {entry['check']}")
    print(f"可能导致该方法失效的情况:{entry['failure_mode']}")

# 示例:在企业工作空间中分阶段推出人工智能功能
select_method("staged_rollout")
print()
# 示例:在不同模型层级之间根据置信阈值进行路由选择
select_method("threshold_routing")

预期输出:

部署场景:      分阶段推出人工智能功能
使用的方法:        差异分析法
关键假设:    实验组与对照组在处理前的发展趋势是平行的
需要进行的检查:    在处理开始前,按组别绘制每周的平均值;进行处理前的安慰剂回归分析
可能导致该方法失效的情况:如果处理前的发展趋势不平行,或者存在随时间变化的混杂因素,或者在采用新方法时没有应用Callaway-Sant'Anna校正方法

部署场景:      根据置信阈值进行路由选择
使用的方法:        回归间断设计法
关键假设:    用户无法精确地调整自己的得分,使其落在分界点上
需要进行的检查:    进行McCrary密度检验;测试该方法对不同带宽的敏感性;验证该方法的二次规格稳健性
可能导致该方法失效的情况:如果用户可以操纵自己的得分,或者其他政策也在同一分界点上生效,或者在分界点附近进行外推分析时会出现偏差

每种部署方案都对应着一种特定的方法、一个主要的假设依据、用于验证该假设是否成立的诊断机制,以及会使得分析结果无效的失败情形。

这种功能其实是一种决策辅助工具,它使方法选择的过程变得明确化,这样团队在编写任何回归代码之前就能就识别策略达成一致。如果没有这样的共识,往往会在分析过程中发现团队中的两个人实际上在使用不同的因果模型来处理相同的数据。

选择了错误的方法,再干净的数据也无济于事

大多数团队都会选择他们最熟悉的因果分析方法。但这种做法其实是错误的;而Netflix制定的分类体系正是为了避免这种错误。

一个拥有实验设计经验的大型语言模型团队,即使在他们使用阈值路由系统进行分析时——而在这种情况下RDD这种方法会给出更准确的结果,并能得到一个可靠的地方性处理效应估计值,而不是一个平均后的估算结果——他们也会优先选择实验设计方法。

这种分类体系强调了一个至关重要的原则:方法的选择应该由数据分配机制本身来决定,而不是取决于团队对某种方法的熟悉程度。如果你的数据分配机制是基于某个临界分数来进行的,那么无论团队已经掌握了哪些分析方法,RDD都应该作为首选工具。

如果选择了错误的方法,不仅会得到一个误差更大的估计结果,还会得到一个在结构上就不正确的结论,而再干净的数据也无法纠正这种错误。

案例研究3:Lyft的双重稳健性验证方法

为什么单一模型方法在实际应用中会失败

Shima Nassiri在Lyft工程博客上发表的文章《信任那些无法被检验的方法:双重稳健模型的验证与诊断机制》指出,在大多数实际的因果分析项目中,至少会存在一个包含错误设定因素的模型。

在进行观察性因果分析时,你几乎总是在同时使用两个模型:一个是倾向得分模型(根据协变量来预测受试者是否接受治疗),另一个是结果模型(根据治疗情况和协变量来预测最终的结果)。

这两个模型实际上都是对未知真实函数的近似表示。如果其中任何一个模型的设定有误,那么你的因果分析结论就会产生偏差,而仅凭常规的分析输出你是无法发现这一点的。

为了解决这个问题,人们提出了双重稳健性估计方法,尤其是增强型逆概率加权估计器(AIPW)。AIPW结合了倾向得分加权技术和回归调整机制:只要倾向得分模型或结果模型的设定是正确的,AIPW得出的估计结果就是可靠的。因此,只需要一个设定合理的模型就足够了。

不过,AIPW并不能有效防止那些未被测量到的混杂因素的影响;此外,它仍然要求所有同时影响治疗分配和结果的因子都必须被纳入分析模型中。如果你的数据中缺少某个关键的混杂因素,AIPW同样无法帮助你得到正确的分析结果。

Nassiri的文章所涉及的内容其实超出了估计工具本身的范围。真正使其具有实际意义的是,文章中描述的那套用于在采取行动之前验证观察性分析结果的诊断工具包。

在规范的随机实验中,你可以检查数据分布的平衡性并计算统计功效;而在观察性研究中,你就需要付出更多的努力,因为这类研究的设计本身并不保证数据的随机性。我见过一些团队跳过了这个诊断步骤,结果后来花费了数周时间来解释为什么他们的因果估计结果会相差两倍之多。

Lyft的生产诊断系统能在决策之前发现模型中的错误

该诊断流程包括四项检查:

1. 权重分布检查

在拟合完倾向性模型后,需要绘制IPW权重的分布图。如果某些用户的权重值超过20或30,那就说明这些用户的处理组分配概率几乎为零,而这违反了正性假设——即每个样本都应具有被分配到处理组或对照组的非零概率。

对于这类用户来说,缺乏可供对比的“反事实数据”;如果让这种异常值影响最终的因果分析结果,就会破坏整个分析的可靠性。正是由于忽略了这项检查,某些行为异常的特殊用户才可能导致ATE估计结果出现15个百分点的偏差。

2. 修剪阈值设置

需要设定一个最大权重值。任何权重超过该阈值的观测值都会被缩减到该阈值水平。常见的选择是权重分布的95百分位或99百分位。

通过设置修剪阈值,我们可以用较小的偏差换取方差的显著降低,从而使估计结果在模型设定出现轻微错误时也能保持稳定性。如果不进行这种修剪处理,数据中那些极端的异常值就会影响最终的分析结果。

3. 协变量平衡性检查

需要为倾向性模型中的每个协变量绘制加权前后的标准化均值差异图。理想情况下,加权处理后这些差异的绝对值应小于0.1。

如果某些协变量的权重在加权处理后仍超过这个阈值,那就说明倾向性模型没有充分考虑该协变量对处理结果的影响。这项检查能够有效避免“我们已经考虑了所有因素”这种思维陷阱带来的错误。

4. 安慰剂结果测试

可以选择一个你的处理措施显然不会导致的结果进行测试,比如在该处理措施出现之前就已经存在的某个指标,然后使用完整的AIPW分析流程对该指标进行评估。

如果分析结果显示安慰剂组存在显著差异,那就说明存在问题:可能是未测量的混杂因素、倾向性模型设定错误,或是数据泄露等原因。安慰剂测试失败是表明你的分析结果不可信的最明显信号之一,而且这种问题在正式发布任何分析结果之前就能被发现。

参考实现代码

下面的代码展示了Lyft的分析流程中用于权重分布检查和数据修剪的步骤,这些步骤是在接受任何因果估计结果之前必须执行的。import pandas as pd import numpy as np import matplotlib matplotlib.use("Agg") import matplotlib.pyplot as plt from sklearn.linear_model import LogisticRegression df = pd.read_csv("data/synthetic_llm_logs.csv") # 估计用户选择使用代理模式的倾向 X = pd.get_dummies( df[["engagement_tier", "query_confidence"]], drop_first=True ).astype(float) y = df["opt_in_agent_mode"] ps_model = LogisticRegression(max_iter=1000).fit(X, y) df["propensity"] = ps_model.predict_proba(X)[:, 1] # ATE权重计算:处理组为1/P(treat),对照组为1/(1-P) df["ipw"] = np.where( df.opt_in_agent_mode == 1, 1 / df.propensity, 1 / (1 - df.propensity), ) # 统计诊断分析1:权重分布 print("IPW权重百分位数:") for p in [50, 75, 90, 95, 99]: print(f"第{p}百分位:{np.percentile(df.ipw, p):.2f}") fig, ax = plt.subplots(figsize=(8, 4)) ax.hist(df.ipw, bins=60, edgecolor="none", alpha=0.7) ax.axvline(nppercentile(df.ipw, 99), color="red", linestyle="--", label="第99百分位(截断阈值)") ax.set_xlabel("IPW权重") ax.set_ylabel("数量") ax.set_title("权重分布:检查极端值") ax.legend() plt.tight_layout() plt.savefig("weight_distribution.png", dpi=140) print("已保存文件 weightdistribution.png") # 统计诊断分析2:在99百分位处截断极端权重 trim_threshold = nppercentile(df.ipw, 99) df["ipw_trimmed"] = df.ipw.clip(upper=trim_threshold) # 比较截断前后のATE值 def weighted_ate(data): t = data[data.opt_in_agent_mode == 1] c = data[data/opt_in_agent_mode == 0] return ( (t.task_completed * t.ipw_trimmed).sum() / t.ipw_trimmed.sum() - (c.task_completed * c.ipw_trimmed).sum() / c.ipw_trimmed.sum() ) # 使用ipw列计算未截断时的ATE值 df["ipw_trimmed_orig"] = df["ipw"].copy() # 先备份原始数据 ate_untrimmed = ( (df[df.opt_in_agent_mode==1].task_completed * df[df/opt_in_agent_mode==1].ipw).sum() / df[df(opt_in_agent_mode==1].ipw.sum() - (df[df.opt_in_agent_mode==0].task_completed * df[df.opt_in_agent_mode==0].ipw).sum() / df[df.opt_in_agent_mode==0].ipw.sum()) ) ate_trimmed = weighted_ate(df) print(f"\n未截断时的ATE值:{ate_untrimmed:+.4f}") print(f"截断后的ATE值: {ate_trimmed:+.4f}") print(f"截断阈值: {trim_threshold:.2f}")

预期输出:

IPW权重百分位数: 第50百分位:1.52 第75百分位:1.57 第90百分位:2.88 第95百分位:8.14 第99百分位:8.58 已保存文件 weight_distribution.png 未截断时的ATE值:+0.0851 截断后的ATE值: +0.0852 截断阈值: 8.58 IPW权重分布直方图(在完成上述统计诊断分析后):该图表显示了50,000个IPW权重的分布情况,其中99百分位处的极端值被截除;下方面板对比了未截断时的ATE值+0.0851与截断后的ATE值+0.0852,结果证明极端权重对最终计算结果的影响可以忽略不计。

图2:在包含50,000名用户的合成数据集上,IPW权重的分布情况。大部分权重集中在1.0到3.0之间,有500个观测值的权重超过了99百分位阈值8.58。进行数据筛选后,平均处理效应仅变化了0.0001,这进一步证明了极端值对最终估计结果的影响微乎其微。与图1中的概念性分析不同,这种诊断方法是直接基于共享数据集中的真实数据进行的。

具体操作过程如下:首先建立倾向模型并计算ATE权重,然后绘制权重直方图,以此判断是否存在某些用户的权重值过高,从而对最终估计结果产生主导性影响。

99百分位线就是用于数据筛选的视觉参考标准。通过应用这一标准来比较未筛选处理与经过筛选处理后的平均处理效应,如果两者相差不大,说明极端值对结果的影响很小;但如果差异较大,那就意味着存在少数具有显著影响的观测值,此时经过筛选后的估计结果会更加可靠。

两小时的诊断工作能避免四分之一的错误工程决策

当通过观察性数据来衡量人工智能特征的因果效应时,几乎可以肯定的是,你的倾向模型和结果模型都可能存在误差。而AIPW结构能够有效防止其中某个模型出现错误。Lyft提供的诊断工具包可以帮助你在采取行动之前了解这两个模型的误差程度。

进行权重诊断分析和安慰剂测试可能会使因果分析的过程增加大约2小时的时间。但这2小时的时间却能避免那些基于错误结论而导致的、耗费工程师数月时间去研究错误方向的错误工程决策,这种情况我确实见过。忽略这些诊断步骤所带来的代价是沉重的:六名工程师将会把精力投入到根本与目标结果无关的研究中。

案例研究4:Uber的因果预测分析流程

将因果估计结果与预测数据相结合

因果分析的标准输出通常包括一个点估计值以及置信区间。例如,某个人工智能特征使任务完成率提高了6个百分点,95%置信区间为[3.8, 8.2]。这样的数值主要用于回答“过去发生了什么”这类问题。

然而产品决策往往需要基于对未来的预测。如果你考虑将模型路由的阈值从0.85提高到0.90,你就需要了解这样做在下一个季度会带来怎样的成本和质量方面的影响——这种预测必须建立在你从上个月实验中获得的经验基础上。 Totte Harinen和Bonnie Li在Uber工程博客上发表的文章《利用因果推断提升Uber用户体验》详细介绍了Uber是如何将因果推断方法应用于实际产品决策中的,这一做法为将因果效应估计结果融入到未来预测模型中提供了重要依据。这种结构上的调整在于:将这种因果关系视为预测模型中的一个参数。如果分别预测成本和质量,并假设它们之间存在稳定的关联关系,那么这个因果参数实际上就无法被明确指定出来。而通过这种结构上的调整,我们可以直接对路由阈值对成本与质量之间权衡关系的影响进行建模,然后根据关于查询量、查询分布以及模型性能的不同假设,来预测这一参数在未来会呈现出怎样的变化趋势。

这对于大型语言模型系统而言尤为重要,因为路由决策与成本之间的关系是非线性的,并且会受到数据分布的影响。在当前查询量下看似具有成本效益的路由阈值,在查询量增加三倍时可能会失效。你在第一季度优化的路由模型,在第三季度可能会被价格更低的模型取代,从而导致成本与质量之间的平衡关系发生根本性变化。将这种因果关系纳入预测模型中,就能在这些结构性变化发生之前及时发现它们。

参考实现

在研究接近路由阈值的区域时,需要基于两个关键假设来进行分析。首先,工程师和用户无法精确地控制query_confidence这个参数,使其始终落在0.85这一阈值的一侧;因此,在阈值附近的一个狭窄范围内,查询分配的结果应该是随机的。

其次,潜在结果函数必须在整个阈值区间内保持连续性,这样在0.85这个临界点观察到的变化才能真正归因于路由分配机制,而不会被其他在同一分数水平上执行的策略所影响。

import pandas as pd import numpy as np df = pd.read_csv("data/synthetic_llm_logs.csv") # 第一步:估算路由阈值变化对成本和质量的因果影响 # (采用RDD算法:比较接近路由阈值的用户的数据) cutoff = 0.85 bw = 0.10 near = df[ (df.query_confidence > cutoff - bw) & (df.query_confidence < cutoff + bw) ].copy() # 低置信度的查询会被路由到高级模型(低于阈值的查询需要特殊处理) near["routed_premium"] = (near.query_confidence < cutoff).astype(int) # 通过接近阈值的区域进行因果效应分析 quality_effect = ( near[near.routed_premium == 1].task_completed.mean() - near[near.routed_premium == 0].task_completed.mean() ) cost_effect = ( near[near.routed_premium == 1].cost_usd.mean() - near[near.routed_premium == 0].cost_usd.mean() ) print(f"高级路由对质量的影响:{quality_effect:+.4f}") print(f"高级路由对成本的影响:{cost_effect:+.4f}") # 第二步:将这些结果应用到未来的预测场景中 # 假设我们要分析的是:如果将阈值从0.85提高到0.90,会带来什么影响? # 那些置信度在0.85到0.90之间的查询,将会从高级路由切换到廉价路由。 threshold_change_users = df[ (df.query_confidence >= 0.85) & (df.query_confidence < 0.90) ] n_shifted = len(threshold_change_users) print(f"在阈值从0.85变为0.90的情况下,会有{n_shifted}条查询发生变化") # 不同的查询量场景 monthly_query_volume = [500_000, 1_000_000, 2_000_000] shifted_fraction = n_shifted / len(df) # 发生变化的查询占总流量的比例 print("\n预测结果:将阈值从0.85提高到0.90") print(f"当每月查询量为{monthly_query_volume[0]}时,质量变化幅度为>16%;成本变化幅度为>20美元/月") for vol in monthly_query_volume: n_affected = vol * shifted_fraction delta_quality = quality_effect * n_affected / vol # 整体质量的变化率 delta_cost = -cost_effect * n_affected # 由于切换到廉价路由而节省的成本 print(f"{vol:>20,.0f} 质量变化幅度:{delta_quality:>+16.4f} 成本变化幅度:{delta_cost:>+20,.0f}")预期输出:
高级路由方案带来的质量提升效果:+0.0613  
高级路由方案带来的成本降低效果:+0.0080  

当阈值从0.85提高到0.90时,会有5415个查询请求的路由方式发生改变。  

未来情景分析:如果将阈值提高至0.90,  
      - 每月查询量          质量变化            成本变化(美元/月)  
              500,000            +0.0066              -436  
              1,000,000            +0.0066              -871  
              2,000,000            +0.0066              -1,742  

具体分析过程如下:首先,通过在接近阈值的位置进行对比分析,来评估高级路由方案对任务完成质量及成本的影响;然后确定当阈值从0.85提高到0.90时,会有多少查询请求的路由方式发生改变;最后,针对不同的每月查询量情景,预测这种变化所带来的质量与成本影响。最终生成的表格可以直接供产品团队或财务团队参考使用——在当前的查询量下,提高阈值每月可节省大约X美元的成本,但同时也会使任务完成率下降约Y个百分点。

容量规划中的因果预测

这种因果预测方法在涉及成本与质量双重因素的路由决策及基础设施规划中尤为有用,因为在这种情况下,你需要在尚未达到实际业务规模之前就做出相应的选择。通过将这种因果分析结果应用到不同的业务量情景中,原本只是回顾性的分析结果就能转化为具有实际操作意义的预测数据。

如果跳过这个步骤,这些因果分析结果就会仅仅停留在分析文件中,与容量规划及定价决策脱节。我见过很多有用的分析报告就是因为这个原因而被忽视的。而通过运用这种方法,分析团队所提供的信息实际上会对产品的运营产生直接影响。

这四个团队的共同点

这四个团队虽然采用了不同的方法,但都遵循了相同的操作规范。

根据部署结构选择合适的方法

分析时应从数据分配机制入手,再逆向推导出识别策略。Airbnb放弃了短期的A/B测试,因为他们的功能所带来的长期价值远远超出了30天的观察周期;Netflix则使用RDD来构建阈值路由系统,因为这种划分方式本身就是一种天然的识别策略。

选择某种技术,必须确保你的系统设计使得相应的识别策略具有可行性。如果默认采用团队最熟悉的方法,就很容易出现识别错误,而这些错误往往不会被及时发现。

在构建预测模型之前先进行诊断性分析

在报告预测结果之前,必须先验证各种假设是否成立。Airbnb会用历史数据来检验他们的领先指标模型;Lyft则在基于观察数据得出初步预测之前,会先分析数据的分布情况并进行对照组测试。

如果某项估算结果没有附带相应的诊断性分析数据,那么这种估算就缺乏说服力。在季度评审时,当产品团队对你的数据提出质疑时,这一区别就显得尤为重要。

针对具体的产品决策,设计相应的因果估算方法

Airbnb会通过估算长期价值来辅助制定功能发布的决策;Netflix则通过开展准实验来确定功能的推出时机。

那些无法为任何具体产品决策提供参考的分析根本不值得进行——它们只会浪费分析师的时间,在报告结果中产生误导性的信息,而且长此以往还会削弱利益相关者对数据分析能力的信任。

在每项估算结果中都记录可能出现的失败原因

每种分析方法都有其可能出错的特定情形:对于差异性实验来说,可能是趋势不平行;对于随机分配实验而言,可能是数据划分方式存在问题;对于倾向得分法来说,可能是未测量到某些混淆因素;而对于针对全体用户的评估方法来说,可能是合成控制组的匹配效果不佳。

在发布估算结果时,必须同时说明其可能出现的失败条件。对于持怀疑态度的受众而言,一项分析的可信度并不取决于置信区间本身,而在于能否透明地披露那些可能导致该分析结果失效的具体假设。

如何在自己的大语言模型系统中应用这些方法

大多数大语言模型团队目前并没有建立起完善的因果分析体系。以下步骤是按照影响程度排序的。

1. 在需要数据之前就先建立相应的分析框架

在所有的观察性因果分析中,最大的限制往往在于所需的数据尚未被收集起来。在进行差异性实验之前,你必须为两个实验组都准备好预处理数据;而对于那些用户自愿参与的功能来说,你也需要有一套能够预测用户选择意愿的协变量。

现在就为六个月后可能需要进行的分析建立相应的系统框架:记录会话时长、查询复杂度、7天内的用户留存率以及模型决策过程等参数。虽然这样的准备工作成本不高,但事后收集数据却是不可能的。

2. 对自己的部署机制进行分类

将Netflix制定的分类标准应用到目前产品中正在使用的所有人工智能功能上。对于每一个功能,都要思考:治疗组是如何分配的?这种分配机制支持哪种因果分析方法?其核心假设是什么?你是否拥有验证这些假设的数据?通过这样的分析,通常会发现大多数功能的评估工具与其实际的分配机制并不匹配。这种不匹配并不意味着学术上的缺陷,而是意味着你无法确定这些功能是否真的起到了预期的效果。

3. 进行一次包含大量诊断性分析的因果研究

选择其中一个功能,进行平衡性检查、安慰剂测试,评估不同参数设置对分析结果的影响,并将所有分析结果整理成报告。养成每次都进行这些检查的习惯,有助于为未来的分析工作树立规范。

通常,这种情况也会暴露出与你最看重的某个功能相关的某个令人不满的问题。我在三个不同的团队中都见过这种情况:那些“看起来肯定有效”的功能,其实其对比组的设计存在缺陷。

4. 区分短期指标与长期指标

借鉴Airbnb的做法,至少确定一个能够在30天的实验周期内测量的、能够反映产品长期价值的指标。比如用户留存率在7天后的数据、第3周的复访率,或者问题升级的趋势等,都是合适的候选指标。

在每次实验的总结报告中,都要同时汇报这些长期指标以及短期的用户参与度数据。如果不这样做,你实际上就是在优化一个替代性指标,而直到下个季度才会发现其中存在的问题。

5. 使因果分析具有前瞻性

在生成因果分析结果时,添加一行内容:“在业务量仅为当前水平的30%的情况下,这种效应会导致……”这样的表述方式能迫使分析师将分析结果与产品规划工作联系起来,同时也会吸引更多人关注这些分析结果。

当生产环境中的因果分析流程出现故障时

生产环境中的因果分析流程往往会在一些可预测的地方出问题。

组织层面的缺陷

首先,没有人真正负责设计这些测量指标。在大多数团队中,数据科学家总是在功能上线之后才进行数据分析。由于这是常规的工作流程,因此人们总是会对那些本来就不是为因果分析而设计的数据进行事后分析。

解决办法是在功能上线之前就对测量指标的设计进行审查:确定对照组的选择标准、预实验期的长度、核心假设是什么,以及哪些因素会影响到这些测量的准确性。只需花费30分钟的时间进行这样的审查,就能避免许多无法挽回的分析错误。

其次,因果分析的结果并没有传达给决策者。即使统计分析结果是正确的,但如果这些结果没有为产品决策提供任何参考,那么这种分析也是失败的。仅仅改进分析方法并不能解决这个问题。因果分析流程需要同时具备快速报告机制和严谨的分析流程。

技术层面的故障

首先,往往是在事后才发现数据采集过程中存在缺陷。最常见的技术问题是某些必要的协变量并没有被记录下来。直到实验结束三周后,当试图检查数据平衡性或运行倾向模型时,才会发现这些缺陷。

前面提到的“尽早收集数据”的原则可以解决这个问题,但这需要基础设施团队的大力支持——他们必须优先考虑那些对因果分析有直接帮助的数据采集工作,而不仅仅是满足产品报表的需求。不过,获得这样的支持往往比实际进行数据采集本身更加困难。

其次,在合成数据集中会出现“处理组信息泄露”的问题。对于那些在合成数据或内部数据上测试因果分析方法的团队来说,数据生成过程可能会无意中融入你想要测量的因果效应,从而导致各种分析方法看起来都有效果,但实际上并不准确。

请使用外部保留数据或生成窗口之外的样本集来验证你的分析结果。这一点很容易被忽视,因为合成数据看起来非常整齐规范。数据行中的结构性污染往往很隐蔽,难以被发现。

解释性错误

首先,将“晚期处理效应”与“平均处理效应”混为一谈。随机区组设计能够估算出“局部平均处理效应”:即在临界点附近、针对特定用户的处理效果;而倾向匹配法则能估算出“平均处理效应”:即那些接受了处理的用户所体现出的效果。不过,要估算整个群体的平均处理效应,则需要采用不同的方法。

当分析师询问“这个特征到底有什么作用”时,他们通常指的是平均处理效应。如果你的因果分析结果只给出了晚期处理效应,却没有解释两者之间的区别,那么他们就会将这一估算结果用于那些本不该用它来做出决策的场合,最终导致做出的选择出现错误,而这种错误往往很难追溯到最初的分析过程中。

其次,外部有效性假设并不总是成立。上个季度针对某一用户群体得出的因果估算结果,可能并不适用于下一个季度;尤其是当你将业务扩展到新的市场领域或进入国际市场时,这种情况更为明显。

当某个功能开始推广时,如果你要评估早期就选择使用该功能的高级用户所受到的影响,那么就必须明确记录你的估算结果是针对哪一类用户的。同时,也要明确指出:当这个估算结果被应用于其他用户群体时,其结论可能会产生怎样的偏差。

第三,报告的精确度往往高估了结果的确定性。在那些存在残余混杂因素的观察性研究中,如果因果估算结果的精确度达到两位小数,那么这种表述方式就会给人一种结果非常确定的印象,但实际上这种确定性并不符合分析的实际情况。

在报告中,应同时提供点估计值、置信区间、这些估算结果所依赖的假设条件,以及经过加权处理后的最终结果。所有这些信息都应该放在决策者能够看到的地方进行展示。只有当人们能够清楚地看到这些不确定性因素时,这项分析才算真正完成。

自助法置信区间

观察性分析得出的点估计值都存在抽样误差。下面通过自助法得出的95%置信区间,可以为本文中的三个数值估计结果提供参考:Airbnb的差异处理效应对未来价值得分的影响、Lyft的平均处理效应,以及Uber的随机区组设计质量效应。

import pandas as pd
import numpy as np
from sklearn.linear_model import LinearRegression, LogisticRegression

rng = np.random.default_rng(7)
df = pd.read_csv("data/synthetic_llm_logs.csv")
n_boot = 500

# 自助法1:Airbnb差异处理效应对未来价值得分的影响
historical = df[df.signup_week < 10].copy()
feature_cols = ["task_completed", "thumbs_up", "session_minutes"]
fv_model = LinearRegression().fit(historical[feature_cols].fillna(0), historical["retained_7d"].values)
df["future_value_score"] = fv_model.predict(df[feature_cols].fillna(0))
analysis = df[df.signup_week < 30].copy()
analysis["post"] = (analysissignup_week >= 20).astype(int)
analysis["treated"] = (analysis.wave == 1).astype(int)

did_boots = []
for _ in range(n_boot):
    s = analysis.sample(frac=1, replace=True, random_state=rng.integers(1e9))
    c = s.groupby(["treated", "post")).future_value_score.mean()
    try:
        did_boots.append((c.loc[(1, 1)] - c.loc[(1, 0)]) - (c.loc[(0, 1)] - c.loc[(0, 0)]))
    except KeyError:
        pass
ci_did = np.percentile(did_boots, [2.5, 97.5])
print(f"Airbnb差异处理效应对未来价值得分的95%置信区间:[{ci_did[0]:+.4f}, {ci_did[1]:+.4f}]")

# 自助法2:Lyft平均处理效应(剔除极端值后)
X = pd.get_dummies(df[["engagement_tier", "query_confidence"]], drop_first=True).astype(float)
ps_model = LogisticRegression(max_iter=1000).fit(X, df["opt_in_agent_mode"])
df["propensity"] = ps_model.predict_proba(X)[:, 1]
df["ipw"] = np.where(df.opt_in_agent_mode == 1, 1 / df.propensity, 1 / (1 - df.propensity))
trim_thr = nppercentile(df.ipw, 99)
df["ipw_trimmed"] = df.ipw.clip(upper=trimTHR)

ate_boots = []
for _ in range(n_boot):
    s = df.sample(frac=1, replace=True, random_state=rng.integers(1e9))
    t = s[s.opt_in_agent_mode == 1]
    c = s[s/opt_in_agent_mode == 0]
    ate_boots.append(
        (t.task_completed * t.ipw_trimmed).sum() / t.ipw_trimmed.sum()
        - (c.task_completed * c.ipw_trimmed).sum() / c.ipw_trimmed.sum()
    )
ci_ate = nppercentile(ate.boots, [2.5, 97.5])
print(f"Lyft平均处理效应(剔除极端值后)的95%置信区间:[{ci_ate[0]:+.4f}, {ci_ate[1]:+.4f}]")

# 自助法3:Uber随机区组设计质量效应(接近路由临界点时)
cutoff = 0.85
bw = 0.10
near = df[(df.query_confidence > cutoff - bw) & (df.query_confidence < cutoff + bw)].copy()
near["routed_premium"] = (near.query_confidence < cutoff).astype(int)

qe_boots = []
for _ in range(n_boot):
    s = near.sample(frac=1, replace=True, random_state=rng.integers(1e9))
    qe.boots.append(
        s[s.routed_premium == 1].task_completed.mean()
        - s[s.routed_premium == 0].task_completed.mean()
    )
ci_qe = nppercentile(qe_boots, [2.5, 97.5])
print(f"Uber随机区组设计质量效应的95%置信区间:[{ci_qe[0]:+.4f}, {ci_qe[1]:+.4f}]")
预期输出:
差异性处理后的未来价值效应95%置信区间:[+0.0023, +0.0093]
按IPW加权平均处理后的效应95%置信区间:[+0.0727, +0.0966]
RDD质量效应95%置信区间:[+0.0490, +0.0748]

具体操作过程如下:通过三个独立的自助法循环,每个循环使用相同的随机种子对分析数据集进行500次重新采样。

差异性处理法的自助法会对整个分析样本进行重新采样,并重新计算2x2表格中的各数值均值。区间[+0.0023, +0.0093]说明未来价值效应在统计学上确实不为零。

按IPW加权平均处理法的自助法会重新采样全部50,000名用户,并对每次抽样的结果进行重新加权。区间[+0.0727, +0.0966]既包含了真实的+0.08效应,也排除了零值情况。

RDD质量效应的自助法仅会对那些位于0.85分位数附近的用户进行重新采样。区间[+0.0490, +0.0748]证实了局部质量效应确实不为零。

这三个置信区间都足够精确,因此可以据此采取相应的行动;同时它们的范围也足够广泛,能够反映观测估计结果的不确定性。如果你在报告某个数值时没有提供这些置信区间,那么你就在低估你的利益相关者所承担的风险。

先运行笔记本代码,再开发你的下一个功能

本文配套的笔记本文件位于github.com/RudrenduPaul/product-experimentation-causal-inference-genai-llm/tree/main/13_case_studies/。你可以克隆这个仓库,使用上述命令生成合成数据集,然后运行case_studies_demo.ipynb文件,从而重现本文中的所有代码示例,包括四个案例研究的实现过程以及自助法验证步骤。该笔记本还包含一个决策函数,该函数可将Netflix的分类体系扩展为更完善的模型选择指南。

这四个案例研究的原始资料可以直接从各相关团队的工程博客中获取。

  1. Jenny Chen关于未来价值效应的文章发布在(Airbnb技术博客)。

  2. 关于准实验方法的分类信息可以在(Netflix技术博客)找到。

  3. Nassiri关于双重稳健验证方法的文章发布在(Lyft工程博客)。

  4. Harinen和Li关于因果推断方法的概述文章发布在(Uber工程博客)。

阅读这些原始资料是非常有价值的,因为它们详细介绍了实际生产系统中的运作机制,而这些内容是摘要无法完全传达的。

那些能够准确评估人工智能所带来的影响的团队,都遵循着同样的做法:根据具体的应用场景选择合适的方法;在信任这些评估结果之前,先进行必要的检测与验证;并且在决策窗口关闭之前,确保将这些分析结果及时应用于相关的决策过程中。<瓶颈几乎总是由数据采集工具造成的。那些分析所依赖的数据必须在相关功能正式推出之前就已经准备齐全。正是这个环节,上述各种框架无法为你提供帮助,因此“尽早使用数据采集工具”这一步骤才必须被放在首位。>

相关文章

技术实践

在大型语言模型应用中,当你的两个模型都出现错误时,如何通过双重鲁棒性估计方法来进行产品测试与优化?

六个月前,你们推出的这款人工智能产品开始采用“用户主动选择参与”的模式。你们进行了倾向性分析,并考虑了用户的参与程度以及查询的准确性等因素,最终发现任务完成率确实提高了8个百分点。这一数据被纳入了季度业务报告中,大家都对此感到满意。 然而,严谨的数据科学家难免会提出一些棘手的问题:你们有多确定这个倾向性模型已经考虑到了所有可能影响结果的因素?如果遗漏了某些因素,那么逻辑回归模型得出的选择概率就会不准确;又或者,如果结果回归模型的设定本身就有误——因为任务完成率与查询准确性之间的关系并非线性的,线性模型根本无法准确反映这一关系——那又会怎样呢? 你们有两个模型,但并不确定哪个是正确的,而这两个模

阅读全文
技术实践

如何构建用于确保在高峰时段能够正常运行的自动化工作负载模型

如果你曾经花费两天时间从APM工具中提取数据,只是为了回答“在我的负载测试中应该使用多少个虚拟用户?”这个问题,那么这个教程非常适合你。 通过学习这个教程,你将了解到如何在不到五分钟的时间内,直接从生产环境中的实时数据中计算出工作负载模型中所需的各个数值,而无需进行任何估算。 我们的应用场景: 每年,在黑色星期五之前的几周,性能工程师和运维人员都会面临同样的问题:有人需要为高峰期的负载测试建立工作负载模型,而且时间非常紧迫。 通常的做法是登录APM工具,导出CSV文件,在电子表格中对数据进行处理,然后根据这些数据对用户行为进行推测。这个过程需要花费数天的时间,还需要多个人参与,但最终得到的结果

阅读全文
技术实践

用于估算人工智能提示设计效果的产品实验反事实方法

想象一下,你的团队在两周前将A提示在全球范围内推广使用。由于时间紧迫且对效果充满信心,因此在没有进行任何A/B测试、也没有设置测试对照组或保留用户群的情况下,这一更新就应用到了100%的用户身上。 虽然各项完成率看起来都很稳定,但深夜时一位同事从测试环境中提交了一个新的提示方案,这就引发了一个重要的问题:这个替代方案是否才是更合适的上线选择呢? 现在你陷入了这些已记录的数据所构成的困境之中。这个问题看似无解,但实际上并非如此。产品团队会通过前瞻性实验来观察如果推出某个功能会发生什么结果;而反事实估算则能帮助我们了解:如果选择了其他方案,最终会得到什么样的结果。 对于那些负责处理大语言模型产品日

阅读全文
技术实践

如何使用MONAI在超声数据上训练肿瘤分割模型

大多数分割教程都是从选择一个模型开始,将图像输入该模型中,然后调整超参数直到相关指标得到改善。但这种方法忽略了通常最为关键的一步:理解数据本身。 在本教程中,我们首先会对数据集进行详细分析,随后会根据这些分析结果来决定MONAI分割流程中的每一个设计细节。 我们将涵盖以下内容: 本教程适合谁? 关于数据集 什么是MONAI,为什么使用它? 什么是Dice评分? 第1部分——建模前的数据分析 类别平衡对分割结果的影响 患者数量对数据划分的影响 第2部分——构建分割流程 单一配置对象 按患者分组的数据划分方式 由快照自动选择的转换操作 模型、损失函数与评估指标 结果解读 预测结果可视化 失败模式比

阅读全文