Skip to content

Decouple from dowhy internals & adopt new econml/dowhy features (follow-up to #338) #339

Description

@ZmeiGorynych

Follow-up to the econml 0.16 / dowhy 0.14 upgrade (#338). That PR was intentionally behavior-preserving; this issue tracks the deferred modernization and feature-adoption work.

1. Decouple from dowhy internals

The bump kept CausalTune's existing coupling to dowhy internals and only adapted it. Durable-decoupling items:

  • Migrate EconML dispatch off string method_name. CausalTune dispatches via causal_model.estimate_effect(method_name="backdoor.econml.dml.LinearDML", …), which dowhy ≥0.13 deprecates (we currently just silence the warning in causaltune/__init__.py). Note CausalModel.estimate_effect unconditionally overwrites method_params["econml_estimator"] with the string, so the only instance-based path is to bypass it and call dowhy's functional estimate_effect(data, treatment, outcome, identifier_name, estimator=<Econml adapter instance>, …). Moderate effort + core-path test coverage; removes the deprecation for good.
  • Reduce reliance on private attributes. shap.py / visualizer.py read econml's estimator._input_names["feature_names"]; scoring.py reads _effect_modifier_names / _treatment_value. Introduce a thin, documented adapter surface instead of reaching into privates.
  • Reconsider the effect_tt base-class monkey-patch and effect_stderr. dowhy 0.14's Econml adapter now natively provides effect_tt / apply_multitreatment / effect_inference. Consider subclassing the adapter (or a dedicated estimator wrapper) rather than patching CausalEstimator.
  • Custom-estimator plumbing. DoWhyWrapper still constructs CausalEstimate by hand and does not call super().__init__. Consider aligning it with dowhy 0.14's estimator lifecycle to reduce future breakage.
  • Forward control_value to custom estimators' fit (Codex, deferred from Upgrade econml to 0.16.0 and dowhy to 0.14 (numpy 2, Python 3.10–3.12) #338). dowhy 0.14 passes control_value only to estimate_effect, so DoWhyWrapper.fit constructs the inner estimator with control_value=0. Harmless today (control is ~always 0), but should be threaded through for non-zero-control datasets.

2. Adopt new capabilities

Evaluate and, where they fit the AutoML loop, adopt:

  • dowhy (0.10 → 0.14): doubly-robust estimator; refutation-based scoring / faster refuters as first-class model-selection signals; DRtester-style validation; generalized adjustment criterion for automatic adjustment-set selection; GCM missing-data support.
  • econml (0.14 → 0.16): policy learning; new / updated CATE estimators; RScorer improvements; updated inference (effect_inference / BootstrapInference).

3. Broaden estimator coverage

  • The experimental backdoor.propensity_score_weighting estimator is excluded by default and its effect_tt scoring path is not covered; decide whether to support or drop it.
  • Revisit OrthoForest large-dataset handling now that dependencies are current.

4. Python 3.13

  • Raise the ceiling to Python 3.13 once econml / numba / the rest of the stack publish 3.13-compatible wheels (the bump caps at <3.13).

Notes / gotchas discovered during the bump

  • dcor ≥0.7 changed pairwise_distances(A, B) to return shape (len(B), len(A)) (transposed vs. psw_joint_weights); fixed in psw_energy_distance but worth an audit of any pairwise-distance usage added later.
  • sklearn 1.6 strictly enforces feature-name order between fit/predict — the propensity scoring path had a fit/predict column-list mismatch (fixed in Upgrade econml to 0.16.0 and dowhy to 0.14 (numpy 2, Python 3.10–3.12) #338). Watch for the same pattern elsewhere.
  • numpy 2 removed numpy.distutils and np.trapz; the stack now caps pandas <3 and scikit-learn <1.7, driven by FLAML / numba / econml ceilings.
  • Several dataset loaders fetch from third-party URLs that are periodically dead (NHEFS host now serves HTML); test_datasets skips on download failure.

Basis: docs/followup_decouple_and_features.md (kept local in the PR branch).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions