55 bool standardize_outcome =
true;
58 int cutpoint_grid_size = 100;
59 std::vector<FeatureType> feature_types;
60 LinkFunction link_function = LinkFunction::Identity;
61 OutcomeType outcome_type = OutcomeType::Continuous;
64 bool keep_burnin =
false;
67 double a_sigma2_global = 0.0;
68 double b_sigma2_global = 0.0;
69 double sigma2_global_init = 1.0;
70 bool sample_sigma2_global =
true;
73 int num_trees_mean = 200;
74 double alpha_mean = 0.95;
75 double beta_mean = 2.0;
76 int min_samples_leaf_mean = 5;
77 int max_depth_mean = -1;
78 bool leaf_constant_mean =
true;
79 int leaf_dim_mean = 1;
80 bool exponentiated_leaf_mean =
false;
81 int num_features_subsample_mean = 0;
82 double a_sigma2_mean = 3.0;
83 double b_sigma2_mean = -1.0;
84 double sigma2_mean_init = -1.0;
85 std::vector<double> var_weights_mean;
86 std::vector<double> sigma2_leaf_mean_matrix;
87 bool sample_sigma2_leaf_mean =
false;
88 std::vector<int> sweep_update_indices_mean;
89 MeanLeafModelType mean_leaf_model_type = MeanLeafModelType::GaussianConstant;
90 int num_classes_cloglog = 0;
91 double cloglog_leaf_prior_shape = 2.0;
92 double cloglog_leaf_prior_scale = 2.0;
93 double cloglog_cutpoint_0 = 0.0;
96 int num_trees_variance = 0;
97 double leaf_prior_calibration_param = 1.5;
98 double shape_variance_forest = -1.0;
99 double scale_variance_forest = -1.0;
100 double variance_forest_leaf_init = -1.0;
101 double alpha_variance = 0.5;
102 double beta_variance = 2.0;
103 int min_samples_leaf_variance = 5;
104 int max_depth_variance = -1;
105 bool leaf_constant_variance =
true;
106 int leaf_dim_variance = 1;
107 bool exponentiated_leaf_variance =
true;
108 int num_features_subsample_variance = 0;
109 std::vector<double> var_weights_variance;
110 std::vector<int> sweep_update_indices_variance;
113 bool has_random_effects =
false;
114 BARTRFXModelSpec rfx_model_spec = BARTRFXModelSpec::Custom;
115 std::vector<double> rfx_working_parameter_mean_prior;
116 std::vector<double> rfx_group_parameter_mean_prior;
117 std::vector<double> rfx_working_parameter_cov_prior;
118 std::vector<double> rfx_group_parameter_cov_prior;
119 double rfx_variance_prior_shape = 1.0;
120 double rfx_variance_prior_scale = 1.0;
127 std::vector<double> mean_forest_predictions_train;
130 std::vector<double> variance_forest_predictions_train;
133 std::vector<double> mean_forest_predictions_test;
136 std::vector<double> variance_forest_predictions_test;
139 std::vector<double> global_error_variance_samples;
142 std::vector<double> leaf_scale_samples;
145 std::unique_ptr<ForestContainer> mean_forests;
148 std::unique_ptr<ForestContainer> variance_forests;
151 std::vector<double> cloglog_cutpoint_samples;
154 std::vector<double> rfx_predictions_train;
157 std::vector<double> rfx_predictions_test;
160 std::unique_ptr<RandomEffectsContainer> rfx_container;
161 std::unique_ptr<LabelMapper> rfx_label_mapper;
170 void AppendToJson(nlohmann::json& obj)
const {
172 nlohmann::json forests = nlohmann::json::object();
174 if (mean_forests !=
nullptr) {
175 forests.emplace(
"mean_forest", mean_forests->to_json());
178 if (variance_forests !=
nullptr) {
179 forests.emplace(
"variance_forest", variance_forests->to_json());
186 obj[
"forests"] = forests;
187 obj[
"num_forests"] = num_forests;
189 nlohmann::json parameters = nlohmann::json::object();
190 if (!global_error_variance_samples.empty()) {
191 parameters.emplace(
"sigma2_global_samples", global_error_variance_samples);
193 if (!leaf_scale_samples.empty()) {
194 parameters.emplace(
"sigma2_leaf_samples", leaf_scale_samples);
196 if (!cloglog_cutpoint_samples.empty()) {
197 parameters.emplace(
"cloglog_cutpoint_samples", cloglog_cutpoint_samples);
199 if (!parameters.empty()) {
200 obj[
"parameters"] = parameters;
203 obj[
"outcome_mean"] = y_bar;
204 obj[
"outcome_scale"] = y_std;
205 obj[
"num_samples"] = num_samples;
207 int num_random_effects = 0;
208 nlohmann::json rfx = nlohmann::json::object();
209 if (rfx_container !=
nullptr && rfx_label_mapper !=
nullptr) {
210 rfx.emplace(
"random_effect_container_0", rfx_container->to_json());
211 rfx.emplace(
"random_effect_label_mapper_0", rfx_label_mapper->to_json());
212 rfx.emplace(
"random_effect_groupids_0", rfx_label_mapper->Keys());
213 num_random_effects = 1;
215 obj[
"random_effects"] = rfx;
216 obj[
"num_random_effects"] = num_random_effects;
220 void FromJson(
const nlohmann::json& obj) {
222 if (obj.contains(
"forests")) {
223 const nlohmann::json& forests = obj.at(
"forests");
224 if (forests.contains(
"mean_forest")) {
225 mean_forests = std::make_unique<ForestContainer>(0, 0,
false,
false);
226 mean_forests->from_json(forests.at(
"mean_forest"));
228 if (forests.contains(
"variance_forest")) {
229 variance_forests = std::make_unique<ForestContainer>(0, 0,
false,
false);
230 variance_forests->from_json(forests.at(
"variance_forest"));
234 if (obj.contains(
"parameters")) {
235 const nlohmann::json& parameters = obj.at(
"parameters");
236 if (parameters.contains(
"sigma2_global_samples")) {
237 global_error_variance_samples = parameters.at(
"sigma2_global_samples").get<std::vector<double>>();
239 if (parameters.contains(
"sigma2_leaf_samples")) {
240 leaf_scale_samples = parameters.at(
"sigma2_leaf_samples").get<std::vector<double>>();
242 if (parameters.contains(
"cloglog_cutpoint_samples")) {
243 cloglog_cutpoint_samples = parameters.at(
"cloglog_cutpoint_samples").get<std::vector<double>>();
247 if (obj.contains(
"num_random_effects") && obj.at(
"num_random_effects").get<
int>() > 0) {
248 rfx_container = std::make_unique<RandomEffectsContainer>();
249 rfx_label_mapper = std::make_unique<LabelMapper>();
250 rfx_container->from_json(obj.at(
"random_effects").at(
"random_effect_container_0"));
251 rfx_label_mapper->from_json(obj.at(
"random_effects").at(
"random_effect_label_mapper_0"));
254 if (obj.contains(
"outcome_mean")) y_bar = obj.at(
"outcome_mean").get<
double>();
255 if (obj.contains(
"outcome_scale")) y_std = obj.at(
"outcome_scale").get<
double>();
256 if (obj.contains(
"num_samples")) num_samples = obj.at(
"num_samples").get<
int>();
265 if (y_bar != other.y_bar || y_std != other.y_std) {
266 Log::Fatal(
"Cannot merge BARTSamples with different outcome standardization");
268 if (rfx_container !=
nullptr && other.rfx_container !=
nullptr) {
269 if (rfx_container->NumComponents() != other.rfx_container->NumComponents() ||
270 rfx_container->NumGroups() != other.rfx_container->NumGroups()) {
271 Log::Fatal(
"Cannot merge BARTSamples with different random effects structure");
273 if (rfx_label_mapper->Keys() != other.rfx_label_mapper->Keys()) {
274 Log::Fatal(
"Cannot merge BARTSamples with different random effects label mapping");
276 if (rfx_label_mapper->Map() != other.rfx_label_mapper->Map()) {
277 Log::Fatal(
"Cannot merge BARTSamples with different random effects label mapping");
287 if ((!global_error_variance_samples.empty() && other.global_error_variance_samples.empty()) ||
288 (global_error_variance_samples.empty() && !other.global_error_variance_samples.empty())) {
289 Log::Fatal(
"Cannot merge BARTSamples objects: global error variance samples present in one chain but not the other");
291 global_error_variance_samples.insert(global_error_variance_samples.end(),
292 other.global_error_variance_samples.begin(), other.global_error_variance_samples.end());
293 if ((!leaf_scale_samples.empty() && other.leaf_scale_samples.empty()) ||
294 (leaf_scale_samples.empty() && !other.leaf_scale_samples.empty())) {
295 Log::Fatal(
"Cannot merge BARTSamples objects: leaf scale samples present in one chain but not the other");
297 leaf_scale_samples.insert(leaf_scale_samples.end(),
298 other.leaf_scale_samples.begin(), other.leaf_scale_samples.end());
299 if ((!cloglog_cutpoint_samples.empty() && other.cloglog_cutpoint_samples.empty()) ||
300 (cloglog_cutpoint_samples.empty() && !other.cloglog_cutpoint_samples.empty())) {
301 Log::Fatal(
"Cannot merge BARTSamples objects: cloglog cutpoint samples present in one chain but not the other");
303 cloglog_cutpoint_samples.insert(cloglog_cutpoint_samples.end(),
304 other.cloglog_cutpoint_samples.begin(), other.cloglog_cutpoint_samples.end());
305 num_samples += other.num_samples;
308 std::vector<double> OutcomePredictionsTrain()
const {
309 std::vector<double> predictions(num_train * num_samples, 0.0);
310 for (
int i = 0; i < num_train * num_samples; ++i) {
311 if (!mean_forest_predictions_train.empty()) {
312 predictions[i] += mean_forest_predictions_train[i];
314 if (!rfx_predictions_train.empty()) {
315 predictions[i] += rfx_predictions_train[i];
321 std::vector<double> OutcomePredictionsTest()
const {
322 std::vector<double> predictions(num_test * num_samples, 0.0);
323 for (
int i = 0; i < num_test * num_samples; ++i) {
324 if (!mean_forest_predictions_test.empty()) {
325 predictions[i] += mean_forest_predictions_test[i];
327 if (!rfx_predictions_test.empty()) {
328 predictions[i] += rfx_predictions_test[i];