Skip to main content

Semiparametric Causal Inference for Right-Censored Outcomes with Many Weak Invalid Instruments

Project description

MAWII-SURV

Semiparametric causal inference for right-censored outcomes with many weak or invalid instruments, powered by the GEL-NOW framework.

PyPI Python License: MIT

MAWII-Surv (MAny Weak and Invalid Instruments for Survival outcomes) implements GEL-NOW: Generalized Empirical Likelihood with Non-Orthogonal and Weak moments. It extends classical GEL to non-orthogonal nuisance settings and allows many weak or invalid IVs under right-censoring.


Table of Contents


Introduction to MAWII-Surv

MAWII-Surv (MAny Weak and Invalid Instruments for Survival outcomes) is a Python package for semiparametric causal inference with right-censored outcomes in the presence of many weak or invalid instruments. The package implements the novel GEL-NOW (Generalized Empirical Likelihood with Non-Orthogonal and Weak moments, or GEL 2.0) framework, which extends classical generalized empirical likelihood to settings where nuisance functions enter non-orthogonally and where instruments may be weak or invalid.

Key features include:

  • Heteroscedasticity-based identification under an accelerated failure time (AFT) model, enabling causal effect estimation even with invalid instruments.

  • Flexible nuisance estimation using modern machine learning methods, including deep neural networks, to capture complex nonlinear structures.

  • Robust inference that explicitly accounts for additional variance from non-orthogonal nuisances, ensuring valid confidence intervals.

  • Diagnostics such as a censoring-adjusted over-identification test to assess instrument validity.

  • Applications to biobank-scale data, with built-in support for analyzing time-to-event outcomes such as disease onset.

With simulation tools, diagnostic functions, and real-data examples, MAWII-Surv provides a user-friendly platform for researchers in statistics, econometrics, epidemiology, and genetics to conduct reliable causal inference from censored survival data

Why MAWII-Surv?

  • Survival + Endogeneity: G-estimation for treatment effects with right-censoring and unmeasured confounding.
  • Many Weak/Invalid IVs: Robust to weak instruments and horizontal pleiotropy.
  • GEL 2.0 (GEL-NOW): Empirical Likelihood (EL), Exponential Tilting (ET), and Continuous Updating (CUE) with theory for non-orthogonal nuisances.
  • Modern ML Nuisances: Deep neural nets (PyTorch), Random Forests, XGBoost, plus classical linear models.
  • Diagnostics: Over-identification test adapted to censoring; standard errors account for censoring-induced variance inflation.

Features

  • Uncensor‐data (mawii_noncensor)
  • Right‐censoring (mawii_censor)
  • Multiple model backends:
    • Neural networks
    • Linear regression
    • Random forests
    • XGBoost
  • Choice of Generalized Empirical Likelihood (GEL) functions:
    • Empirical Tilting (ET)
    • Empirical Likelihood (EL)
    • Continuous Updating Estimator (CUE)

Installation

Install from PyPI:

pip install mawiisurv

Dependencies

Make sure you have the following installed (the minimal compatible versions shown):

  • numpy>=1.19
  • torch>=1.8
  • scipy>=1.5
  • scikit-learn>=0.24
  • xgboost>=1.3
  • numba>=0.53

If you plan to use GPU, please install a CUDA-compatible PyTorch from the official download page before installing this package.


Quick start

A runnable demo is provided below. It simulates both non-censored and right-censored data, fits the DNN + ET specification, and prints the point estimate, standard error, and the over-identification test statistic.

# demo

#  pip install mawiisurv
import numpy as np
import mawiisurv
import torch
import copy
# function input
'''
Main input variables:
    X: (n,p) array, covariates
    Z: (n,m) array, instrumental variables
    A: (n,) array, treatment
    Y: (n,) array, outcome
    censor_delta: (n,) array, censor indicator, 1 for uncensor and 0 for censor
    h: window for local KM estimation, and default setting is 1
    model_types: ['neural_network','linear_regression','random_forest','xgboost'], 4 choices of comparsion models, and default setting is ['neural_network']
    rho_function_names: ['ET','EL','CUE'], GEL functions, and default setting is ['EL']

Other DNN setting: 
    hidden_layers=[50, 50],
    learning_rate=0.0005,
    weight_decay=0.0001,
    batch_size=256,
    dropout_rate=0,
    patience=5,
    epochs=1000,
    validation_split=0.05,
    shuffle=False,
    device='cpu'
'''

# two main functions:
'''
'mawii_noncensor' for complete data
'mawii_censor' for right censor data
'''

# function output
'''
function will return a list of result, including 
    'beta' : estimation of treatment effect
    'se' : estimated standard error
    'test' : overidentification test statistics
'''

# complete data simulation
n = 10000
m = 20
p = 1
beta_0 = 0.4
device = 'cuda:0' if torch.cuda.is_available() else 'cpu'


def generate_data(n=10000, m=10, p=5, beta_0=0.4, h_2=0.2,eta_A=1,censor_rate=0.3, case='case1'):
    random_coefs = np.random.normal(loc=0, scale=1, size=1000)
    
    X = np.random.uniform(-2,2,size=(n,p))
    Z = np.random.uniform(-2,2,size=(n,m))

    gamma = np.sqrt(h_2 / (1.5*m)) * random_coefs[0 : m] 
    delta = np.sqrt(h_2 / (1.5*m)) * random_coefs[m : 2*m]

    epsilon_A = np.random.normal(0, 0.4*(1-h_2), size=n)
    epsilon_Y = np.random.normal(0, 0.4*(1-h_2), size=n)
    

    alpha_case1 = np.zeros(m)
    alpha_case2 = np.sqrt(h_2 / (1.5*m)) * (random_coefs[2*m : 3*m])/2
    alpha_case3 = gamma / 2
    Z_new = copy.deepcopy(Z)
    Z_new = np.cos(Z*2)

    
    if case == "case1":
        tmp = np.random.multinomial(1, [1, 0, 0], size=m)
    elif case == "case2":
        tmp = np.random.multinomial(1, [0.6, 0.2, 0.2], size=m)
    elif case == "case3":
        tmp = np.random.multinomial(1, [0.1, 0.9, 0], size=m)
    elif case == "case4":
        tmp = np.random.multinomial(1, [0.1, 0, 0.9], size=m)
    else:
        raise ValueError("Unknown case provided.")
    alpha = tmp[:, 0] * alpha_case1 + tmp[:, 1] * alpha_case2 + tmp[:, 2] * alpha_case3

    U = np.random.normal(0, 0.6*(1-h_2), size=n)
    A = Z_new @ gamma + U + (1 + Z @ delta)*epsilon_A
    T = beta_0*A  + Z_new @ alpha -U  + epsilon_Y 

    rr = 0
    
    while True:
        C = np.random.uniform( -1+rr,5+rr, size=n)
        censor_delta = np.where(T <= C, 1, 0) 
        if np.mean(1-censor_delta) >=censor_rate+0.03:
            rr = rr + 0.1
        elif np.mean(1-censor_delta)<=censor_rate-0.03:
            rr = rr - 0.1
        else:
             break
            
    Y = np.minimum(T,C)
 
    return X, Z, A, Y, T, censor_delta

X, Z, A, Y, T, censor_delta= generate_data(n=10000, m=20, p=1, beta_0=0.4, h_2=0.2, eta_A=1, censor_rate=0.4, case='case1')


# uncensored data simulation

result_noncensor = mawiisurv.mawii_noncensor(X, Z, A, T, 
                          model_types=['neural_network'], # options:  ['neural_network','linear_regression','random_forest','xgboost'],
                          rho_function_names=['ET'], # options: ['ET','EL','CUE'],
                          device = device)

print(f"DNN+ET BETA: {result_noncensor['neural_network']['ET']['beta']:.3f}")
print(f"DNN+ET SE: {result_noncensor['neural_network']['ET']['se']:.3f}")
print(f"DNN+ET over-identification test: {result_noncensor['neural_network']['ET']['test']:.3f}")


# right-censor data simulation

result_censor = mawiisurv.mawii_censor(X, Z, A, Y, censor_delta, h = 4,
                                           model_types=['neural_network'], # options:  ['neural_network','linear_regression','random_forest','xgboost'],
                                           rho_function_names=['ET'], # options: ['ET','EL','CUE'],
                                          device = device)

print(f"DNN+ET BETA: {result_censor['neural_network']['ET']['beta']:.3f}")
print(f"DNN+ET SE: {result_censor['neural_network']['ET']['se']:.3f}")
print(f"DNN+ET over-identification test: {result_censor['neural_network']['ET']['test']:.3f}")
    

API

mawii_noncensor(
    X, Z, A, Y,
    model_types=['neural_network'],
    rho_function_names=['ET'],
    hidden_layers=[50, 50],
    learning_rate=0.0005,
    weight_decay=0.0001,
    batch_size=256,
    dropout_rate=0,
    patience=5,
    epochs=100,
    validation_split=0.05,
    shuffle=False,
    device='cpu',
) -> dict
mawii_censor(
    X, Z, A, Y, censor_delta, h=1,
    model_types=['neural_network'],
    rho_function_names=['ET'],
    hidden_layers=[50, 50],
    learning_rate=0.0005,
    weight_decay=0.0001,
    batch_size=256,
    dropout_rate=0,
    patience=5,
    epochs=100,
    validation_split=0.05,
    shuffle=False,
    device='cpu',
) -> dict

Arguments

  • X: array of shape n by p, baseline covariates

  • Z: array of shape n by m, instrumental variables

  • A: array of shape n, treatment

  • Y: array of shape n, outcome

  • censor_delta: array of shape n, 1 uncensored and 0 censored, only for mawii_censor

  • h: scalar, window for local Kaplan–Meier in censoring adjustment

  • model_types: list of model backends, choose from neural_network, linear_regression, random_forest, xgboost

  • rho_function_names: list of GEL score types, choose from ET, EL, CUE

  • device: cpu or cuda device string such as cuda:0


Return values:

{
  'neural_network': {
    'ET': {
      'beta': float,    # point estimate
      'se': float,      # standard error
      'test': float     # overidentification test statistic
    },
    'EL': {...},
    'CUE': {...}
  },
  'linear_regression': {...},
  ...
}

Notes

  • We generally recommend ET or EL over CUE under weak identification.

  • Deep NNs tend to be most robust for complex nonlinear nuisances; RF/XGB are strong baselines in moderate dimensions.

  • Under censoring, standard errors include an extra variance component due to estimating the censoring distribution.

Citation:

If you use MAWII-Surv, please cite:

Bu Q., Su W., Zhao X., Liu Z. (2025).
Semiparametric Causal Inference for Right-Censored Outcomes with Many Weak Invalid Instruments.
(manuscript)

BibTeX:

@misc{mawiisurv2025,
  title   = {Semiparametric Causal Inference for Right-Censored Outcomes with Many Weak Invalid Instruments},
  author  = {Bu, Qiushi and Su, Wen and Zhao, Xingqiu and Liu, Zhonghua},
  year    = {2025},
  note    = {Python package: MAWII-Surv},
  howpublished = {\url{https://pypi.org/project/mawiisurv/}}
}

Contributing

Contributions are welcome!
Please use Issues for bug reports and pull requests for code contributions.

License

MIT License — see LICENSE for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mawiisurv-0.7.0.tar.gz (16.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mawiisurv-0.7.0-py3-none-any.whl (15.1 kB view details)

Uploaded Python 3

File details

Details for the file mawiisurv-0.7.0.tar.gz.

File metadata

  • Download URL: mawiisurv-0.7.0.tar.gz
  • Upload date:
  • Size: 16.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.7

File hashes

Hashes for mawiisurv-0.7.0.tar.gz
Algorithm Hash digest
SHA256 c83a39cc77755f24319e61e9deb2a146e2ce435d9dca1e3bdec66aa7c551c089
MD5 4d0bd4ce78b1602d5eaadcaf18f63cd6
BLAKE2b-256 f748efbe5f41ee341dccf29f43b4debd9b7b5c3798deb9c6d98bd1d0fdfb66b9

See more details on using hashes here.

File details

Details for the file mawiisurv-0.7.0-py3-none-any.whl.

File metadata

  • Download URL: mawiisurv-0.7.0-py3-none-any.whl
  • Upload date:
  • Size: 15.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.7

File hashes

Hashes for mawiisurv-0.7.0-py3-none-any.whl
Algorithm Hash digest
SHA256 727546a70ad9a58da58a66337d0643ca3aed7bc9797eebe1abe0b7062c24bce5
MD5 af9bed729c9972967c860670ff66ffd6
BLAKE2b-256 bb703a92b2615b299637d8735c0d61b03bd63533facbad59d3268c1e8fb5eed6

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page