-
-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
AnyParameterProperties refactor #4412
Changes from 3 commits
0a8628d
c505c2a
3aba095
476d2a9
3e32f1c
dfb5aea
2bf79c4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,9 @@ | ||
/* | ||
* This software is distributed under BSD 3-clause license (see LICENSE file). | ||
* | ||
* Authors: Heiko Strathmann, Gil Hoben | ||
*/ | ||
|
||
#ifndef __ANYPARAMETER_H__ | ||
#define __ANYPARAMETER_H__ | ||
|
||
|
@@ -21,49 +27,102 @@ namespace shogun | |
GRADIENT_NOT_AVAILABLE = 0, | ||
GRADIENT_AVAILABLE = 1 | ||
}; | ||
|
||
/** @brief Class AnyParameterProperties keeps track of parameter properties. | ||
* | ||
* Currently there are three types of parameters: | ||
* -# HYPERPARAMETER: the parameter determines how the training is | ||
* performed, e.g. regularisation | ||
* -# GRADIENT_PARAM: the parameter is used in gradient updates | ||
* -# MODEL_PARAM: model parameter that is trained, e.g. weight and bias | ||
* vectors and bias | ||
*/ | ||
class AnyParameterProperties | ||
{ | ||
public: | ||
AnyParameterProperties() | ||
: m_description(), m_model_selection(MS_NOT_AVAILABLE), | ||
m_gradient(GRADIENT_NOT_AVAILABLE) | ||
static const int32_t HYPERPARAMETER = 0x00000001; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What about making it an int enum? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah that's neat! I'll implement that. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can we keep the naming self-consistent Actually, in favour of short and concise names, why dont we use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK! But hyperparameter is a term that could be misinterpreted if it written as HYPER, no? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it is pretty clear since the class is ending with "Parameter", so everything in there is one .... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The name MODEL causes conflicts if we use an enum, so will have to use something more specific, or just have these values as static class members of AnyParameterProperties. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes, please don't define them globally, but as a static member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. would it make sense to use an enum within the class scope? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fine as well |
||
static const int32_t GRADIENT_PARAM = 0x00000010; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can also use the << operator to shift the 1 a desired number of digits There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I had a look at the post, and the Enum with bit operations is pretty cool. I just thought that the hexadecimal representation is more readable than doing the bit shifts, no? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. at the end of the day, it is style. You can either define the mask as you did with hexadecimal as you did there. Or, instead, you can generate those masks on the fly using a shift operator, and then the
The latter has the advantage that somebody reading the code never is exposed to hexadecimal numbers, nor powers or two (which can be confusing). On the other hand, masking operations (as what I wrote above) becomes a bit more notation heavy. Idk what is best to be honest. I think the shifting is more standard and therefore I think we should follow that. Ah one thing I think is good about the shifting approach is that you can change the size of the mask easily. You are using a 32bit int above, but you only write down the last 8 bits, which is weird. Imagine you now changed the mask to 64 bit. Then the hexadecimals would be quite long, whereas the shifts wouldnt be. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK! I think you're right, I have changed the class members to use bit shifts, it is a bit cleaner. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would call this GRADIENT_AVAILABLE |
||
static const int32_t MODEL_PARAM = 0x00000100; | ||
|
||
/** default constructor where all parameter types are switched to false | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Minor: sentences start with capital letters |
||
*/ | ||
AnyParameterProperties() : m_description(), m_mask_attribute(0x00000000) | ||
{ | ||
} | ||
/** legacy constructor */ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would remove that. Until we haven't removed it, it is not legacy. |
||
AnyParameterProperties( | ||
std::string description, | ||
EModelSelectionAvailability model_selection = MS_NOT_AVAILABLE, | ||
EGradientAvailability gradient = GRADIENT_NOT_AVAILABLE) | ||
EGradientAvailability gradient = GRADIENT_NOT_AVAILABLE, | ||
bool hyperparameter = false) | ||
: m_description(description), m_model_selection(model_selection), | ||
m_gradient(gradient) | ||
{ | ||
m_mask_attribute = 0x00000000; | ||
if (model_selection) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. wouldnt this work?
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. or in the new style
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. True, that would be more concise. Is it worth writing a static member that is the default, i.e. 0? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If the default is 0, then we don't need that. |
||
m_mask_attribute |= MODEL_PARAM; | ||
if (gradient) | ||
m_mask_attribute |= GRADIENT_PARAM; | ||
if (hyperparameter) | ||
m_mask_attribute |= HYPERPARAMETER; | ||
} | ||
/** mask constructor */ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if you add doxygen docs, pls document all parameters |
||
AnyParameterProperties(std::string description, int32_t mask_attribute) | ||
: m_description(description) | ||
{ | ||
m_mask_attribute = mask_attribute; | ||
} | ||
/** copy contructor */ | ||
AnyParameterProperties(const AnyParameterProperties& other) | ||
: m_description(other.m_description), | ||
m_model_selection(other.m_model_selection), | ||
m_gradient(other.m_gradient) | ||
m_gradient(other.m_gradient), | ||
m_mask_attribute(other.m_mask_attribute) | ||
{ | ||
} | ||
|
||
/** description getter */ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. superflous doc, as the method name explains it, i would just remove it |
||
std::string get_description() const | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. minor what about returning a const string reference There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I think we could do that. It seems to be pretty much standard now to return const references for std::string. It can sometimes lead to odd behaviours, but I don't think we need to worry about those.. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes, but the first rule of the C++ committee is: |
||
{ | ||
return m_description; | ||
} | ||
|
||
/** model selection flag getter */ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same here, would remove the comment |
||
EModelSelectionAvailability get_model_selection() const | ||
{ | ||
return m_model_selection; | ||
EModelSelectionAvailability return_val; | ||
if (m_mask_attribute & HYPERPARAMETER) | ||
return_val = EModelSelectionAvailability::MS_AVAILABLE; | ||
else | ||
return_val = EModelSelectionAvailability::MS_NOT_AVAILABLE; | ||
return return_val; | ||
} | ||
|
||
/** gradient flag getter */ | ||
EGradientAvailability get_gradient() const | ||
{ | ||
return m_gradient; | ||
EGradientAvailability return_val; | ||
if (m_mask_attribute & GRADIENT_PARAM) | ||
return_val = EGradientAvailability::GRADIENT_AVAILABLE; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it makes sense to return immediately without return_val There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you mean with a one liner like this?
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah maybe with some helper function so it looks shorter? There is some repeated code in these flags. |
||
else | ||
return_val = EGradientAvailability::GRADIENT_NOT_AVAILABLE; | ||
return return_val; | ||
} | ||
|
||
/** hyperparameter flag getter */ | ||
bool get_hyperparameter() const | ||
{ | ||
bool return_val; | ||
if (m_mask_attribute & HYPERPARAMETER) | ||
return_val = true; | ||
else | ||
return_val = false; | ||
return return_val; | ||
} | ||
|
||
private: | ||
std::string m_description; | ||
EModelSelectionAvailability m_model_selection; | ||
EGradientAvailability m_gradient; | ||
/** mask to store all param flags*/ | ||
int32_t m_mask_attribute; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what about calling it "attribute_mask" ? :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yup, I just noticed that I switched the order... |
||
}; | ||
|
||
class AnyParameter | ||
|
@@ -116,6 +175,6 @@ namespace shogun | |
Any m_value; | ||
AnyParameterProperties m_properties; | ||
}; | ||
} | ||
} // namespace shogun | ||
|
||
#endif |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -676,7 +676,10 @@ class CSGObject | |
void watch_param( | ||
const std::string& name, T* value, | ||
AnyParameterProperties properties = AnyParameterProperties( | ||
"Unknown parameter", MS_NOT_AVAILABLE, GRADIENT_NOT_AVAILABLE)) | ||
"Unknown parameter", | ||
AnyParameterProperties::HYPERPARAMETER | | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. instead of doing this here, I think it might be better to offer a constructor that does not take any properties, and then set the default values inside there. We need to discuss clever default values as well btw |
||
AnyParameterProperties::GRADIENT_PARAM | | ||
AnyParameterProperties::MODEL_PARAM)) | ||
{ | ||
BaseTag tag(name); | ||
create_parameter(tag, AnyParameter(make_any_ref(value), properties)); | ||
|
@@ -694,7 +697,10 @@ class CSGObject | |
void watch_param( | ||
const std::string& name, T** value, S* len, | ||
AnyParameterProperties properties = AnyParameterProperties( | ||
"Unknown parameter", MS_NOT_AVAILABLE, GRADIENT_NOT_AVAILABLE)) | ||
"Unknown parameter", | ||
AnyParameterProperties::HYPERPARAMETER | | ||
AnyParameterProperties::GRADIENT_PARAM | | ||
AnyParameterProperties::MODEL_PARAM)) | ||
{ | ||
BaseTag tag(name); | ||
create_parameter( | ||
|
@@ -715,7 +721,10 @@ class CSGObject | |
void watch_param( | ||
const std::string& name, T** value, S* rows, S* cols, | ||
AnyParameterProperties properties = AnyParameterProperties( | ||
"Unknown parameter", MS_NOT_AVAILABLE, GRADIENT_NOT_AVAILABLE)) | ||
"Unknown parameter", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same with the description, I would offer a ctor that does not ask for one, and then set it to the empty string or "No description given" in the ctor, but not here in |
||
AnyParameterProperties::HYPERPARAMETER | | ||
AnyParameterProperties::GRADIENT_PARAM | | ||
AnyParameterProperties::MODEL_PARAM)) | ||
{ | ||
BaseTag tag(name); | ||
create_parameter( | ||
|
@@ -733,7 +742,10 @@ class CSGObject | |
{ | ||
BaseTag tag(name); | ||
AnyParameterProperties properties( | ||
"Dynamic parameter", MS_NOT_AVAILABLE, GRADIENT_NOT_AVAILABLE); | ||
"Dynamic parameter", | ||
AnyParameterProperties::HYPERPARAMETER | | ||
AnyParameterProperties::GRADIENT_PARAM | | ||
AnyParameterProperties::MODEL_PARAM); | ||
std::function<T()> bind_method = | ||
std::bind(method, dynamic_cast<const S*>(this)); | ||
create_parameter(tag, AnyParameter(make_any(bind_method), properties)); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pls don’t put such things into the docs, they outdated at light speed.
Better describe that there are attributes, maybe an example, but not losing them all
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK!