-
Notifications
You must be signed in to change notification settings - Fork 0
Feat/update interface #83
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 7 commits
12eee88
7c189f6
a979b30
c2887bd
a3631ae
6c13af9
163d053
3b3b6e9
a287e57
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -24,28 +24,46 @@ def compute_estimates_att( | |||||||||||||||||||
| Y0_hat: np.ndarray, | ||||||||||||||||||||
| Y1_hat: np.ndarray, | ||||||||||||||||||||
| Yhat: np.ndarray, | ||||||||||||||||||||
| stabilized: bool = False, | ||||||||||||||||||||
| clip_percentile: float = 1, | ||||||||||||||||||||
| ) -> Tuple[np.ndarray, np.ndarray]: | ||||||||||||||||||||
| """ | ||||||||||||||||||||
| Compute updated outcome estimates for ATT using a one-step TMLE targeting step. | ||||||||||||||||||||
| """ | ||||||||||||||||||||
| # Estimate the fluctuation parameter epsilon using a logistic regression: | ||||||||||||||||||||
| H = compute_clever_covariate_att(A, ps, stabilized=stabilized) | ||||||||||||||||||||
| H = compute_clever_covariate_att(A, ps, clip_percentile=clip_percentile) | ||||||||||||||||||||
| epsilon = estimate_fluctuation_parameter(H, Y, Yhat) | ||||||||||||||||||||
|
|
||||||||||||||||||||
| # --- Step 2: Define the CORRECT, separate update terms --- | ||||||||||||||||||||
| # This is the part that was incorrect in your new code. We revert to the logic | ||||||||||||||||||||
| # from your old implementation. | ||||||||||||||||||||
| p_treated = np.mean(A == 1) | ||||||||||||||||||||
| if ( | ||||||||||||||||||||
| p_treated == 0 | ||||||||||||||||||||
| ): # Should be caught by compute_clever_covariate_att but good practice | ||||||||||||||||||||
| return Y1_hat, Y0_hat | ||||||||||||||||||||
|
|
||||||||||||||||||||
| # The update term for the treated group is always the same | ||||||||||||||||||||
| # The update term for the potential outcome under treatment, Q(1,W). | ||||||||||||||||||||
| # This is a scalar value applied to everyone's Y1_hat. | ||||||||||||||||||||
| update_term_1 = epsilon * (1.0 / p_treated) | ||||||||||||||||||||
|
|
||||||||||||||||||||
| # The update term for the control group depends on stabilization | ||||||||||||||||||||
| if stabilized: | ||||||||||||||||||||
| # Stabilized update term for controls | ||||||||||||||||||||
| update_term_0 = -epsilon * (ps * (1 - p_treated) / (p_treated * (1 - ps))) | ||||||||||||||||||||
| else: | ||||||||||||||||||||
| # Unstabilized update term for controls | ||||||||||||||||||||
| update_term_0 = -epsilon * (ps / (p_treated * (1 - ps))) | ||||||||||||||||||||
| # The update term for the potential outcome under control, Q(0,W). | ||||||||||||||||||||
| # This is a vector of values applied to everyone's Y0_hat. | ||||||||||||||||||||
| # We must re-calculate the weight component here. | ||||||||||||||||||||
| # For theoretical consistency, if ps were clipped to find H, they should be clipped here too. | ||||||||||||||||||||
|
|
||||||||||||||||||||
| weight_component = ps / (p_treated * (1 - ps)) | ||||||||||||||||||||
|
|
||||||||||||||||||||
| if clip_percentile < 1: | ||||||||||||||||||||
| control_mask: np.ndarray = A == 0 | ||||||||||||||||||||
| if control_mask.sum() > 0: | ||||||||||||||||||||
| control_weights = weight_component[control_mask] | ||||||||||||||||||||
| threshold = np.percentile(control_weights, clip_percentile * 100) | ||||||||||||||||||||
| # Clip the component for ALL subjects based on the threshold from controls | ||||||||||||||||||||
| weight_component = np.clip(weight_component, a_min=None, a_max=threshold) | ||||||||||||||||||||
|
|
||||||||||||||||||||
| update_term_0 = -epsilon * weight_component | ||||||||||||||||||||
|
|
||||||||||||||||||||
| # --- Step 3: Apply the separate updates to the potential outcome models --- | ||||||||||||||||||||
| Q_star_1 = expit(logit(Y1_hat) + update_term_1) | ||||||||||||||||||||
| Q_star_0 = expit(logit(Y0_hat) + update_term_0) | ||||||||||||||||||||
|
Comment on lines
+67
to
69
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Avoid logit(0) / logit(1) -> inf; clip Y1_hat/Y0_hat before logit This will otherwise produce inf/NaN updates. Apply: - Q_star_1 = expit(logit(Y1_hat) + update_term_1)
- Q_star_0 = expit(logit(Y0_hat) + update_term_0)
+ eps = 1e-6
+ Y1_c = np.clip(Y1_hat, eps, 1 - eps)
+ Y0_c = np.clip(Y0_hat, eps, 1 - eps)
+ Q_star_1 = expit(logit(Y1_c) + update_term_1)
+ Q_star_0 = expit(logit(Y0_c) + update_term_0)📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||
|
|
||||||||||||||||||||
|
|
@@ -59,14 +77,14 @@ def compute_tmle_att( | |||||||||||||||||||
| Y0_hat: np.ndarray, | ||||||||||||||||||||
| Y1_hat: np.ndarray, | ||||||||||||||||||||
| Yhat: np.ndarray, | ||||||||||||||||||||
| stabilized: bool = False, | ||||||||||||||||||||
| clip_percentile: float = 1, | ||||||||||||||||||||
| ) -> dict: | ||||||||||||||||||||
| """ | ||||||||||||||||||||
| Estimate the Average Treatment Effect on the Treated (ATT) using TMLE, | ||||||||||||||||||||
| with optional weight stabilization for the control group. | ||||||||||||||||||||
| with optional clipping for the control group. | ||||||||||||||||||||
| """ | ||||||||||||||||||||
| Q_star_1, Q_star_0 = compute_estimates_att( | ||||||||||||||||||||
| A, Y, ps, Y0_hat, Y1_hat, Yhat, stabilized=stabilized | ||||||||||||||||||||
| A, Y, ps, Y0_hat, Y1_hat, Yhat, clip_percentile=clip_percentile | ||||||||||||||||||||
| ) | ||||||||||||||||||||
|
|
||||||||||||||||||||
| # The final ATT parameter is the mean difference within the treated population | ||||||||||||||||||||
|
|
||||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.