Commit e54b24b1 authored by Thomas Purcell's avatar Thomas Purcell
Browse files

Add parameterization for top level only

add support similar to what was used with ceres
parent 7c2be95f
......@@ -38,6 +38,24 @@ BOOST_CLASS_EXPORT_GUID(InvParamNode, "InvParamNode")
BOOST_CLASS_EXPORT_GUID(SinParamNode, "SinParamNode")
BOOST_CLASS_EXPORT_GUID(CosParamNode, "CosParamNode")
BOOST_CLASS_EXPORT_GUID(AddParamTopLevNode, "AddParamTopLevNode")
BOOST_CLASS_EXPORT_GUID(SubParamTopLevNode, "SubParamTopLevNode")
BOOST_CLASS_EXPORT_GUID(AbsDiffParamTopLevNode, "AbsDiffParamTopLevNode")
BOOST_CLASS_EXPORT_GUID(MultParamTopLevNode, "MultParamTopLevNode")
BOOST_CLASS_EXPORT_GUID(DivParamTopLevNode, "DivParamTopLevNode")
BOOST_CLASS_EXPORT_GUID(SqParamTopLevNode, "SqParamTopLevNode")
BOOST_CLASS_EXPORT_GUID(SqrtParamTopLevNode, "SqrtParamTopLevNode")
BOOST_CLASS_EXPORT_GUID(CbParamTopLevNode, "CbParamTopLevNode")
BOOST_CLASS_EXPORT_GUID(CbrtParamTopLevNode, "CbrtParamTopLevNode")
BOOST_CLASS_EXPORT_GUID(SixPowParamTopLevNode, "SixPowParamTopLevNode")
BOOST_CLASS_EXPORT_GUID(ExpParamTopLevNode, "ExpParamTopLevNode")
BOOST_CLASS_EXPORT_GUID(NegExpParamTopLevNode, "NegExpParamTopLevNode")
BOOST_CLASS_EXPORT_GUID(LogParamTopLevNode, "LogParamTopLevNode")
BOOST_CLASS_EXPORT_GUID(AbsParamTopLevNode, "AbsParamTopLevNode")
BOOST_CLASS_EXPORT_GUID(InvParamTopLevNode, "InvParamTopLevNode")
BOOST_CLASS_EXPORT_GUID(SinParamTopLevNode, "SinParamTopLevNode")
BOOST_CLASS_EXPORT_GUID(CosParamTopLevNode, "CosParamTopLevNode")
FeatureSpace::FeatureSpace(
std::shared_ptr<MPI_Interface> mpi_comm,
std::vector<node_ptr> phi_0,
......@@ -52,7 +70,8 @@ FeatureSpace::FeatureSpace(
int n_rung_generate,
double cross_corr_max,
double min_abs_feat_val,
double max_abs_feat_val
double max_abs_feat_val,
bool param_internal
):
_phi(phi_0),
_phi_0(phi_0),
......@@ -73,7 +92,8 @@ FeatureSpace::FeatureSpace(
_n_samp(phi_0[0]->n_samp()),
_n_feat(phi_0.size()),
_n_rung_store(max_store_rung),
_n_rung_generate(n_rung_generate)
_n_rung_generate(n_rung_generate),
_param_internal(param_internal)
{
initialize_fs(project_type);
}
......@@ -84,7 +104,7 @@ void FeatureSpace::initialize_fs(std::string project_type)
if(_allowed_param_ops.size() != 0)
throw std::logic_error("Parameterization is not possible recompile with -DPARAMETERIZE");
#else
nlopt_wrapper::set_objective(project_type, _prop.data(), _task_sizes, _max_phi);
nlopt_wrapper::set_objective(project_type, _prop.data(), _task_sizes, _max_phi, _param_internal);
#endif
if(_n_rung_store == -1)
......
......@@ -82,6 +82,8 @@ class FeatureSpace
const int _n_sis_select; //!< Number of features to select for each dimensions
const int _n_samp; //!< Number of samples (training data)
const int _n_rung_generate; //!< Total number of rungs to generate on the fly
bool _param_internal; //!< True if parameterize all scale and shift parameters in a feature
public:
/**
......@@ -117,7 +119,8 @@ public:
int n_rung_generate=0,
double cross_corr_max=1.0,
double min_abs_feat_val=1e-50,
double max_abs_feat_val=1e50
double max_abs_feat_val=1e50,
bool param_internal=true
);
/**
......@@ -299,7 +302,8 @@ public:
int n_rung_generate=0,
double cross_corr_max=1.0,
double min_abs_feat_val=1e-50,
double max_abs_feat_val=1e50
double max_abs_feat_val=1e50,
bool param_internal=true
);
/**
......@@ -333,7 +337,8 @@ public:
int n_rung_generate=0,
double cross_corr_max=1.0,
double min_abs_feat_val=1e-50,
double max_abs_feat_val=1e50
double max_abs_feat_val=1e50,
bool param_internal=true
);
/**
......
......@@ -346,7 +346,7 @@ public:
* @brief returns the number of theoretical parameters for this feature
* @return the number of theoretical parameters
*/
inline int n_params(int n_cur = 0){return std::accumulate(_feats.begin(), _feats.end(), 2, [](double tot, node_ptr feat){return tot + feat->n_params();});}
virtual inline int n_params(int n_cur = 0){return std::accumulate(_feats.begin(), _feats.end(), 2, [](double tot, node_ptr feat){return tot + feat->n_params();});}
/**
* @brief Set the values of the training data for the feature inside of the value storage arrays
......
#include <feature_creation/node/operator_nodes/allowed_operator_nodes/abs/parameterize_top_lev_absolute_value.hpp>
void generateAbsParamTopLevNode(std::vector<node_ptr>& feat_list, node_ptr feat, int& feat_ind, double l_bound, double u_bound, std::vector<double>& prop)
{
++feat_ind;
node_ptr new_feat = std::make_shared<AbsParamTopLevNode>(feat, feat_ind, prop);
new_feat->set_value();
if(new_feat->is_nan() || new_feat->is_const() || (util_funcs::max_abs_val<double>(new_feat->value_ptr(), new_feat->n_samp()) > u_bound) || (util_funcs::max_abs_val<double>(new_feat->value_ptr(), new_feat->n_samp()) < l_bound))
return;
feat_list.push_back(new_feat);
}
AbsParamTopLevNode::AbsParamTopLevNode()
{}
AbsParamTopLevNode::AbsParamTopLevNode(node_ptr feat, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop) :
AbsParamNode(feat, feat_ind, l_bound, u_bound)
{
_params.resize(n_params(), 0.0);
get_parameters(prop);
if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound))
throw InvalidFeatureException();
}
AbsParamTopLevNode::AbsParamTopLevNode(node_ptr feat, int feat_ind, std::vector<double>& prop) :
AbsParamNode(feat, feat_ind)
{
_params.resize(n_params(), 0.0);
get_parameters(prop);
}
AbsParamTopLevNode::AbsParamTopLevNode(node_ptr feat, int feat_ind, double l_bound, double u_bound) :
AbsParamNode(feat, feat_ind, l_bound, u_bound)
{
_params.resize(n_params(), 0.0);
}
void AbsParamTopLevNode::set_value(int offset)
{
offset = (offset == -1) ? rung() : offset;
if(_selected)
allowed_op_funcs::abs(_n_samp, _feats[0]->value_ptr(offset + 2), _params[0], _params[1], node_value_arrs::get_d_matrix_ptr(_d_mat_ind));
allowed_op_funcs::abs(_n_samp, _feats[0]->value_ptr(offset + 2), _params[0], _params[1], node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset, false));
}
void AbsParamTopLevNode::set_test_value(int offset)
{
offset = (offset == -1) ? rung() : offset;
allowed_op_funcs::abs(_n_test_samp, _feats[0]->test_value_ptr(offset + 2), _params[0], _params[1], node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset, false));
}
void AbsParamTopLevNode::set_bounds(double* lb, double* ub, int from_parent)
{
lb[0] = _sign_alpha;
ub[0] = _sign_alpha;
}
/** @file feature_creation/node/operator_nodes/allowed_operator_nodes/abs/parameterize_top_levabsolute_value.hpp
* @brief Class describing the parameterized absolute value operator
*
* This class represents the parameterized unary operator -> |alpha * A + a|
*
* @author Thomas A. R. Purcell (tpurcell)
* @bug No known bugs.
*/
#ifndef PARAM_TOP_LEV_ABS_VAL_NODE
#define PARAM_TOP_LEV_ABS_VAL_NODE
#include <feature_creation/node/operator_nodes/allowed_operator_nodes/abs/parameterized_absolute_value.hpp>
#include <nl_opt/NLOptWrapper.hpp>
// DocString: cls_abs_node
/**
* @brief Node for the absolute value operator
*
*/
class AbsParamTopLevNode: public AbsParamNode
{
using AbsParamNode::set_value;
using AbsParamNode::set_test_value;
using AbsParamNode::value_ptr;
using AbsParamNode::test_value_ptr;
using AbsParamNode::domain;
using AbsParamNode::expr;
friend class boost::serialization::access;
/**
* @brief Serialization function to send over MPI
*
* @param ar Archive representation of node
*/
template <typename Archive>
void serialize(Archive& ar, const unsigned int version)
{
ar & boost::serialization::base_object<AbsParamNode>(*this);
}
public:
/**
* @brief Base Constructor
* @details This is only used for serialization
*/
AbsParamTopLevNode();
/**
* @brief Constructor
* @details Constructs the Node from node pointer of the feature to operate on
*
* @param feat_1 shared_ptr of the feature to operate on (A)
* @param feat_ind Index of the new feature
* @param l_bound Minimum absolute value allowed for the feature.
* @param u_bound Maximum absolute value allowed for the feature.
* @param param_list The list of parameters to optimize using non-linear least squares
* @param prop The property to fit to
*/
AbsParamTopLevNode(node_ptr feat, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop);
/**
* @brief Constructor
* @details Constructs the Node from node pointer of the feature to operate on
*
* @param feat_1 shared_ptr of the feature to operate on (A)
* @param feat_ind Index of the new feature
* @param prop The property to fit to
*/
AbsParamTopLevNode(node_ptr feat, int feat_ind, std::vector<double>& prop);
/**
* @brief Constructor
* @details Constructs the Node from node pointer of the feature to operate on
*
* @param feat_1 shared_ptr of the feature to operate on (A)
* @param feat_ind Index of the new feature
* @param l_bound Minimum absolute value allowed for the feature.
* @param u_bound Maximum absolute value allowed for the feature.
* @param param_list The list of parameters to optimize using non-linear least squares
*/
AbsParamTopLevNode(node_ptr feat, int feat_ind, double l_bound=1e-50, double u_bound=1e50);
// DocString: abs_param_top_lev_node_n_params
/**
* @brief returns the number of theoretical parameters for this feature
* @return the number of theoretical parameters
*/
inline int n_params(int n_cur = 0){return 2;}
// DocString: abs_param_top_lev_node_set_value
/**
* @brief Set the values of the training data for the feature inside of the value storage arrays
*
* @param offset(int) Key to determine which part of the temporary storage array to look into
*/
void set_value(int offset = -1);
// DocString: abs_param_top_lev_node_set_test_value
/**
* @brief Set the values of the test data for the feature inside of the value storage arrays
*
* @param offset(int) Key to determine which part of the temporary storage array to look into
*/
void set_test_value(int offset = -1);
// DocString: abs_param_top_lev_node_expr
/**
* @brief Get the expression for the overall feature (From root node down)
*/
inline std::string expr(){return "|" + std::to_string(_params[0]) + "*" + _feats[0]->expr() + " + " + std::to_string(_params[1]) + "|";}
// DocString: abs_param_top_lev_node_domain
/**
* @brief The domain for the feature (min/max values)
*/
inline Domain domain(){return _feats[0]->domain().abs(_params[0], _params[1]);}
// DocString: abs_param_top_lev_node_set_bounds
/**
* @brief Set the bounds for the nl parameterization
*
* @param lb pointer to the lower bounds data
* @param ub pointer to the upper bounds data
*/
void set_bounds(double* lb, double* ub, int from_parent=2);
};
void generateAbsParamTopLevNode(std::vector<node_ptr>& feat_list, node_ptr feat, int& feat_ind, double l_bound, double u_bound, std::vector<double>& prop);
#endif
#include <feature_creation/node/operator_nodes/allowed_operator_nodes/abs/parameterized_absolute_value.hpp>
BOOST_SERIALIZATION_ASSUME_ABSTRACT(AbsParamNode)
void generateAbsParamNode(std::vector<node_ptr>& feat_list, node_ptr feat, int& feat_ind, double l_bound, double u_bound, std::vector<double>& prop)
{
++feat_ind;
......
......@@ -19,13 +19,6 @@
*/
class AbsParamNode: public AbsNode
{
using AbsNode::set_value;
using AbsNode::set_test_value;
using AbsNode::value_ptr;
using AbsNode::test_value_ptr;
using AbsNode::domain;
using AbsNode::expr;
friend class boost::serialization::access;
/**
......@@ -42,6 +35,12 @@ class AbsParamNode: public AbsNode
}
protected:
using AbsNode::set_value;
using AbsNode::set_test_value;
using AbsNode::value_ptr;
using AbsNode::test_value_ptr;
using AbsNode::domain;
using AbsNode::expr;
std::vector<double> _params; //!< The parameters vector
double _sign_alpha; //!< 1 if alpha is positive, -1 if alpha is negative
......@@ -85,7 +84,7 @@ public:
* @param u_bound Maximum absolute value allowed for the feature.
* @param param_list The list of parameters to optimize using non-linear least squares
*/
AbsParamNode(node_ptr feat, int feat_ind, double l_bound, double u_bound);
AbsParamNode(node_ptr feat, int feat_ind, double l_bound=1e-50, double u_bound=1e50);
// DocString: abs_param_node_set_value
/**
......
#include <feature_creation/node/operator_nodes/allowed_operator_nodes/abs_diff/parameterize_top_lev_absolute_difference.hpp>
void generateAbsDiffParamTopLevNode(std::vector<node_ptr>& feat_list, node_ptr feat_1, node_ptr feat_2, int& feat_ind, double l_bound, double u_bound, std::vector<double>& prop)
{
++feat_ind;
node_ptr new_feat = std::make_shared<AbsDiffParamTopLevNode>(feat_1, feat_2, feat_ind, prop);
std::map<std::string, int> add_sub_leaves;
int expected_abs_tot = 0;
feat_1->update_add_sub_leaves(add_sub_leaves, 1, expected_abs_tot);
feat_2->update_add_sub_leaves(add_sub_leaves,-1, expected_abs_tot);
if((add_sub_leaves.size() < 2))
return;
double* params = new_feat->parameters().data();
double* val_ptr = new_feat->value_ptr();
const int offset = new_feat->rung();
allowed_op_funcs::sub(feat_1->n_samp(), feat_1->value_ptr(offset + 2), feat_2->value_ptr(offset + 1), params[0], params[1], val_ptr);
if(*std::min_element(val_ptr, val_ptr + new_feat->n_samp()) > l_bound)
return;
new_feat->set_value();
if(new_feat->is_nan() || new_feat->is_const() || (util_funcs::max_abs_val<double>(new_feat->value_ptr(), new_feat->n_samp()) > u_bound) || (util_funcs::max_abs_val<double>(new_feat->value_ptr(), new_feat->n_samp()) < l_bound) || (util_funcs::max_abs_val<double>(val_ptr, feat_1->n_samp()) < l_bound))
return;
feat_list.push_back(new_feat);
}
AbsDiffParamTopLevNode::AbsDiffParamTopLevNode()
{}
AbsDiffParamTopLevNode::AbsDiffParamTopLevNode(node_ptr feat_1, node_ptr feat_2, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop):
AbsDiffParamNode(feat_1, feat_2, feat_ind, l_bound, u_bound)
{
std::map<std::string, int> add_sub_leaves;
int expected_abs_tot = 0;
feat_1->update_add_sub_leaves(add_sub_leaves, 1, expected_abs_tot);
feat_2->update_add_sub_leaves(add_sub_leaves,-1, expected_abs_tot);
if((add_sub_leaves.size() < 2))
throw InvalidFeatureException();
_params.resize(n_params(), 0.0);
get_parameters(prop);
double* params = _params.data();
double* val_ptr = value_ptr();
const int offset = rung();
allowed_op_funcs::sub(feat_1->n_samp(), feat_1->value_ptr(offset + 2), feat_2->value_ptr(offset + 1), params[0], params[1], val_ptr);
if(*std::min_element(val_ptr, val_ptr + _n_samp) > l_bound)
throw InvalidFeatureException();
if(is_nan() || is_const()|| (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound))
throw InvalidFeatureException();
}
AbsDiffParamTopLevNode::AbsDiffParamTopLevNode(node_ptr feat_1, node_ptr feat_2, int feat_ind, std::vector<double>& prop):
AbsDiffParamNode(feat_1, feat_2, feat_ind)
{
_params.resize(n_params(), 0.0);
get_parameters(prop);
}
AbsDiffParamTopLevNode::AbsDiffParamTopLevNode(node_ptr feat_1, node_ptr feat_2, int feat_ind, double l_bound, double u_bound):
AbsDiffParamNode(feat_1, feat_2, feat_ind, l_bound, u_bound)
{
_params.resize(n_params(), 0.0);
}
void AbsDiffParamTopLevNode::set_value(int offset)
{
offset = (offset == -1) ? rung() : offset;
if(_selected)
allowed_op_funcs::abs_diff(_n_samp, _feats[0]->value_ptr(offset + 2), _feats[1]->value_ptr(offset + 1), _params[0], _params[1], node_value_arrs::get_d_matrix_ptr(_d_mat_ind));
allowed_op_funcs::abs_diff(_n_samp, _feats[0]->value_ptr(offset + 2), _feats[1]->value_ptr(offset + 1), _params[0], _params[1], node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset, false));
}
void AbsDiffParamTopLevNode::set_test_value(int offset)
{
offset = (offset == -1) ? rung() : offset;
allowed_op_funcs::abs_diff(_n_test_samp, _feats[0]->test_value_ptr(offset + 2), _feats[1]->test_value_ptr(offset + 1), _params[0], _params[1], node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset, false));
}
void AbsDiffParamTopLevNode::set_bounds(double* lb, double* ub, int from_parent)
{}
/** @file feature_creation/node/operator_nodes/allowed_operator_nodes/abs_diff/parameterize_top_levabsolute_difference.hpp
* @brief Class describing the parameterized absolute difference operator
*
* This class represents the parameterized unary operator -> |A - alpha * B + a|
*
* @author Thomas A. R. Purcell (tpurcell)
* @bug No known bugs.
*/
#ifndef PARAM_TOP_LEV_ABS_DIFF_NODE
#define PARAM_TOP_LEV_ABS_DIFF_NODE
#include <feature_creation/node/operator_nodes/allowed_operator_nodes/abs_diff/parameterized_absolute_difference.hpp>
#include <nl_opt/NLOptWrapper.hpp>
// DocString: cls_abs_node
/**
* @brief ParamNode for the absolute value operator
*
*/
class AbsDiffParamTopLevNode: public AbsDiffParamNode
{
using AbsDiffParamNode::set_value;
using AbsDiffParamNode::set_test_value;
using AbsDiffParamNode::value_ptr;
using AbsDiffParamNode::test_value_ptr;
using AbsDiffParamNode::domain;
using AbsDiffParamNode::expr;
friend class boost::serialization::access;
/**
* @brief Serialization function to send over MPI
*
* @param ar Archive representation of node
*/
template <typename Archive>
void serialize(Archive& ar, const unsigned int version)
{
ar & boost::serialization::base_object<AbsDiffParamNode>(*this);
}
public:
/**
* @brief Base Constructor
* @details This is only used for serialization
*/
AbsDiffParamTopLevNode();
/**
* @brief Constructor
* @details Constructs the ParamNode from node pointer of the feature to operate on
*
* @param feat_1 shared_ptr of the feature to operate on (A)
* @param feat_2 shared_ptr of the feature to operate on (B)
* @param feat_ind Index of the new feature
* @param l_bound Minimum absolute value allowed for the feature.
* @param u_bound Maximum absolute value allowed for the feature.
* @param prop The property to fit to
*/
AbsDiffParamTopLevNode(node_ptr feat_1, node_ptr feat_2, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop);
/**
* @brief Constructor
* @details Constructs the ParamNode from node pointer of the feature to operate on
*
* @param feat_1 shared_ptr of the feature to operate on (A)
* @param feat_2 shared_ptr of the feature to operate on (B)
* @param feat_ind Index of the new feature
* @param prop The property to fit to
*/
AbsDiffParamTopLevNode(node_ptr feat_1, node_ptr feat_2, int feat_ind, std::vector<double>& prop);
/**
* @brief Constructor
* @details Constructs the ParamNode from node pointer of the feature to operate on
*
* @param feat_1 shared_ptr of the feature to operate on (A)
* @param feat_ind Index of the new feature
* @param l_bound Minimum absolute value allowed for the feature.
* @param u_bound Maximum absolute value allowed for the feature.
* @param param_list The list of parameters to optimize using non-linear least squares
* @param prop The property to fit to
*/
AbsDiffParamTopLevNode(node_ptr feat_1, node_ptr feat_2, int feat_ind, double l_bound=1e-50, double u_bound=1e50);
// DocString: abs_diff_param_top_lev_node_n_params
/**
* @brief returns the number of theoretical parameters for this feature
* @return the number of theoretical parameters
*/
inline int n_params(int n_cur = 0){return 2;}
// DocString: abs_diff_param_top_lev_node_set_value
/**
* @brief Set the values of the training data for the feature inside of the value storage arrays
*
* @param offset(int) Key to determine which part of the temporary storage array to look into
*/
void set_value(int offset = -1);
// DocString: abs_diff_param_top_lev_node_set_test_value
/**
* @brief Set the values of the test data for the feature inside of the value storage arrays
*
* @param offset(int) Key to determine which part of the temporary storage array to look into
*/
void set_test_value(int offset = -1);
// DocString: abs_diff_param_top_lev_node_expr
/**
* @brief Get the expression for the overall feature (From root node down)
*/
inline std::string expr(){return "|(" + _feats[0]->expr() + ") - (" + std::to_string(_params[0]) + "*" + _feats[1]->expr() + " + " + std::to_string(_params[1]) + ")|";}
// DocString: abs_diff_param_top_lev_node_domain
/**
* @brief The domain for the feature (min/max values)
*/
inline Domain domain(){return _feats[0]->domain().sub(_feats[1]->domain(), _params[0], _params[1]).abs();}
// DocString: abs_diff_param_top_lev_node_set_bounds
/**
* @brief Set the bounds for the nl parameterization
*