crabbymetrics
  • Home
  • API
    • API Overview
    • Regression And GLMs
    • Survival / Event-Time
    • Causal Inference And Panels
    • Hypothesis Testing And Utilities
    • Transforms
    • Estimation Interfaces
  • Binding Crash Course
  • Regression And GLMs
    • OLS
    • ABC OLS
    • Anytime-Valid Confidence Sequences
    • Ridge
    • Bagged Polynomial Regression
    • Fixed Effects OLS
    • ElasticNet
    • Logit
    • Multinomial Logit
    • Poisson
    • MLE Prediction Interface
    • Survival / Recurrent Events
    • GMM
    • FTRL
    • MEstimator Poisson
  • Causal Inference
    • Balancing Weights
    • EPLM
    • Average Derivative
    • Double ML And AIPW
    • Richer Regression
    • TwoSLS
    • Synthetic Control
    • Synthetic DID
    • Horizontal Panel Ridge
    • Matrix Completion
    • Interactive Fixed Effects
    • Staggered Panel Event Study
    • Joint Hypothesis Tests
  • Transforms
    • PCA And Kernel Basis
  • Ablations
    • Variance Estimators
    • Semiparametric Estimator Comparisons
    • Two-Period Semiparametric DID
    • Bridging Finite And Superpopulation
    • Panel Estimator DGP Comparisons
    • Same Root Panel Case Studies
    • Randomized Sketching And Least Squares
  • Optimization
    • Optimizers
    • GMM With Optimizers
  • Ding: First Course
    • Overview And TOC
    • Ch 1 Correlation And Simpson
    • Ch 2 Potential Outcomes
    • Ch 3 CRE And Fisher RT
    • Ch 4 CRE And Neyman
    • Ch 9 Bridging Finite And Superpopulation
    • Ch 11 Propensity Score
    • Ch 12 Double Robust ATE
    • Ch 13 Double Robust ATT
    • Ch 21 Experimental IV
    • Ch 23 Econometric IV
    • Ch 27 Mediation

On this page

  • 1 Where it fits
  • 2 Calibration system and numerical objective
  • 3 Diagnostics and inference
  • 4 Performance and numerical behavior
  • 5 Python API
  • 6 Minimal example
  • 7 summary() contract

BalancingWeights

Calibration weights for covariate balance

from _api_doc_utils import *

1 Where it fits

Group: Causal inference

BalancingWeights chooses weights for a source sample so weighted source covariate means match a target sample:

\[ \sum_i w_i x_i / \sum_i w_i \approx \sum_j q_j x_j / \sum_j q_j. \]

The objective can be quadratic or entropy-like, with optional lower/upper bounds and ridge stabilization.

2 Calibration system and numerical objective

Let \(\bar x_T\) be the optionally weighted target mean and define calibration rows

\[ z_i=(1,\ x_i-\bar x_T)'. \]

Weights are normalized implicitly by solving \(Z'w=e_1\). For entropy calibration, the dual map is

\[ w_i(\beta)= \begin{cases} \exp(z_i'\beta), & \text{without baseline weights},\\ q_i\exp(z_i'\beta-1), & \text{with normalized baseline }q_i, \end{cases} \]

clipped to the configured box when the bounded phase is needed. For quadratic calibration it is

\[ w_i(\beta)= \begin{cases} z_i'\beta, & \text{without baseline weights},\\ q_i(1+z_i'\beta), & \text{with baseline }q_i, \end{cases} \]

again clipped to the weight box. Thus the objective name selects the primal calibration geometry and corresponding dual weight map; it is not the literal function passed to the optimizer.

For allowed L2 imbalance \(\delta\), define

\[ s(\beta_{-0}) = \begin{cases} \delta\,\beta_{-0}/\|\beta_{-0}\|_2,&\|\beta_{-0}\|_2>0,\\ 0,&\text{otherwise}. \end{cases} \]

The numerical solver minimizes

\[ \frac12\|r(\beta)\|_2^2, \qquad r(\beta)=Z'w(\beta)-e_1+(0,s(\beta_{-0})')'. \]

Gauss-Newton uses the analytic residual Jacobian with a small \(10^{-8}\) normal-equation ridge and backtracking. Automatic mode tries Gauss-Newton first and falls back to BFGS only when needed. Entropy fits begin with relaxed bounds and rerun with clipping if the first solution violates the requested box.

3 Diagnostics and inference

There is no outcome model, treatment-effect estimand, standard error, or covariance calculation. The fitted object returns normalized weights, original-scale mean differences, effective sample size

\[ \mathrm{ESS}=\frac{1}{\sum_i w_i^2}, \]

the dual coefficient, and solver diagnostics. A successful fit must satisfy calibration residual tolerance, weight sum and bounds, and the L2 mean-difference tolerance.

With autoscaling, covariates are min-max scaled using source-sample minima and ranges before solving. The final success check also compares the unscaled mean-difference norm to the same L2 tolerance. Consequently, success can be false even when the scaled calibration system converged; the reported original-scale mean differences should be inspected directly.

4 Performance and numerical behavior

For \(n\) source rows and \(p\) covariates, each residual/Jacobian construction forms dense weighted cross-products with about \(O(np^2)\) work and \(O(np+p^2)\) storage; the Gauss-Newton system costs up to \(O(p^3)\). BFGS fallback adds repeated residual and Jacobian evaluations. Tight box constraints or an infeasible balance tolerance can leave a finite set of weights with success false rather than raising. Constant source columns are mapped to zero under autoscaling, and target values outside the source range are not clipped.

5 Python API

Constructor: cm.BalancingWeights

Use fit(covariates, target_covariates, baseline_weights=None, target_weights=None). get_weights() returns the fitted source weights. summary() reports balance diagnostics, the dual coefficients, effective sample size, and solver status.

print(inspect.signature(cm.BalancingWeights))
(objective='quadratic', solver='auto', autoscale=False, min_weight=0.0, max_weight=1.0, l2_norm=0.0, max_iterations=200, tolerance=1e-08)
cls = cm.BalancingWeights
display(HTML(html_table(["Public method"], public_methods(cls))))
Public method
fit(self, /, covariates, target_covariates, baseline_weights=None, target_weights=None)
get_weights(self, /)
summary(self, /)

6 Minimal example

rng = np.random.default_rng(10)
x0 = rng.normal(size=(180, 3))
x1 = rng.normal(loc=np.array([0.4, -0.2, 0.1]), size=(80, 3))
model = cm.BalancingWeights(objective='quadratic', max_iterations=500)
model.fit(x0, x1)
print(model.summary()['mean_diff'])
print(model.summary()['effective_sample_size'])
print(model.get_weights()[:5])
[1.11022302e-16 5.55111512e-17 1.17961196e-16]
155.1166258737379
[0.00415802 0.00646452 0.00614945 0.00537598 0.00450626]

7 summary() contract

The table below is generated by fitting the live class in this repository and then inspecting summary(). Shapes are shown because most values are plain NumPy arrays or scalars.

rng = np.random.default_rng(110)
x0 = rng.normal(size=(80, 3))
x1 = rng.normal(loc=np.array([0.4, -0.2, 0.1]), size=(40, 3))
model = cm.BalancingWeights()
model.fit(x0, x1)
summary = model.summary()
display(HTML(html_table(["summary() key", "shape"], summary_shape_rows(summary))))
summary() key shape
weights (80,)
beta (4,)
objective ()
solver ()
success ()
nit ()
criterion ()
residual_norm ()
weight_sum ()
weighted_mean (3,)
target_mean (3,)
mean_diff (3,)
l2_diff ()
max_abs_diff ()
effective_sample_size ()
min_weight ()
max_weight ()
l2_norm ()