DiSMEC++
|
Base class for all objects that have adjustable hyper-parameters. More...
#include <hyperparams.h>
Classes | |
struct | HyperParamData |
This structure collects the Getter and Setter functions. This is what we store in the variant. More... | |
Public Types | |
using | hyper_param_t = std::variant< long, double > |
Public Member Functions | |
HyperParameterBase ()=default | |
virtual | ~HyperParameterBase ()=default |
HyperParameterBase (const HyperParameterBase &)=default | |
HyperParameterBase (HyperParameterBase &&)=default | |
HyperParameterBase & | operator= (HyperParameterBase &&)=default |
HyperParameterBase & | operator= (const HyperParameterBase &)=default |
void | set_hyper_parameter (const std::string &name, long value) |
void | set_hyper_parameter (const std::string &name, double value) |
hyper_param_t | get_hyper_parameter (const std::string &name) const |
std::vector< std::string > | get_hyper_parameter_names () const |
Returns a vector that lists all hyper parameter names. More... | |
Protected Member Functions | |
template<class U , class S > | |
void | declare_hyper_parameter (std::string name, U S::*pointer) |
template<class U , class S > | |
void | declare_hyper_parameter (std::string name, U(S::*getter)() const, void(S::*setter)(U)) |
Declares an constrained hyper-parameter with explicit getter and setter function. More... | |
template<class T , class S > | |
void | declare_sub_object (const std::string &name, T S::*object) |
Declares a sub-object that also contains hyper-parameters. More... | |
Private Types | |
using | hyper_param_ptr_t = std::variant< HyperParamData< long >, HyperParamData< double > > |
Private Member Functions | |
template<class D > | |
void | declare_hyper_parameter (std::string name, HyperParamData< D > data) |
Private Attributes | |
std::unordered_map< std::string, hyper_param_ptr_t > | m_HyperParameters |
Base class for all objects that have adjustable hyper-parameters.
This class defines a common interface for all objects with adjustable hyper-parameters, and provides the implementation. Derived classes only have to declare their hyper-parameters in the constructor using the declare_hyper_parameter
functions, and the rest is handled by this class.
This is some fairly complicated C++ magic; however, if you only want to modify the solver algorithms or objective functions, then this class should not need to be touched. Using is should be fairly straightforward, though:
Usage: The intent of this class is to provide a unified interface and implementation to objects that expose some sort of hyper-parameters which we would like to read from a config file or the command line. In that case, make you class (called Object
here) derive from HyperParameterBase
. This will provide the functions set_hyper_parameter
and get_hyper_parameter
to query and update hyper-parameter values based on a string name.
How do you define which hyper-parameters exist? This is what the protected declare_hyper_parameter
functions are for. These should be called in the constructor of your class, and declare a name for each hyper-parameter you want to use. The HyperParameterBase
object does not manage the storage of the hyper-parameter values, just access to it. This is deliberate, as looking up a hyper-parameter by name might be a costly operation, so the actual Object
, which anyways knows exactly which hyper-parameters it has, should not do. Instead, the hyper-parameters are stored as part of the Object
class. For example, consider
In this case, A
is a parameter which presumably can take on any valid double value, whereas the values of B
should fulfill the check_value
function. The corresponding constructor could look like this:
Implementation Details: Internally, the hyper-parameters are stored as a map that maps hyper-parameter names to getter and setter functions. These functions take as first argument a pointer to the object, the setter as second argument the target value. The reason why we give the getters/setters a pointer to the object, instead of having them modify the values directly, is that the latter would break after copy/move operations on HyperParameterBase, whereas in this way we do not need to disable copy and move.
Even though the class itself provides no virtual functions, its destructor is declared virtual. This enables RTTI, which we use to check consistency of the supplied this pointers.
The magic happens in the declare_hyper_parameter
functions. These construct the function objects, based on member pointers or pointers-to-member-function. See their documentation for details.
Definition at line 83 of file hyperparams.h.
|
private |
Definition at line 233 of file hyperparams.h.
using dismec::HyperParameterBase::hyper_param_t = std::variant<long, double> |
Definition at line 85 of file hyperparams.h.
|
default |
|
virtualdefault |
|
default |
|
default |
|
inlineprivate |
The internal declare_hyper_parameter
function, adds the HP data to the map and checks that the names are unique.
Definition at line 226 of file hyperparams.h.
References m_HyperParameters.
|
inlineprotected |
Declares an unconstrained hyper-parameter. The getter and setter functions are created automatically and read from/write to the given member variable.
U | The type of the hyper-parameter. Has to be one of long, double |
S | The class into which the pointer goes. This has to be the actual type (or a base therof) of the this pointer, i.e. it is required that dynamic_cast<S*>(this) succeeds. |
name | Name of the hyper-parameter. |
pointer | Pointer to member of the class which stores the value of the hyper-parameter. |
statically, we can only test whether whether the class S
is derived from HyperParameterBase
, but not if it is actually consistent with the this
pointer. However, this static assert should catch almost all erroneous uses. The rest will be caught at runtime in the dynamic_cast check
OK, we know we are consistent, generate the getter and setter functions. I think technically we could get away with using static_cast here, since we know that self
is actually of type S
, but I think having the explicit dynamic_cast helps to emphasize what is happening.
and insert them into the map
Definition at line 117 of file hyperparams.h.
Referenced by dismec::solvers::BacktrackingLineSearch::BacktrackingLineSearch(), dismec::solvers::CGMinimizer::CGMinimizer(), declare_hyper_parameter(), declare_sub_object(), and dismec::solvers::NewtonWithLineSearch::NewtonWithLineSearch().
|
inlineprotected |
Declares an constrained hyper-parameter with explicit getter and setter function.
U | The type of the hyper-parameter. Has to be one of long, double. |
S | The class into which the member function pointer goes. This has to be the actual type (or a base therof) of the this pointer, i.e. it is required that dynamic_cast<S*>(this) succeeds. |
name | Name of the hyper-parameter. |
getter | Pointer to member of the class which reads the value of the hyper-parameter. |
setter | Pointer to member of the class which sets the value of the hyper-parameter. |
Definition at line 152 of file hyperparams.h.
References declare_hyper_parameter().
|
inlineprotected |
Declares a sub-object that also contains hyper-parameters.
Any hyper-parameter in the sub-object will be also added to this object, where the name is prefixed by the name
parameter given to this function. At the point of this function call, the sub-object must exist and have its hyper-paramters already initialized.
S | The class into which the member function pointer goes. This has to be the actual type (or a base therof) of the this pointer, i.e. it is required that dynamic_cast<S*>(this) succeeds. |
Definition at line 179 of file hyperparams.h.
References declare_hyper_parameter(), m_HyperParameters, and dismec::types::visit().
Referenced by dismec::solvers::NewtonWithLineSearch::NewtonWithLineSearch().
auto HyperParameterBase::get_hyper_parameter | ( | const std::string & | name | ) | const |
Gets the value of the named hyper-parameter. Since we cannot know the exact type, we return a variant.
Definition at line 10 of file hyperparams.cpp.
References dismec::types::visit().
std::vector< std::string > HyperParameterBase::get_hyper_parameter_names | ( | ) | const |
Returns a vector that lists all hyper parameter names.
Definition at line 29 of file hyperparams.cpp.
References m_HyperParameters.
|
default |
|
default |
void HyperParameterBase::set_hyper_parameter | ( | const std::string & | name, |
double | value | ||
) |
Definition at line 24 of file hyperparams.cpp.
References m_HyperParameters.
void HyperParameterBase::set_hyper_parameter | ( | const std::string & | name, |
long | value | ||
) |
updates the value of the hyper-parameter with the given name
. If the type does not match the internal hyper-parameter type, an exception is throw.
Definition at line 19 of file hyperparams.cpp.
References m_HyperParameters.
Referenced by dismec::HyperParameters::apply().
|
private |
Definition at line 234 of file hyperparams.h.
Referenced by declare_hyper_parameter(), declare_sub_object(), get_hyper_parameter_names(), and set_hyper_parameter().