From 0de44e7006590611df88dc26bcc54f37af255c57 Mon Sep 17 00:00:00 2001 From: Richard Stotz Date: Tue, 7 Nov 2023 04:34:24 -0800 Subject: [PATCH] [PYDF] Add support for hyperparameter templates PiperOrigin-RevId: 580133998 --- .../port/python/ydf/learner/BUILD | 1 + .../python/ydf/learner/hyperparameters.py | 38 ++++ .../port/python/ydf/learner/learner_test.py | 16 ++ .../specialized_learners_pre_generated.py | 166 +++++++++++++++++- .../ydf/learner/wrapper/wrapper_generator.bzl | 1 + .../ydf/learner/wrapper/wrapper_generator.cc | 139 +++++++++------ .../ydf/learner/wrapper/wrapper_test.cc | 51 ++++++ 7 files changed, 356 insertions(+), 56 deletions(-) diff --git a/yggdrasil_decision_forests/port/python/ydf/learner/BUILD b/yggdrasil_decision_forests/port/python/ydf/learner/BUILD index 9949206e..5be8e0fa 100644 --- a/yggdrasil_decision_forests/port/python/ydf/learner/BUILD +++ b/yggdrasil_decision_forests/port/python/ydf/learner/BUILD @@ -93,6 +93,7 @@ py_library( srcs = ["specialized_learners_pre_generated.py"], deps = [ ":generic_learner", + ":hyperparameters", ":tuner", "//ydf/dataset", "//ydf/dataset:dataspec", diff --git a/yggdrasil_decision_forests/port/python/ydf/learner/hyperparameters.py b/yggdrasil_decision_forests/port/python/ydf/learner/hyperparameters.py index 64b6a4f2..84aa3894 100644 --- a/yggdrasil_decision_forests/port/python/ydf/learner/hyperparameters.py +++ b/yggdrasil_decision_forests/port/python/ydf/learner/hyperparameters.py @@ -13,6 +13,8 @@ # limitations under the License. """Utility functions for YDF Hyperparameters.""" +from collections.abc import Mapping +import dataclasses from typing import Dict, Union from yggdrasil_decision_forests.model import hyperparameter_pb2 @@ -69,3 +71,39 @@ def dict_to_generic_hyperparameter( else: raise ValueError(f"Invalid value {value} for parameter {key}") return generic_hps + + +@dataclasses.dataclass +class HyperparameterTemplate(Mapping): + """A named and versioned set of hyper-parameters. + + List of hyper-parameter sets that outperforms the default hyper-parameters + (either generally or in specific scenarios). A template is also a mapping of + hyperparameters and may be used with the double star operator. + + Usage example: + + ```python + templates = ydf.GradientBoostedTreesLearner.hyperparameter_templates() + better_default = templates["better_defaultv1"] + # Apply the parameters of the template on the learner. + learner = ydf.GradientBoostedTreesLearner(label, **better_default) + ``` + """ + + name: str + version: int + parameters: HyperParameters + description: str + + def __iter__(self): + for key in self.parameters.keys(): + yield key + + def __len__(self): + return len(self.parameters) + + def __getitem__(self, item): + if isinstance(self.parameters, dict) and item in self.parameters: + return self.parameters[item] + return None diff --git a/yggdrasil_decision_forests/port/python/ydf/learner/learner_test.py b/yggdrasil_decision_forests/port/python/ydf/learner/learner_test.py index b22716ad..4e61e3cd 100644 --- a/yggdrasil_decision_forests/port/python/ydf/learner/learner_test.py +++ b/yggdrasil_decision_forests/port/python/ydf/learner/learner_test.py @@ -620,6 +620,22 @@ def test_predict_iris(self): row_sums, np.ones(predictions.shape[0]), decimal=5 ) + def test_better_default_template(self): + ds = toy_dataset() + label = "label" + templates = ( + specialized_learners.GradientBoostedTreesLearner.hyperparameter_templates() + ) + self.assertIn("better_defaultv1", templates) + better_defaultv1 = templates["better_defaultv1"] + learner = specialized_learners.GradientBoostedTreesLearner( + label=label, **better_defaultv1 + ) + self.assertEqual( + learner.hyperparameters["growing_strategy"], "BEST_FIRST_GLOBAL" + ) + _ = learner.train(ds) + class LoggingTest(parameterized.TestCase): diff --git a/yggdrasil_decision_forests/port/python/ydf/learner/specialized_learners_pre_generated.py b/yggdrasil_decision_forests/port/python/ydf/learner/specialized_learners_pre_generated.py index 43536e81..6910da7a 100644 --- a/yggdrasil_decision_forests/port/python/ydf/learner/specialized_learners_pre_generated.py +++ b/yggdrasil_decision_forests/port/python/ydf/learner/specialized_learners_pre_generated.py @@ -30,7 +30,7 @@ compilation. """ -from typing import Optional +from typing import Dict, Optional from yggdrasil_decision_forests.dataset import data_spec_pb2 from yggdrasil_decision_forests.learner import abstract_learner_pb2 @@ -38,6 +38,7 @@ from ydf.dataset import dataspec from ydf.dataset import dataset from ydf.learner import generic_learner +from ydf.learner import hyperparameters from ydf.learner import tuner as tuner_lib @@ -68,6 +69,13 @@ class RandomForestLearner(generic_learner.GenericLearner): print(model.summary()) ``` + Hyperparameters are configured to give reasonable results for typical + datasets. Hyperparameters can also be modified manually (see descriptions) + below or by applying the hyperparameter templates available with + `RandomForestLearner.hyperparameter_templates()` (see this function's + documentation for + details). + Attributes: label: Label of the dataset. The label column should not be identified as a feature in the `features` parameter. @@ -450,6 +458,7 @@ def __init__( "uplift_split_score": uplift_split_score, "winner_take_all": winner_take_all, } + data_spec_args = dataspec.DataSpecInferenceArgs( columns=dataspec.normalize_column_defs(features), include_all_columns=include_all_columns, @@ -491,6 +500,57 @@ def capabilities(cls) -> abstract_learner_pb2.LearnerCapabilities: support_monotonic_constraints=False, ) + @classmethod + def hyperparameter_templates( + cls, + ) -> Dict[str, hyperparameters.HyperparameterTemplate]: + r"""Hyperparameter templates for this Learner. + + Hyperparameter templates are sets of pre-defined hyperparameters for easy + access to different variants of the learner. Each template is a mapping to a + set of hyperparameters and can be applied directly on the learner. + + Usage example: + ```python + templates = ydf.RandomForestLearner.hyperparameter_templates() + better_defaultv1 = templates["better_defaultv1"] + # Print a description of the template + print(better_defaultv1.description) + # Apply the template's settings on the learner. + learner = ydf.RandomForestLearner(label, **better_defaultv1) + ``` + + Returns: + Dictionary of the available templates + """ + return { + "better_defaultv1": hyperparameters.HyperparameterTemplate( + name="better_default", + version=1, + description=( + "A configuration that is generally better than the default" + " parameters without being more expensive." + ), + parameters={"winner_take_all": True}, + ), + "benchmark_rank1v1": hyperparameters.HyperparameterTemplate( + name="benchmark_rank1", + version=1, + description=( + "Top ranking hyper-parameters on our benchmark slightly" + " modified to run in reasonable time." + ), + parameters={ + "winner_take_all": True, + "categorical_algorithm": "RANDOM", + "split_axis": "SPARSE_OBLIQUE", + "sparse_oblique_normalization": "MIN_MAX", + "sparse_oblique_num_projections_exponent": 1.0, + }, + ), + } + + class HyperparameterOptimizerLearner(generic_learner.GenericLearner): r"""Hyperparameter Optimizer learning algorithm. @@ -507,6 +567,13 @@ class HyperparameterOptimizerLearner(generic_learner.GenericLearner): print(model.summary()) ``` + Hyperparameters are configured to give reasonable results for typical + datasets. Hyperparameters can also be modified manually (see descriptions) + below or by applying the hyperparameter templates available with + `HyperparameterOptimizerLearner.hyperparameter_templates()` (see this + function's documentation for + details). + Attributes: label: Label of the dataset. The label column should not be identified as a feature in the `features` parameter. @@ -628,6 +695,7 @@ def __init__( "pure_serving_model": pure_serving_model, "random_seed": random_seed, } + data_spec_args = dataspec.DataSpecInferenceArgs( columns=dataspec.normalize_column_defs(features), include_all_columns=include_all_columns, @@ -669,6 +737,21 @@ def capabilities(cls) -> abstract_learner_pb2.LearnerCapabilities: support_monotonic_constraints=False, ) + @classmethod + def hyperparameter_templates( + cls, + ) -> Dict[str, hyperparameters.HyperparameterTemplate]: + r"""Hyperparameter templates for this Learner. + + This learner currently does not provide any hyperparameter templates, this + method is provided for consistency with other learners. + + Returns: + Empty dictionary. + """ + return {} + + class GradientBoostedTreesLearner(generic_learner.GenericLearner): r"""Gradient Boosted Trees learning algorithm. @@ -692,6 +775,13 @@ class GradientBoostedTreesLearner(generic_learner.GenericLearner): print(model.summary()) ``` + Hyperparameters are configured to give reasonable results for typical + datasets. Hyperparameters can also be modified manually (see descriptions) + below or by applying the hyperparameter templates available with + `GradientBoostedTreesLearner.hyperparameter_templates()` (see this function's + documentation for + details). + Attributes: label: Label of the dataset. The label column should not be identified as a feature in the `features` parameter. @@ -1175,6 +1265,7 @@ def __init__( "validation_interval_in_trees": validation_interval_in_trees, "validation_ratio": validation_ratio, } + data_spec_args = dataspec.DataSpecInferenceArgs( columns=dataspec.normalize_column_defs(features), include_all_columns=include_all_columns, @@ -1216,6 +1307,57 @@ def capabilities(cls) -> abstract_learner_pb2.LearnerCapabilities: support_monotonic_constraints=True, ) + @classmethod + def hyperparameter_templates( + cls, + ) -> Dict[str, hyperparameters.HyperparameterTemplate]: + r"""Hyperparameter templates for this Learner. + + Hyperparameter templates are sets of pre-defined hyperparameters for easy + access to different variants of the learner. Each template is a mapping to a + set of hyperparameters and can be applied directly on the learner. + + Usage example: + ```python + templates = ydf.GradientBoostedTreesLearner.hyperparameter_templates() + better_defaultv1 = templates["better_defaultv1"] + # Print a description of the template + print(better_defaultv1.description) + # Apply the template's settings on the learner. + learner = ydf.GradientBoostedTreesLearner(label, **better_defaultv1) + ``` + + Returns: + Dictionary of the available templates + """ + return { + "better_defaultv1": hyperparameters.HyperparameterTemplate( + name="better_default", + version=1, + description=( + "A configuration that is generally better than the default" + " parameters without being more expensive." + ), + parameters={"growing_strategy": "BEST_FIRST_GLOBAL"}, + ), + "benchmark_rank1v1": hyperparameters.HyperparameterTemplate( + name="benchmark_rank1", + version=1, + description=( + "Top ranking hyper-parameters on our benchmark slightly" + " modified to run in reasonable time." + ), + parameters={ + "growing_strategy": "BEST_FIRST_GLOBAL", + "categorical_algorithm": "RANDOM", + "split_axis": "SPARSE_OBLIQUE", + "sparse_oblique_normalization": "MIN_MAX", + "sparse_oblique_num_projections_exponent": 1.0, + }, + ), + } + + class CartLearner(generic_learner.GenericLearner): r"""Cart learning algorithm. @@ -1237,6 +1379,13 @@ class CartLearner(generic_learner.GenericLearner): print(model.summary()) ``` + Hyperparameters are configured to give reasonable results for typical + datasets. Hyperparameters can also be modified manually (see descriptions) + below or by applying the hyperparameter templates available with + `CartLearner.hyperparameter_templates()` (see this function's documentation + for + details). + Attributes: label: Label of the dataset. The label column should not be identified as a feature in the `features` parameter. @@ -1561,6 +1710,7 @@ def __init__( "uplift_split_score": uplift_split_score, "validation_ratio": validation_ratio, } + data_spec_args = dataspec.DataSpecInferenceArgs( columns=dataspec.normalize_column_defs(features), include_all_columns=include_all_columns, @@ -1601,3 +1751,17 @@ def capabilities(cls) -> abstract_learner_pb2.LearnerCapabilities: support_max_model_size_in_memory=False, support_monotonic_constraints=False, ) + + @classmethod + def hyperparameter_templates( + cls, + ) -> Dict[str, hyperparameters.HyperparameterTemplate]: + r"""Hyperparameter templates for this Learner. + + This learner currently does not provide any hyperparameter templates, this + method is provided for consistency with other learners. + + Returns: + Empty dictionary. + """ + return {} diff --git a/yggdrasil_decision_forests/port/python/ydf/learner/wrapper/wrapper_generator.bzl b/yggdrasil_decision_forests/port/python/ydf/learner/wrapper/wrapper_generator.bzl index b8700afd..a5ccfa75 100644 --- a/yggdrasil_decision_forests/port/python/ydf/learner/wrapper/wrapper_generator.bzl +++ b/yggdrasil_decision_forests/port/python/ydf/learner/wrapper/wrapper_generator.bzl @@ -74,6 +74,7 @@ def py_wrap_yggdrasil_learners( "//ydf/dataset:dataset", "//ydf/dataset:dataspec", "//ydf/learner:generic_learner", + "//ydf/learner:hyperparameters", "//ydf/learner:tuner", ], data = [":" + run_wrapper_name, ":" + wrapper_name], diff --git a/yggdrasil_decision_forests/port/python/ydf/learner/wrapper/wrapper_generator.cc b/yggdrasil_decision_forests/port/python/ydf/learner/wrapper/wrapper_generator.cc index ef2960e7..c2846e87 100644 --- a/yggdrasil_decision_forests/port/python/ydf/learner/wrapper/wrapper_generator.cc +++ b/yggdrasil_decision_forests/port/python/ydf/learner/wrapper/wrapper_generator.cc @@ -95,47 +95,36 @@ std::string PythonFloat(const float value) { return str_value; } -// Generates the python documentation and python object for the pre-defined -// hyper-parameters. +// Generates the Python object for the pre-defined hyper-parameters and the name +// of the first template for the documentation. absl::StatusOr> -BuildPredefinedHyperParameter(const model::AbstractLearner* learner) { - // Documentation about the list of template hyper-parameters. - std::string predefined_hp_doc; - // Python list of template hyper-parameters. - std::string predefined_hp_list = "["; - bool first = true; - - const auto predefined_hyper_parameter_sets = - learner->PredefinedHyperParameters(); - for (const auto& predefined : predefined_hyper_parameter_sets) { - if (first) { - first = false; - } else { - absl::SubstituteAndAppend(&predefined_hp_doc, "\n"); +BuildHyperparameterTemplates(const model::AbstractLearner* learner) { + // Python dictionary of template hyper-parameters. + std::string predefined_hp_dict = "{"; + std::string first_template_name = ""; + + const auto hyperparameter_templates = learner->PredefinedHyperParameters(); + for (const auto& hp_template : hyperparameter_templates) { + if (first_template_name.empty()) { + first_template_name = + absl::Substitute("$0v$1", hp_template.name(), hp_template.version()); } - absl::SubstituteAndAppend( - &predefined_hp_doc, - "- $0@v$1: $2 The parameters are: ", predefined.name(), - predefined.version(), predefined.description()); - absl::SubstituteAndAppend( - &predefined_hp_list, - "core.HyperParameterTemplate(name=\"$0\", " + &predefined_hp_dict, + "\"$0v$1\": " + "hyperparameters.HyperparameterTemplate(name=\"$0\", " "version=$1, description=\"$2\", parameters={", - predefined.name(), predefined.version(), - absl::StrReplaceAll(predefined.description(), {{"\"", "\\\""}})); - + hp_template.name(), hp_template.version(), + absl::StrReplaceAll(hp_template.description(), {{"\"", "\\\""}})); // Iterate over the individual parameters. bool first_field = true; - for (const auto& field : predefined.parameters().fields()) { + for (const auto& field : hp_template.parameters().fields()) { if (first_field) { first_field = false; } else { - absl::StrAppend(&predefined_hp_doc, ", "); - absl::StrAppend(&predefined_hp_list, ", "); + absl::StrAppend(&predefined_hp_dict, ", "); } - absl::StrAppend(&predefined_hp_doc, field.name(), "="); - absl::StrAppend(&predefined_hp_list, "\"", field.name(), "\" :"); + absl::StrAppend(&predefined_hp_dict, "\"", field.name(), "\" :"); switch (field.value().Type_case()) { case model::proto::GenericHyperParameters_Value::TYPE_NOT_SET: return absl::InternalError("Non configured value"); @@ -147,37 +136,27 @@ BuildPredefinedHyperParameter(const model::AbstractLearner* learner) { } else { value = absl::StrCat("\"", value, "\""); } - absl::StrAppend(&predefined_hp_doc, value); - absl::StrAppend(&predefined_hp_list, value); + absl::StrAppend(&predefined_hp_dict, value); } break; case model::proto::GenericHyperParameters_Value::kInteger: - absl::StrAppend(&predefined_hp_doc, field.value().integer()); - absl::StrAppend(&predefined_hp_list, field.value().integer()); + absl::StrAppend(&predefined_hp_dict, field.value().integer()); break; case model::proto::GenericHyperParameters_Value::kReal: - absl::StrAppend(&predefined_hp_doc, - PythonFloat(field.value().real())); - absl::StrAppend(&predefined_hp_list, + absl::StrAppend(&predefined_hp_dict, PythonFloat(field.value().real())); break; case model::proto::GenericHyperParameters_Value::kCategoricalList: absl::StrAppend( - &predefined_hp_doc, "[", - absl::StrJoin(field.value().categorical_list().values(), ","), - "]"); - absl::StrAppend( - &predefined_hp_list, "[", + &predefined_hp_dict, "[", absl::StrJoin(field.value().categorical_list().values(), ","), "]"); break; } } - absl::SubstituteAndAppend(&predefined_hp_doc, "."); - absl::SubstituteAndAppend(&predefined_hp_list, "}),"); + absl::SubstituteAndAppend(&predefined_hp_dict, "}), "); } - absl::StrAppend(&predefined_hp_list, "]"); - return std::pair(predefined_hp_doc, - predefined_hp_list); + absl::StrAppend(&predefined_hp_dict, "}"); + return std::make_pair(predefined_hp_dict, first_template_name); } // Formats some documentation. @@ -254,6 +233,7 @@ from $0yggdrasil_decision_forests.model import abstract_model_pb2 # pylint: dis from $1dataset import dataspec from $1dataset import dataset from $1learner import generic_learner +from $1learner import hyperparameters from $1learner import tuner as tuner_lib )", prefix, pydf_prefix); @@ -277,7 +257,7 @@ included for reference only. The actual wrappers are re-generated during compilation. """ -from typing import Optional +from typing import Dict, Optional $0 )", @@ -413,10 +393,10 @@ from typing import Optional } // Pre-configured hyper-parameters. - std::string predefined_hp_doc; - std::string predefined_hp_list; - ASSIGN_OR_RETURN(std::tie(predefined_hp_doc, predefined_hp_list), - BuildPredefinedHyperParameter(learner.get())); + std::string hp_template_dict; + std::string first_template_name; + ASSIGN_OR_RETURN(std::tie(hp_template_dict, first_template_name), + BuildHyperparameterTemplates(learner.get())); const auto free_text_documentation = FormatDocumentation(specifications.documentation().description(), @@ -444,6 +424,12 @@ class $0(generic_learner.GenericLearner): print(model.summary()) ``` + Hyperparameters are configured to give reasonable results for typical + datasets. Hyperparameters can also be modified manually (see descriptions) + below or by applying the hyperparameter templates available with + `$0.hyperparameter_templates()` (see this function's documentation for + details). + Attributes: label: Label of the dataset. The label column should not be identified as a feature in the `features` parameter. @@ -542,6 +528,7 @@ class $0(generic_learner.GenericLearner): hyper_parameters = { $4 } + data_spec_args = dataspec.DataSpecInferenceArgs( columns=dataspec.normalize_column_defs(features), include_all_columns=include_all_columns, @@ -575,8 +562,7 @@ class $0(generic_learner.GenericLearner): /*$2*/ fields_documentation, /*$3*/ fields_constructor, /*$4*/ fields_dict, /*$5*/ free_text_documentation, - /*$6*/ nice_learner_name, - /*$7*/ predefined_hp_list); + /*$6*/ nice_learner_name); const auto bool_rep = [](const bool value) -> std::string { return value ? "True" : "False"; @@ -602,6 +588,49 @@ class $0(generic_learner.GenericLearner): /*$3*/ bool_rep(capabilities.support_partial_cache_dataset_format()), /*$4*/ bool_rep(capabilities.support_max_model_size_in_memory()), /*$5*/ bool_rep(capabilities.support_monotonic_constraints())); + + if (hp_template_dict == "{}") { + absl::StrAppend(&wrapper, R"( + @classmethod + def hyperparameter_templates(cls) -> Dict[str, hyperparameters.HyperparameterTemplate]: + r"""Hyperparameter templates for this Learner. + + This learner currently does not provide any hyperparameter templates, this + method is provided for consistency with other learners. + + Returns: + Empty dictionary. + """ + return {} +)"); + } else { + absl::SubstituteAndAppend(&wrapper, R"( + @classmethod + def hyperparameter_templates(cls) -> Dict[str, hyperparameters.HyperparameterTemplate]: + r"""Hyperparameter templates for this Learner. + + Hyperparameter templates are sets of pre-defined hyperparameters for easy + access to different variants of the learner. Each template is a mapping to a + set of hyperparameters and can be applied directly on the learner. + + Usage example: + ```python + templates = ydf.$1.hyperparameter_templates() + $2 = templates["$2"] + # Print a description of the template + print($2.description) + # Apply the template's settings on the learner. + learner = ydf.$1(label, **$2) + ``` + + Returns: + Dictionary of the available templates + """ + return $0 +)", + /*$0*/ hp_template_dict, /*$1*/ class_name, + /*$2*/ first_template_name); + } } return wrapper; diff --git a/yggdrasil_decision_forests/port/python/ydf/learner/wrapper/wrapper_test.cc b/yggdrasil_decision_forests/port/python/ydf/learner/wrapper/wrapper_test.cc index 0c7ffc74..e52d845b 100644 --- a/yggdrasil_decision_forests/port/python/ydf/learner/wrapper/wrapper_test.cc +++ b/yggdrasil_decision_forests/port/python/ydf/learner/wrapper/wrapper_test.cc @@ -16,6 +16,7 @@ #include #include #include +#include #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -58,6 +59,26 @@ class FakeLearner1 : public model::AbstractLearner { a.mutable_documentation()->set_proto_field("c"); return spec; } + + std::vector + PredefinedHyperParameters() const override { + model::proto::PredefinedHyperParameterTemplate hptemplate; + hptemplate.set_name("fake_template_1"); + hptemplate.set_version(4); + hptemplate.set_description("This is a fake template."); + auto* field = hptemplate.mutable_parameters()->add_fields(); + field->set_name("a"); + field->mutable_value()->set_real(2); + + model::proto::PredefinedHyperParameterTemplate hptemplate2; + hptemplate2.set_name("fake_template_2"); + hptemplate2.set_version(1); + hptemplate2.set_description("This is another fake template."); + field = hptemplate2.mutable_parameters()->add_fields(); + field->set_name("a"); + field->mutable_value()->set_real(3); + return {hptemplate, hptemplate2}; + }; }; TEST(LearnerWrappers, LearnerKeyToClassName) { @@ -87,6 +108,12 @@ class FakeAlgorithmLearner(generic_learner.GenericLearner): print(model.summary()) ``` + Hyperparameters are configured to give reasonable results for typical + datasets. Hyperparameters can also be modified manually (see descriptions) + below or by applying the hyperparameter templates available with + `FakeAlgorithmLearner.hyperparameter_templates()` (see this function's documentation for + details). + Attributes: label: Label of the dataset. The label column should not be identified as a feature in the `features` parameter. @@ -187,6 +214,7 @@ class FakeAlgorithmLearner(generic_learner.GenericLearner): "a" : a, } + data_spec_args = dataspec.DataSpecInferenceArgs( columns=dataspec.normalize_column_defs(features), include_all_columns=include_all_columns, @@ -226,6 +254,29 @@ class FakeAlgorithmLearner(generic_learner.GenericLearner): support_max_model_size_in_memory=False, support_monotonic_constraints=False, ) + + @classmethod + def hyperparameter_templates(cls) -> Dict[str, hyperparameters.HyperparameterTemplate]: + r"""Hyperparameter templates for this Learner. + + Hyperparameter templates are sets of pre-defined hyperparameters for easy + access to different variants of the learner. Each template is a mapping to a + set of hyperparameters and can be applied directly on the learner. + + Usage example: + ```python + templates = ydf.FakeAlgorithmLearner.hyperparameter_templates() + fake_template_1v4 = templates["fake_template_1v4"] + # Print a description of the template + print(fake_template_1v4.description) + # Apply the template's settings on the learner. + learner = ydf.FakeAlgorithmLearner(label, **fake_template_1v4) + ``` + + Returns: + Dictionary of the available templates + """ + return {"fake_template_1v4": hyperparameters.HyperparameterTemplate(name="fake_template_1", version=4, description="This is a fake template.", parameters={"a" :2.0}), "fake_template_2v1": hyperparameters.HyperparameterTemplate(name="fake_template_2", version=1, description="This is another fake template.", parameters={"a" :3.0}), } )")); }