paper2skills Playbook

Instrumental Variables (IV) for Causal Inference with Endogeneity

Skill-IV-Instrumental-Variables · 01-因果推断

causalexperimentforecastingoptimizationpricing广告与投放供应链与补货定价与利润WF-A 智能补货WF-B 广告优化WF-F 动态定价
年化 ROI50万
实现难度⭐⭐⭐☆☆
业务优先级⭐⭐⭐☆☆
业务视角
适用角色增长负责人 / CMO · 数据分析师 · 广告优化师
适用平台Amazon · TikTok Shop · Meta Ads · DTC 独立站
什么情况下用广告预算花了,但不确定哪个渠道真的带来新客;做了大促,不知道销量增长是促销效果还是季节规律
成功是什么样的能区分「真实增量」和「自然购买」,砍掉虚假归因渠道后同等预算 ROI 提升 20-40%
业务痛点
钱花出去了不知道有没有用各渠道报告都说自己贡献最大怎么向老板证明这笔钱值得花

1. 解决的问题

Momcozy 想知道自己产品的价格弹性——价格下降10%,销量会增加多少

2. 核心算法逻辑

核心思想:当解释变量(如价格)与误差项相关时(内生性),直接回归会产生偏误。工具变量法是找一个"只通过影响解释变量来影响结果"的外生变量(工具变量),用它的变异来剥离出解释变量的"干净"部分,从而估计真实的因果效应。

3. 业务应用场景

业务问题:Momcozy 想知道自己产品的价格弹性——价格下降10%,销量会增加多少?但简单回归价格对销量的系数不是弹性,因为价格本身由需求决定(内生性)。

工具变量选择: - 竞争对手价格:竞品涨价会迫使本品调整价格,但竞品价格不直接影响本品销量(排他性) - 汇率波动:目标市场货币对美元的汇率波动影响采购成本,进而影响定价,但汇率不直接影响消费者需求 - 原材料成本冲击:如芯片短缺导致吸奶器电子元件成本上涨

应用流程: 1. 第一阶段:用竞争对手价格 + 汇率预测本品实际售价 $$Price_i = \pi_0 + \pi_1 \cdot CompetitorPrice_i + \pi_2 \cdot ExchangeRate_i + \epsilon_i$$ 2. 检验工具变量强度:计算第一阶段F统计量 3. 第二阶段:用预测价格预测销量 $$Sales_i = \beta_0 + \beta_1 \cdot \hat{Price}_i + \gamma \cdot Controls_i + u_i$$ 4. 计算价格弹性:$\epsilon = \beta_1 \cdot \frac{\bar

4. 输入数据要求

请查看原始代码模板获取输入规格。

5. 输出结果

请查看原始代码模板获取输出规格。

6. 业务价值 / ROI

  • 数据要求:需要找到合理的工具变量(最大的挑战)
  • 技术门槛:中等,2SLS逻辑清晰但工具变量选择需要领域知识
  • 主要挑战:论证排他性约束(说服团队为什么工具变量不直接影响结果)
  • 刚需场景:价格弹性是定价策略的核心输入,但没有IV就无法得到因果弹性
  • 方法成熟:2SLS有100年历史,实现简单
  • 与现有技能互补:DiD处理时间维度,IV处理截面维度,两者覆盖电商因果推断的两大场景

7. 代码模板

代码块数量:1 · 路径:未检测到

"""
Instrumental Variables (IV) — 工具变量法
用于处理内生性问题的因果推断

支持:经典2SLS、弱工具变量检验、异质性IV-DML
"""

import numpy as np
import pandas as pd
from sklearn.linear_model import LinearRegression
from sklearn.ensemble import GradientBoostingRegressor
import warnings
warnings.filterwarnings('ignore')


# ==================== IV 核心实现 ====================

class InstrumentalVariables:
    """工具变量估计器 (2SLS)"""

    def __init__(self):
        self.first_stage_model = None
        self.second_stage_model = None
        self.iv_coef = None
        self.first_stage_f = None
        self.first_stage_r2 = None

    def fit(self, X_endog, Z_iv, Y_outcome, X_controls=None):
        """
        拟合2SLS

        Args:
            X_endog: 内生解释变量 (n_samples,)
            Z_iv: 工具变量 (n_samples, n_iv)
            Y_outcome: 结果变量 (n_samples,)
            X_controls: 控制变量 (n_samples, n_controls) — 可选
        """
        n = len(X_endog)
        X_endog = np.array(X_endog).reshape(-1, 1)
        Z_iv = np.array(Z_iv).reshape(n, -1) if Z_iv.ndim == 1 else np.array(Z_iv)
        Y_outcome = np.array(Y_outcome)

        # ========== 第一阶段:Z → X ==========
        # 特征 = [Z, controls]
        if X_controls is not None:
            X_controls = np.array(X_controls)
            if X_controls.ndim == 1:
                X_controls = X_controls.reshape(-1, 1)
            Z_first = np.column_stack([Z_iv, X_controls])
        else:
            Z_first = Z_iv

        self.first_stage_model = LinearRegression()
        self.first_stage_model.fit(Z_first, X_endog.ravel())

        # 预测 X
        X_pred = self.first_stage_model.predict(Z_first)

        # 第一阶段统计量
        self.first_stage_r2 = self.first_stage_model.score(Z_first, X_endog.ravel())

8. 论文来源

未自动抽取;请查看原始 Skill 卡片。