All notable changes to grf
will be documented in this file.
The format is based on Keep a Changelog and this project adheres to Semantic Versioning.
[2.4.0] - 2024-11-15
Fixed
-
IMPORTANT: Make random seed behavior independent of the number of cores the forest is trained with. This fix means code from previous versions will produce slightly different results, even with the same random seed. A global package option
options(grf.legacy.seed)
is added for users who wish to exactly recover past results without reinstalling a previous grf version. #1447
- Respect
num.threads
argument in internal debiasing weights estimation. #1437
- Relax a minimum cluster size requirement in
boot_grf
. #1412
- Ensure input dimensions of covariate matrix X is non-zero. #1408
- Fix minor docstring typos. #1406, #1420, #1443
[2.3.2] - 2024-02-25
Fixed
- Emit an overlap warning in
rank_average_treatment_effect
if evaluation forest treatment propensities get too low/high. #1378
- Make the default TOC plot x-axis label more informative. #1388
- Improve the RATE docstring examples. #1390
- Fix a typo in the TOC docstring. #1395
- Address a ‘lost braces’ docstring Note in latest R CMD CHECK. #1379
[2.3.1] - 2023-10-01
Fixed
- Fix weak instrument warning in
get_scores.instrumental_forest
. #1351
- Add extra input validation to
sample.weights
argument. #1352
[2.3.0] - 2023-05-10
Added
- Add support for a continuous treatment
W
in causal_survival_forest
, mimicking the average partial effect estimand in causal_forest
. #1280
- Add
target.sample = "overlap"
option to best_linear_projection
allowing for estimation with weights equal to e(X)(1 - e(X)). #1258
- Add optional
drop
argument to predict.multi_arm_causal_forest
, predict.multi_regression_forest
, and predict.lm_forest
which drops the singleton dimension in the prediction array in case the forest is fit with only a single outcome. #1271, #1281
- Add column names to the
variance.estimates
matrix when calling predict.multi_arm_causal_forest
, predict.probability_forest
, and predict.lm_forest
. #1272, #1283
Fixed
- Fix missing
num.threads
argument in internal causal_survival_forest
nuisance estimation that would cause some components to utilize all available threads even though the num.threads
arguments specified less. #1267
- Drop C++11 compiler flag in src/Makevars per latest CRAN guidelines. #1305
[2.2.1] - 2022-12-14
Added
- Add
rank_average_treatment_effect.fit
, an optional interface to RATE which allows for user-supplied doubly robust evaluation set scores. #1242
Fixed
- Fix minor docstring example typo in
rank_average_treatment_effect
. #1209
- Move a missing values input check in
rank_average_treatment_effect
. #1212
- Allow factor variables in the covariate matrix
A
passed to best_linear_projection
. #1215
- Fix the “ai1” and “ai2” example DGPs included in
dgps.R
. #1241
[2.2.0] - 2022-08-06
Added
- Add new “linear model” forest
lm_forest
allowing for forest-based estimation of the conditionally linear model Y = c(x) + h_1(x)W_1 + … + h_K(x)W_K at X = x (this generalization nests causal and multi-arm causal forest). As an example, one could use this forest to estimate heterogeneous treatment effects in a regression discontinuity design by setting W_1 to 1{Z >= cutoff} and W_2 = Z, where Z is a running variable and “cutoff” a treatment threshold. #1138
- Add optional
prediction.times
argument to predict.survival_forest
. The new option “times” allows for easier computation of IPCW-type weights. #1139
- Add support for
instrumental_forest
to best_linear_projection
. #1158
Fixed
- Fix optional
failure.times
argument in predict.survival_forest
. This only affects survival_forest
predictions in cases the optional failure.times
contains time points outside the training grid. #1132
- Fix
ll_regression_forest
such that all allowable input types X
work when enable.ll.split = TRUE
. #1198
[2.1.0] - 2022-03-17
Changed (breaking)
IMPORTANT Some of these changes might cause small differences in results compared to previous releases, even if the same random seed is used.
- The optional event grid (
failure.times
) in survival_forest
is now required to be strictly increasing. #1034
- The time values
Y
in survival_forest
are now required to be non-negative. #1058
Added
- Add new feature
rank_average_treatment_effect
(“RATE”) which calculates a scalar metric together with a Targeting Operating Characteristic curve which can be used to assess how well a CATE estimator does in identifying subpopulations which benefit from treatment. #1086
- Add support for survival probability difference estimation with
causal_survival_forest
using new required arguments target
and horizon
. NOTE: this change breaks the experimental API from the previous release and marks a new stable interface. #1055
- Add warning if
multi_arm_causal_forest
is trained with a treatment factor vector W
which contains missing levels. #1039
- Add documentation to
multi_arm_causal_forest
emphasizing that in case multiple outcomes Y
are supplied they should be on the same scale. #1041
- Add documentation note to
survival_forest
emphasizing that the alpha
parameter works as a split constraint on the number of events in child nodes, thus suggesting that if the forest does not split on very low event-rate data lowering this may be useful. #1072
Fixed
- Fix doubly robust scores for
multi_arm_causal_forest
. For forests trained with more than two treatments the doubly robust score construction used for ATE estimation had a typo which could lead to slight under-coverage. #1021
- Allow forest tuning to continue with tuning even when some random parameter draws are inadmissible. This prevents the message “Could not tune forest because some small forest error estimates were NA.” from appearing in some cases. #1067
- For forests requiring estimates of additional nuisance components in summary functions (such as a causal forest with continuous treatment), use the original forest seed when estimating these with a new nuisance forest, avoiding confusion for users who expect the ATE summary functions to produce the exact same result across different invocations. #1070
- Fix sample weighted
average_treatment_effect
for target.sample = c("treated", "control")
in the case the forest is trained without clusters. #1103
- Disable sample weighted
average_treatment_effect
for method = "TMLE"
as these were silently ignored anyways. #1102
- Fix sample weighted
average_treatment_effect
for the rare case when some weights are zero. #1104, #1105
- Remove undocumented legacy “sentinel”
seed = 0
which meant a new random seed was drawn every time. #1093
- Fix documentation notation in
survival_forest
where Y
appeared instead of T
. #1056
[2.0.2] - 2021-07-14
Fixed
- Minor patch release for CRAN Solaris compatibility. #1011
[2.0.0] - 2021-06-22
Changed (breaking)
IMPORTANT Some of these changes might cause small differences in results compared to previous releases, even if the same random seed is used.
- Unify the interface to ATE-type estimators: 1)
average_treatment_effect
is the new entry point for all ATE summaries, meaning average_late
and average_partial_effect
is removed. 2) This function now targets population-type quantities for all forests, meaning some confidence intervals may be slightly wider than before. 3) Some ad-hoc normalization schemes are removed, but can be manually specified through the debiasing.weights
argument. #723
- Remove all
tune_***_forest
functions, restricting the tuning interface to the pre-existing tune.parameters
argument in all tuning-compatible forests. #790
- Remove the optional
orthog.boosting
argument in causal_forest
, since tailored m(x)
estimates can be passed through the existing Y.hat
argument. #892
- Remove support for sparse
X
in forest training (as the internal C++ implementation did not leverage sparsity in X
beyond storage mode). To train a forest with sparse data do forest(as.matrix(X), Y)
. #939
- Remove
custom_forest
. For a template for getting started with a custom GRF estimator, consider using an existing simple forest, like regression_forest
as a scaffold. For more details see the GRF developing document. #870
- Rename
get_sample_weights
to get_forest_weights
. #894
- Return
quantile_forest
predictions in the predictions
attribute of a new output list in order to conform with the GRF convention of returning point predictions as predict(forest)$predictions
. #822
- Change the way optional sample weights (passed through the
sample.weights
argument) interact with the GRF forest weights. When forming estimates according to (2) and (3) in the GRF paper, sample weights now enter through alpha_i(x)’ = alpha_i(x) * sample.weight_i. In addition, causal_forest
and instrumental_forest
now take sample weights into account in the relabeling step (#752). Sample weights are also explicitly disabled for local linear forests (#841). #796
Added
- Add
causal_survival_forest
for estimating conditional average treatment effects with right-censored data. #660
- Add
multi_arm_causal_forest
, an extension of causal_forest
to multiple categorial treatments W
, and optionally multiple responses Y
. #748
- Add
multi_regression_forest
for estimating several conditional mean functions mu_i(x) = E[Y_i | X = x]. #742
- Add
probability_forest
for estimating conditional class probabilities P[Y = k | X = x]. #711
- Add
get_scores
returning doubly robust scores for a number of estimands. #732
- Add
get_leaf_node
utility function which given a GRF tree object returns the leaf node a test sample falls into. #739
- Add a
vcov.type
standard error option to test_calibration
and best_linear_projection
. On large datasets with clusters, setting this option to "HC0"
or "HC1"
will significantly speed up the computation.
- Add optional Nelson-Aalen estimates of the survival function. #685
- Add a docstring example to
survival_forest
on how to calculate concordance with the optional survival
package. #956
Fixed
- Fix the output name in
average_treatment_effect
when method = "TMLE"
. #864
- Fix pointwise variance estimates in (the very unlikely) zero variance case. #907
- Fix
survival_forest
test set predictions with sample weights. #969
- Make forest tuning respect the
seed
argument when drawing a random grid of parameter values, allowing reproducibility without an explicit set.seed
before training. #704
[1.2.0] - 2020-06-04
Added
- Add Survival Forest functionality. #647
- Add optional argument
debiasing.weights
to average_partial_effect
. #637
- Add optional
compute.oob.predictions
argument to Quantile Forest. #665
Fixed
- Fix a performance regression in DefaultPredictionCollector. This improves prediction speed for forests such as Quantile Forest. #650
- Predict with training quantiles by default. #668
[1.1.0] - 2020-03-12
Changed (breaking)
IMPORTANT These changes might cause small differences in results compared to previous releases, even if the same random seed is used.
- Performance improvement: remove an unnecessary splitting rule loop. Note: this may cause very small differences from earlier versions because it changes the order in which potential splits are evaluated. #592
Added
- Add support for missing values in the covariates X with MIA splitting. #612
- Add local linear splitting. An experimental option
enable.ll.split
fits a forest with splits based on ridge residuals as opposed to standard CART splits. Note: local linear tuning does not take the new splits into account. #603
- Add sample weighted splitting. Previously, if a user passed
sample.weights
, they would only be used for prediction. Now they are used in splitting as well. Note: this will make results fitted with sample weights different from previous versions. #590
Fixed
- Remove a superfluous predict call in tuning. #597
- Fix
average_partial_effect
calibration in case of low variation W.hat. #611
- Update
best_linear_projection
to handle non-binary treatment. #615
- Add an error message in case summary functions are passed a subset that refers to too few distinct units. #629
[1.0.1] - 2019-12-05
Fixed
- Fix a bug where the nodes of the printed trees would be in the wrong order. #587
[1.0.0] - 2019-11-29
Changed (breaking)
IMPORTANT These changes might cause small differences in results compared to previous releases, even if the same random seed is used.
- Rename
prune.empty.leaves
to honesty.prune.leaves
. #529
- Simplify the forest tuning API. Previously, tuning was enabled during forest training by setting the option
tune.parameters=TRUE
. All relevant parameters were tuned by default, except for those that were explicitly passed to the forest (like min.node.size=100
). Now the option tune.parameters
directly takes a list of parameters to tune, for example tune.parameters=c("min.node.size", "mtry")
, or tune.parameters="all"
. #534
- Change how data points are weighted in cluster-robust estimation. Previously, each cluster was given equal weight when training the forest and computing estimates. Now, each point is weighted equally regardless of its cluster size. This behavior can be controlled through a new option
equalize.cluster.weights
, which defaults to FALSE
but can be set to TRUE
to match the old behavior of weighting clusters equally. The old option samples.per.cluster
has been removed. #545.
Added
- Improve the performance of
get_tree
. #528
- Add support for tuning instrumental forests (currently marked ‘experimental’). #547
- Introduce optimizations to tree splitting. These improvements lead to a small speed-up in forest training. #560, #561
- Add
best_linear_projection
, a doubly robust estimate of the best linear projection of the conditional average treatment effect onto a set of covariates. #574
- Speed up forest prediction by introducing additional parallelization. #566, #576
Fixed
- Allow the data matrix
X
to be a data frame. #540
- When merging forests, validate that all forests were trained on the same data. #543
- Fix a major performance issue in
get_sample_weights
. #578
[0.10.4] - 2019-09-01
Changed (breaking)
IMPORTANT These changes might cause small differences in results compared to previous releases, even if the same random seed is used.
- Ensure forest estimates are consistent across platforms. #469, #492
- The number of trees used for orthogonalization was changed from
min(500, num.trees)
to max(50, num.trees / 4)
. #439
- Solidify the parameter tuning procedure. If the optimization procedure fails, or if the selected parameters perform worse than defaults, we now return default parameters instead. #455
- Introduce parameters
honesty.fraction
and prune.empty.leaves
to help mitigate the effect of honesty on small datasets, and tune over them when tune.parameters=TRUE
. #456, #484
Added
- Add variance estimates for local linear forests. #442
- Include information about leaf samples in plotting and printing. #460
- Add example of saving a plot with DiagrammeRsvg. #478
- Support average effect estimates for instrumental forests (ACLATE). #490
Fixed
- Performance improvements to forest training. #514
[0.10.3] - 2019-06-01
Changed (breaking)
IMPORTANT These changes might cause small differences in results compared to previous releases, even if the same random seed is used.
- Fix two bugs in the termination criterion for tree splitting.
- Remove the purity condition on outcomes during splitting. For all tree types, we used to stop splitting if all outcomes in a leaf are the same. This behavior does not make sense for causal forests (which incorporates other observations besides the outcome), so it was removed. #362
- Stop splitting if the objective can no longer be improved. With this change,
causal_forest
may split slightly less aggressively. #415
Added
- In out-of-bag prediction, return the Monte Carlo error alongside the debiased error. #327
- Allow for passing a factor for the
cluster
parameter. #329
- Support taking a union of forests through the
merge_forests
method. #347
- Include a summary of the parameter tuning procedure in the forest object. #419
- Add experimental support for sample weighting to regression, causal, and instrumental forests. #376, #418
- Add an experimental new forest type
boosted_regression_forest
, which applies boosting to regression forests. Allow boosting to be used during orthogonalization through the orthog.boosting
parameter. #388
Fixed
- Improve input data validation. #354, #378, #430
- Improve the
test_calibration
function by switching to one-sided p-values. #370
- For custom forests, fix a bug in OOB prediction where the train and tests datasets were switched. #372
- Decrease memory usage during training and out-of-bag prediction. #408, #412
- Allow roxygen to autogenerate the
NAMESPACE
file. #423, #428
[0.10.2] - 2018-11-23
Added
- Add support for confidence intervals in local linear regression forests.
Changed
- Allow samples_per_cluster to be larger than smallest cluster size.
Fixed
- Make sure average effect estimation doesn’t error on data with a single feature.
- Fix a bug in local linear prediction where the penalty wasn’t properly calculated.
- Fix two issues in causal forest tuning that could lead to unstable results.
- Ensure that the ATE and APE functions correctly account for cluster membership.
[0.10.1] - 2018-09-23
Added
- Add basic support for tree plotting (through the
plot
method).
- Add the method
test_calibration
, which performs an omnibus test for presence of heterogeneity via calibration.
- For local linear regression forests, add support for selecting the value of
ll.lambda
through cross-validation.
- Introduce a training option
honesty.fraction
that can be used to specify the fraction of data that should be used in selecting splits vs. performing estimation. Note that this parameter is only relevant when honesty is enabled (the default).
- Start a practical guide to the
grf
algorithm (https://github.com/grf-labs/grf/blob/master/REFERENCE.md).
- In
average_treatment_effect
and average_partial_effect
, add an option subset
to support estimating the treatment effect over a subsample of the data.
Fixed
- Fix a bug in random sampling where features listed earlier in the data matrix were more likely to be selected for splitting.
- Make sure that the sample indices returned in
get_tree
are 1-indexed, as opposed to 0-indexed.
[0.10.0] - 2018-05-08
Added
- Replace the local.linear option with linear.correction.variables, which allows for a subset of variables to be considered during local linear regression.
- Update causal_forest interface to allow user to specify Y.hat and W.hat. Note that these options supercede the precompute.nuisance parameter, which has been removed. To recreate the behavior of precompute.nuisance = TRUE, NULL can be provided for Y.hat and W.hat, and for precompute.nuisance = FALSE, Y.hat and W.hat should be 0.
- Add a causal forest example with variable selection and parameter tuning.
Changed
- Adjust the defaults for the causal forest tuning algorithm.
Fixed
- Prevent tuning down to a min.node.size of 0.
[0.9.6] - 2018-04-13
Added
- Debiased error criterion for measuring the out-of-bag accuracy of a forest using only a few trees.
- Automated tuning via cross-validation for regression and causal forests.
- Estimation of average partial effects with a continuous treatment.
- Overlap-weighted average treatment effects.
- Cluster-robust standard errors for regression and causal forests, and average effect estimates (contributed by @lminer).
- Locally linear prediction in regression forests (contributed by @rinafriedberg).
- Regularize splits in causal/instrumental forests via a variance penalty.
Changed
- Avoid causal forest leaves with all treated or all control samples (controlled via stabilize.splits = TRUE).
- Store in-bag rather than out-of-bag samples to save memory.
- Only support sampling with replacement (as some features are ambiguously defined with bootstrapping).
Fixed
- Bug in IV CI construction (#209).
[0.9.5] - 2018-01-04
Added
- Create a simple method for variable importance based on split frequency and depth.
- Add support for sparse data matrices of type ‘dgCMatrix’.
Changed
- Use RcppEigen for the R package, as opposed to the eigen source.
Fixed
- Fix a few places where we were still using the old default for mtry. This issue was causing poor performance for even moderately large numbers of features.
[0.9.4] - 2017-11-25
Changed
- Update the default for mtry to sqrt(p) + 20.
Fixed
- Fix an issue where split_frequencies fails when p = 1.
- Use a Solaris-compatible version of std::sqrt.
[0.9.3] - 2017-07-20
Fixed
- Fix an out of bounds error when there are fewer trees than threads.
- Fix a bug in the get_tree function where the same tree was always returned.
[0.9.2] - 2017-07-06
Added
- Add an experimental regularized version of the regression splitting rule.
Fixed
- Several bugfixes for CRAN compatibility.
[0.9.1] - 2017-06-27
Added
- Add a regression.splits option to quantile forests to allow emulating the approach in Meinhausen (2006).
[0.9.0] - 2017-06-25
First official (beta) release. The package currently supports
- standard regression forests
- causal, instrumental, and quantile forests
- confidence intervals for causal, instrumental, and regression forests
- training ‘honest’ versions of the above forests