Skip to content

Commit 6907b0f

Browse files
rstzcopybara-github
authored andcommitted
[YDF] Fail on distributed tuning cross-validation
This option was exposed, but didn't actually use cross-validation. Now it fails with an error. PiperOrigin-RevId: 985124213
1 parent 9bdcce8 commit 6907b0f

3 files changed

Lines changed: 57 additions & 28 deletions

File tree

‎yggdrasil_decision_forests/learner/hyperparameters_optimizer/hyperparameters_optimizer.cc‎

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -207,8 +207,24 @@ HyperParameterOptimizerLearner::TrainWithStatusImpl(
207207
const dataset::VerticalDataset& train_dataset,
208208
std::optional<std::reference_wrapper<const dataset::VerticalDataset>>
209209
valid_dataset) const {
210+
// The effective configuration is the user configuration + the default value +
211+
// the automatic configuration (if enabled) + the copy of the non-specified
212+
// training configuration field from the learner to the sub-learner (e.g. copy
213+
// of the label name).
214+
model::proto::TrainingConfig effective_config;
215+
model::proto::TrainingConfigLinking config_link;
216+
RETURN_IF_ERROR(GetEffectiveConfiguration(train_dataset.data_spec(),
217+
&effective_config, &config_link));
218+
const proto::HyperParametersOptimizerLearnerTrainingConfig& spe_config =
219+
effective_config.GetExtension(proto::hyperparameters_optimizer_config);
220+
210221
if (deployment().execution_case() ==
211222
model::proto::DeploymentConfig::ExecutionCase::kDistribute) {
223+
if (spe_config.evaluation().has_cross_validation()) {
224+
return absl::InvalidArgumentError(
225+
"The cross-validation evaluation of the hyper-parameter candidates "
226+
"is not supported with distributed training");
227+
}
212228
// Export the dataset to file and run the training on file.
213229
return TrainFromFileOnMemoryDataset(train_dataset, valid_dataset);
214230
}
@@ -222,17 +238,6 @@ HyperParameterOptimizerLearner::TrainWithStatusImpl(
222238
"deployment configs.");
223239
}
224240

225-
// The effective configuration is the user configuration + the default value +
226-
// the automatic configuration (if enabled) + the copy of the non-specified
227-
// training configuration field from the learner to the sub-learner (e.g. copy
228-
// of the label name).
229-
model::proto::TrainingConfig effective_config;
230-
model::proto::TrainingConfigLinking config_link;
231-
RETURN_IF_ERROR(GetEffectiveConfiguration(train_dataset.data_spec(),
232-
&effective_config, &config_link));
233-
const proto::HyperParametersOptimizerLearnerTrainingConfig& spe_config =
234-
effective_config.GetExtension(proto::hyperparameters_optimizer_config);
235-
236241
// Initialize the learner with the base hyperparameters.
237242
ASSIGN_OR_RETURN(auto base_learner,
238243
BuildBaseLearner(spe_config, /*for_tuning=*/true));
@@ -345,6 +350,12 @@ HyperParameterOptimizerLearner::TrainWithStatusImpl(
345350
const proto::HyperParametersOptimizerLearnerTrainingConfig& spe_config =
346351
effective_config.GetExtension(proto::hyperparameters_optimizer_config);
347352

353+
if (spe_config.evaluation().has_cross_validation()) {
354+
return absl::InvalidArgumentError(
355+
"The cross-validation evaluation of the hyper-parameter candidates "
356+
"is not supported with distributed training");
357+
}
358+
348359
// Initialize the remote workers.
349360
ASSIGN_OR_RETURN(auto manager, CreateDistributeManager(spe_config));
350361

@@ -652,7 +663,8 @@ HyperParameterOptimizerLearner::SearchBestHyperparameterInProcess(
652663

653664
LOG(INFO) << "Start local tuner with "
654665
<< spe_config.optimizer().parallel_trials()
655-
<< " parallel trial(s), each with " << deployment().num_threads()
666+
<< " parallel trial(s), each with "
667+
<< spe_config.base_learner_deployment().num_threads()
656668
<< " thread(s)";
657669
async_evaluator.StartWorkers();
658670

@@ -822,7 +834,12 @@ absl::StatusOr<double> HyperParameterOptimizerLearner::EvaluateCandidateLocally(
822834
*base_learner, train_dataset,
823835
fold_generator, evaluation_options,
824836
spe_config.base_learner_deployment()));
837+
break;
825838
}
839+
default:
840+
return absl::InvalidArgumentError(absl::StrCat(
841+
"Unsupported evaluation source: ",
842+
static_cast<int>(spe_config.evaluation().source_case())));
826843
}
827844

828845
ASSIGN_OR_RETURN(const auto score, EvaluationToScore(spe_config, evaluation));

‎yggdrasil_decision_forests/learner/hyperparameters_optimizer/hyperparameters_optimizer.proto‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,8 @@ message Evaluation {
8484
// Uses the self reported model evaluation e.g. validation score or OOB
8585
// evaluation. Default.
8686
SelfEvaluation self_model_evaluation = 3;
87-
// Uses cross-validation on the training dataset.
87+
// Uses cross-validation on the training dataset. Not supported for
88+
// distributed training.
8889
CrossValidation cross_validation = 4;
8990
}
9091

‎yggdrasil_decision_forests/learner/hyperparameters_optimizer/hyperparameters_optimizer_test.cc‎

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -167,17 +167,40 @@ TEST_F(OnAdult, RandomTuner_MemoryDataset_LocalTraining) {
167167
}
168168

169169
TEST_F(OnAdult, RandomTuner_MemoryDataset_LocalTrainingCrossValidation) {
170-
SetLocalTraining();
170+
SetTrainConfig("RANDOM", "random", 10);
171171
auto* spe_config = train_config_.MutableExtension(
172172
hyperparameters_optimizer_v2::proto::hyperparameters_optimizer_config);
173-
spe_config->mutable_evaluation()->mutable_cross_validation();
174-
SetTrainConfig("RANDOM", "random", 10);
173+
spe_config->mutable_evaluation()
174+
->mutable_cross_validation()
175+
->mutable_fold_generator()
176+
->set_num_folds(3);
177+
178+
SetLocalTraining();
175179
TrainAndEvaluateModel();
176180
EXPECT_GE(metric::Accuracy(evaluation_), 0.865);
177181
EXPECT_LT(metric::LogLoss(evaluation_), 0.30);
178182
EXPECT_EQ(model_->hyperparameter_optimizer_logs()->steps_size(), 10);
179183
}
180184

185+
TEST_F(OnAdult, CrossValidationWithDistributedTraining_Fail) {
186+
SetTrainConfig("RANDOM", "random", 5);
187+
auto* spe_config = train_config_.MutableExtension(
188+
hyperparameters_optimizer_v2::proto::hyperparameters_optimizer_config);
189+
spe_config->mutable_evaluation()->mutable_cross_validation();
190+
191+
SetDistributedTraining();
192+
PrepareDataset();
193+
194+
std::unique_ptr<model::AbstractLearner> learner;
195+
ASSERT_OK(model::GetLearner(train_config_, &learner, deployment_config_));
196+
197+
auto model_or = learner->TrainWithStatus(train_dataset_);
198+
EXPECT_FALSE(model_or.ok());
199+
EXPECT_EQ(model_or.status().code(), absl::StatusCode::kInvalidArgument);
200+
EXPECT_THAT(model_or.status().message(),
201+
HasSubstr("not supported with distributed training"));
202+
}
203+
181204
TEST_F(OnAdult, RandomTuner_FileDataset_LocalTraining) {
182205
pass_training_dataset_as_path_ = true;
183206
SetLocalTraining();
@@ -195,18 +218,6 @@ TEST_F(OnAdult, RandomTuner_MemoryDataset_DistributedTraining) {
195218
EXPECT_EQ(model_->hyperparameter_optimizer_logs()->steps_size(), 25);
196219
}
197220

198-
TEST_F(OnAdult, RandomTuner_MemoryDataset_DistributedTrainingCrossValidation) {
199-
SetDistributedTraining();
200-
auto* spe_config = train_config_.MutableExtension(
201-
hyperparameters_optimizer_v2::proto::hyperparameters_optimizer_config);
202-
spe_config->mutable_evaluation()->mutable_cross_validation();
203-
SetTrainConfig("RANDOM", "random", 10);
204-
TrainAndEvaluateModel();
205-
EXPECT_GE(metric::Accuracy(evaluation_), 0.865);
206-
EXPECT_LT(metric::LogLoss(evaluation_), 0.30);
207-
EXPECT_EQ(model_->hyperparameter_optimizer_logs()->steps_size(), 10);
208-
}
209-
210221
TEST_F(OnAdult, RandomTuner_FileDataset_DistributedTraining) {
211222
SetDistributedTraining();
212223
pass_training_dataset_as_path_ = true;

0 commit comments

Comments
 (0)