Targets Module#

The targets module defines what quantity you want to estimate. A target is a functional H(θ) that maps the structural parameters to a scalar.

Overview#

Target

Formula

Use Case

AverageParameter

E[θ_j]

Average treatment effect

AME

E[p(1-p)·β]

Marginal effect on probability

DoseResponse

E[G(θ, t̃)]

Average predicted outcome at treatment level

Profit

E[t̃ · G(θ, t̃)]

Expected revenue at price level

TailProbability

E[P(Y > c | θ, t̃)]

Exceedance/risk probability

ConditionalVariance

E[Var(Y | θ, t̃)]

Model-implied outcome variance

MultiTreatmentATE

E[G(θ, t) - G(θ, t₀)]

Combinatorial treatment effect

ChoiceProbabilityTarget

P(Y=j | W, X)

Multinomial choice probability

MultinomialAME

∂P(Y=j)/∂x_{jk}

Multinomial marginal effect

CustomTarget

User-defined h(x,θ,t̃)

Any custom functional


Built-in Targets#

AverageParameter#

The default target: average of a specific parameter across the population.

from deep_inference.targets import AverageParameter

# Target: E[β(X)] where β is the second parameter (index=1)
target = AverageParameter(param_index=1, theta_dim=2)

Formula:

H(θ) = (1/n) Σ θ_j(x_i)

Jacobian (closed-form):

∂H/∂θ = [0, ..., 1/n, ..., 0]  (1 at position j)

AME (Average Marginal Effect)#

For logit models, the marginal effect on probability (not log-odds).

from deep_inference.targets import AME

# Target: E[p(1-p)·β] evaluated at t_tilde
target = AME(param_index=1, model_type='logit')

Formula (logit):

H(θ, t̃) = (1/n) Σ σ'(α_i + β_i·t̃) · β_i
        = (1/n) Σ p_i(1-p_i) · β_i

Where p_i = σ(α_i + β_i·t̃).

Jacobian (closed-form for logit):

∂H/∂α = p(1-p)(1-2p)·β / n
∂H/∂β = p(1-p)[1 + (1-2p)·β·t̃] / n

DoseResponse#

Average predicted outcome at a given treatment level — the fundamental counterfactual target.

from deep_inference.targets import DoseResponse

# Target: E[σ(α + β·t̃)] at treatment level t̃=1.0
target = DoseResponse(model_type='logit')

Formula (logit):

H(θ, ) = σ(α + β·t̃)

Jacobian (closed-form):

∂H/∂α = p(1-p)
∂H/∂β = p(1-p)·t̃

Where p = σ(α + β·t̃). Supports logit, linear, and poisson model types.

Usage:

from deep_inference import inference
result = inference(Y, T, X, model='logit', target='dose_response', t_tilde=1.0)

Reference: Colangelo & Lee (2026, JBES)

Profit#

Expected revenue per consumer at a given price level: price × purchase probability.

from deep_inference.targets import Profit

target = Profit(model_type='logit')

Formula (logit):

H(θ, t̃) = t̃ · σ(α + β·t̃)

Jacobian (closed-form):

∂H/∂α = t̃·p(1-p)
∂H/∂β = t̃·p(1-p)·t̃

Usage:

result = inference(Y, T, X, model='logit', target='profit', t_tilde=2.0)

Reference: Dubé & Misra (2023, JPE)

TailProbability#

Probability that the outcome exceeds a threshold: P(Y > c | θ, t̃).

from deep_inference.targets import TailProbability

# P(Y > 5 | Poisson rate) at exposure level t̃=1.0
target = TailProbability(threshold=5, model_type='poisson')

Formula (Poisson):

H(θ, t̃) = 1 - Σ_{k=0}^{c} e^{-λ}·λ^k/k!   where λ = exp(α + β·t̃)

Formula (logit, c=0):

H(θ, ) = σ(α + β·t̃)    (identical to DoseResponse)

Formula (linear/Gaussian):

H(θ, ) = 1 - Φ((c - μ)/σ)   where μ = α + β·t̃

Closed-form Jacobian for logit and linear; autodiff for Poisson.

Reference: Melnychuk & Feuerriegel (2026, ICLR)

ConditionalVariance#

Model-implied variance of outcomes — captures heterogeneity in risk across covariates.

from deep_inference.targets import ConditionalVariance

target = ConditionalVariance(model_type='logit')

Formula (logit):

H(θ, ) = p(1-p)   where p = σ(α + β·t̃)

Jacobian (closed-form):

∂H/∂α = p(1-p)(1-2p)
∂H/∂β = p(1-p)(1-2p)·t̃

Usage:

result = inference(Y, T, X, model='logit', target='conditional_variance', t_tilde=0.0)

Reference: Melnychuk & Feuerriegel (2026, ICLR)

MultiTreatmentATE#

Average treatment effect for combinatorial experiments with multiple binary treatments.

from deep_inference.targets import MultiTreatmentATE
from deep_inference.models.combinatorial import CombinatorialModel

model = CombinatorialModel(n_treatments=3, link='gen_sigmoid_ii')
target = MultiTreatmentATE(
    model=model,
    treatment=[1, 0, 1],   # Apply treatments 1 and 3
    control=[0, 0, 0],     # vs no treatment
)

Formula:

H(θ) = G(θ, t) - G(θ, t₀)

Where G is the structural link function from CombinatorialModel. Jacobian computed via autodiff.

Reference: Ye et al. (2025, Management Science)


ChoiceProbabilityTarget#

For multinomial logit models: probability of choosing a specific alternative.

from deep_inference.targets.choice_probability import ChoiceProbabilityTarget

# P(Y=j | W, X) for alternative j=1
target = ChoiceProbabilityTarget(
    alternative=1,        # Which alternative (0-indexed)
    n_alternatives=3,     # Total alternatives J
    n_attributes=2        # Attributes per alternative K
)

Formula:

H = P(Y=j|W,X) = softmax(V)[j]
V_j = alpha_j + x'_j * beta

Jacobian (closed-form):

∂P_j/∂alpha_m = P_{m+1}(delta_{j,m+1} - P_j)
∂P_j/∂beta_k = P_j(x̃_{jk} - x̄_pk)

Where \(\bar{x}_{pk} = \sum_j P_j x_{jk}\) is the probability-weighted mean attribute.

MultinomialAME#

Average Marginal Effect for multinomial logit: how a unit change in attribute \(k\) affects the probability of choosing alternative \(j\).

from deep_inference.targets.choice_probability import MultinomialAME

# dP(Y=1)/dx_{1,0}: effect of attribute 0 on probability of alternative 1
target = MultinomialAME(
    alternative=1,        # Which alternative
    attribute=0,          # Which attribute
    n_alternatives=3,     # Total alternatives J
    n_attributes=2        # Attributes per alternative K
)

Formula:

∂P_j/∂x_{jk} = beta_k * P_j * (1 - P_j)

This generalizes the familiar binary logit AME to the multinomial context.


Custom Targets#

Define any target function and the Jacobian is computed via autodiff.

CustomTarget#

from deep_inference.targets import CustomTarget
import torch

def my_target(x, theta, t_tilde):
    """
    Custom target function.

    Args:
        x: Covariates (unused for average targets)
        theta: (theta_dim,) parameter vector
        t_tilde: Evaluation point for treatment

    Returns:
        Scalar value
    """
    alpha, beta = theta[0], theta[1]
    return torch.sigmoid(alpha + beta * t_tilde)

target = CustomTarget(h_fn=my_target)

Example: Average Prediction#

import torch
from deep_inference import inference

def avg_prediction(x, theta, t_tilde):
    """E[P(Y=1|T=t̃)] = E[σ(α + β·t̃)]"""
    return torch.sigmoid(theta[0] + theta[1] * t_tilde)

result = inference(
    Y, T, X,
    model='logit',
    target_fn=avg_prediction,
    t_tilde=0.0  # Prediction at T=0
)

Example: Counterfactual Comparison#

def treatment_effect(x, theta, t_tilde):
    """E[P(Y=1|T=1) - P(Y=1|T=0)]"""
    alpha, beta = theta[0], theta[1]
    p1 = torch.sigmoid(alpha + beta * 1.0)
    p0 = torch.sigmoid(alpha + beta * 0.0)
    return p1 - p0

result = inference(
    Y, T, X,
    model='logit',
    target_fn=treatment_effect
)

Target Protocol#

All targets implement this interface:

class Target(Protocol):
    def h(self, x: Tensor, theta: Tensor, t_tilde: Tensor) -> Tensor:
        """Compute target value for a single observation."""
        ...

    def jacobian(self, x: Tensor, theta: Tensor, t_tilde: Tensor) -> Tensor:
        """Compute ∂h/∂θ. Falls back to autodiff if not implemented."""
        ...

Implementing Custom Targets#

from deep_inference.targets import BaseTarget
import torch

class MyTarget(BaseTarget):
    def h(self, x, theta, t_tilde):
        # Your target computation
        return theta[0] ** 2 + theta[1] * t_tilde

    def jacobian(self, x, theta, t_tilde):
        # Optional: closed-form Jacobian (faster than autodiff)
        return torch.tensor([2 * theta[0], t_tilde])

Using Targets with inference()#

Built-in Target Strings#

# Average beta (log-odds for logit)
result = inference(Y, T, X, model='logit', target='beta')

# Average marginal effect
result = inference(Y, T, X, model='logit', target='ame', t_tilde=0.0)

Custom Target Functions#

def my_target(x, theta, t_tilde):
    return theta[0] + theta[1] * t_tilde

result = inference(Y, T, X, model='logit', target_fn=my_target, t_tilde=1.0)

Autodiff Jacobian#

When you provide a custom target function, the package automatically computes the Jacobian via PyTorch autodiff:

# Internally, this happens:
theta.requires_grad_(True)
h_value = target_fn(x, theta, t_tilde)
jacobian = torch.autograd.grad(h_value, theta)[0]

This enables arbitrary differentiable targets without manual derivatives.