Use custom propensity_learner on R-learner's first fit#937
Merged
jeongyoonlee merged 1 commit intoJul 9, 2026
Merged
Conversation
The R-learner fit() methods assigned self.model_p = self.propensity_learner after calling _set_propensity_models(), which reads self.model_p to decide whether to use a user-supplied propensity model. On a fresh object model_p did not exist yet, so the first fit silently fell back to the default ElasticNetPropensityModel and ignored propensity_learner. A second fit of the same object then picked it up, so identical calls produced different nuisance estimates depending on fit order. Move the model_p assignment ahead of the propensity-model fitting in BaseRLearner, BaseRClassifier, and XGBRRegressor, and add a regression test. Signed-off-by: Arpit Jain <arpitjain099@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Proposed changes
The R-learner ignores a user-supplied
propensity_learneron the firstfit()of a fresh object. In eachfit()override the lineself.model_p = self.propensity_learnerruns after_set_propensity_models(), but_set_propensity_modelsreadsself.model_p(viahasattr) to decide whether to use the custom propensity model or fall back to the defaultElasticNetPropensityModel. On a new objectmodel_pdoesn't exist yet, so the first fit quietly uses the default and the custom learner is dropped.Because the attribute persists on the object, a second
fit()of the same instance does pick up the custom learner, so the same call gives different nuisance estimates depending on fit order. The fix moves themodel_passignment ahead of the propensity-model fitting in all three affected paths (BaseRLearner,BaseRClassifier,XGBRRegressor).Types of changes
Test plan
test_BaseRLearner_uses_custom_propensity_learner_on_first_fitintests/test_meta_learners.py: it fits a fresh R-learner with a distinctiveElasticNetPropensityModelsubclass and asserts the trainedpropensity_modelis that subclass. It fails onmaster(default ElasticNet is used) and passes with this change.-k "RLearner or RRegressor or RClassifier", 21 tests) passes locally.Checklist