diff --git a/fastlib2/contrib/nvasil/convex_nmf/main.cc b/fastlib2/contrib/nvasil/convex_nmf/main.cc index b1eff0220d..d3bbf2a7dd 100644 --- a/fastlib2/contrib/nvasil/convex_nmf/main.cc +++ b/fastlib2/contrib/nvasil/convex_nmf/main.cc @@ -5,14 +5,14 @@ int main(int argc, char *argv[]) { fx_module *fx_root; fx_root=fx_init(argc, argv, NULL); fx_module *nmf_module=fx_submodule(fx_root, "/engine"); - NmfEngine engine; + NmfEngine engine; fx_set_param_str(nmf_module, "data_file", - "/net/hg200/nvasil/dataset/orl_faces/orl_test_faces_100.csv"); - fx_set_param_int(nmf_module, "sdp_rank",1 ); + "/net/hg200/nvasil/dataset/orl_faces/orl_test_faces_474.csv"); + fx_set_param_int(nmf_module, "sdp_rank", 4); fx_set_param_int(nmf_module, "new_dim", 20); - fx_set_param_double(nmf_module, "l_bfgs/sigma", 0.010); + fx_set_param_double(nmf_module, "l_bfgs/sigma", 0.1); fx_set_param_double(nmf_module, "l_bfgs/norm_grad_tolerance", 10); - fx_set_param_double(nmf_module, "l_bfgs/desired_feasibility", 1); + fx_set_param_double(nmf_module, "l_bfgs/desired_feasibility", 5); fx_set_param_double(nmf_module, "l_bfgs/feasibility_tolerance", 0.01); fx_set_param_int(nmf_module, "l_bfgs/mem_bfgs", 5); engine.Init(nmf_module); diff --git a/fastlib2/contrib/nvasil/convex_nmf/nmf_engine.h b/fastlib2/contrib/nvasil/convex_nmf/nmf_engine.h index 24ce696f2d..59cdd24272 100644 --- a/fastlib2/contrib/nvasil/convex_nmf/nmf_engine.h +++ b/fastlib2/contrib/nvasil/convex_nmf/nmf_engine.h @@ -4,6 +4,7 @@ #include "../l_bfgs/l_bfgs.h" #include "nmf_objectives.h" +template class NmfEngine { public: void Init(fx_module *module) { @@ -59,44 +60,55 @@ class NmfEngine { FATAL("Svd failed soething is wrong...\n"); } bool negative_flag=false; + index_t positives=0; + index_t negatives=0; + index_t zeros=0; for (index_t i=0; i0) { + positives++; } - if (negative_flag==true && vt_mat.get(0, i)>0) { - NONFATAL("Method failed, first eigenvector has positive and negative elements"); - break; - } - } - if (negative_flag==true) { - la::Scale(-1, &vt_mat); - } - opt_function_.Project(&vt_mat); - for(index_t i=0; i=positives) { + la::Scale(-1, &vt_mat); + } + OptUtils::NonNegativeProjection(&vt_mat); + for(index_t i=0; iCopy(w_mat_); } @@ -106,8 +118,8 @@ class NmfEngine { private: fx_module *module_; - LBfgs engine_; - BigSdpNmfObjective opt_function_; + LBfgs engine_; + NmfObjective opt_function_; ArrayList rows_; ArrayList columns_; ArrayList values_; diff --git a/fastlib2/contrib/nvasil/convex_nmf/nmf_objectives.h b/fastlib2/contrib/nvasil/convex_nmf/nmf_objectives.h index 789968e8fc..4873cd24aa 100644 --- a/fastlib2/contrib/nvasil/convex_nmf/nmf_objectives.h +++ b/fastlib2/contrib/nvasil/convex_nmf/nmf_objectives.h @@ -3,7 +3,7 @@ #include "fastlib/fastlib.h" #include "../l_bfgs/optimization_utils.h" -class BigSdpNmfObjective { +class BigSdpNmfObjectiveMaxVar { public: void Init(fx_module *module, ArrayList &rows, @@ -33,7 +33,71 @@ class BigSdpNmfObjective { ArrayList columns_; ArrayList values_; Vector eq_lagrange_mult_; +}; +class BigSdpNmfObjectiveMinVar { + public: + void Init(fx_module *module, + ArrayList &rows, + ArrayList &columns, + ArrayList &values); + void Destruct(); + void ComputeGradient(Matrix &coordinates, Matrix *gradient); + void ComputeObjective(Matrix &coordinates, double *objective); + void ComputeFeasibilityError(Matrix &coordinates, double *error); + double ComputeLagrangian(Matrix &coordinates); + void UpdateLagrangeMult(Matrix &coordinates); + void Project(Matrix *coordinates); + void set_sigma(double sigma); + void GiveInitMatrix(Matrix *init_data); + bool IsDiverging(double objective); + + private: + fx_module *module_; + double sigma_; + index_t num_of_columns_; + index_t num_of_rows_; + index_t new_dim_; + index_t rank_; + index_t offset_h_; + index_t offset_h_mat_; // we need this to know wher h matrix starts + ArrayList rows_; + ArrayList columns_; + ArrayList values_; + Vector eq_lagrange_mult_; +}; + + +class BigSdpNmfObjectiveMinVarIneq { + public: + void Init(fx_module *module, + ArrayList &rows, + ArrayList &columns, + ArrayList &values); + void Destruct(); + void ComputeGradient(Matrix &coordinates, Matrix *gradient); + void ComputeObjective(Matrix &coordinates, double *objective); + void ComputeFeasibilityError(Matrix &coordinates, double *error); + double ComputeLagrangian(Matrix &coordinates); + void UpdateLagrangeMult(Matrix &coordinates); + void Project(Matrix *coordinates); + void set_sigma(double sigma); + void GiveInitMatrix(Matrix *init_data); + bool IsDiverging(double objective); + + private: + fx_module *module_; + double sigma_; + index_t num_of_columns_; + index_t num_of_rows_; + index_t new_dim_; + index_t rank_; + index_t offset_h_; + index_t offset_h_mat_; // we need this to know wher h matrix starts + ArrayList rows_; + ArrayList columns_; + ArrayList values_; + Vector ineqeq_lagrange_mult_; }; #include "nmf_objectives_impl.h" diff --git a/fastlib2/contrib/nvasil/convex_nmf/nmf_objectives_impl.h b/fastlib2/contrib/nvasil/convex_nmf/nmf_objectives_impl.h index 8462b0900a..a311de34db 100644 --- a/fastlib2/contrib/nvasil/convex_nmf/nmf_objectives_impl.h +++ b/fastlib2/contrib/nvasil/convex_nmf/nmf_objectives_impl.h @@ -1,33 +1,33 @@ -void BigSdpNmfObjective::Init(fx_module *module, +void BigSdpNmfObjectiveMaxVar::Init(fx_module *module, ArrayList &rows, ArrayList &columns, ArrayList &values) { module_=module; - rows_.InitCopy(rows); + new_dim_=fx_param_int(module_, "new_dim", 5); + rank_=fx_param_int(module_, "rank", 3); + rows_.InitCopy(rows); columns_.InitCopy(columns); values_.InitCopy(values); num_of_rows_=*std::max_element(rows_.begin(), rows_.end())+1; num_of_columns_=*std::max_element(columns_.begin(), columns_.end())+1; eq_lagrange_mult_.Init(values_.size()); - for(index_t i=0; iCopyValues(coordinates); - la::Scale(2.0, gradient); + la::Scale(-2.0, gradient); + // Gradient on the equalities and inequalities for(index_t i=0; iGetColumnPtr(h)); la::AddExpert(rank_*new_dim_, -eq_lagrange_mult_[i]+2*sigma_*diff, coordinates.GetColumnPtr(h), gradient->GetColumnPtr(w)); - } - + } } -void BigSdpNmfObjective::ComputeObjective(Matrix &coordinates, double *objective) { +void BigSdpNmfObjectiveMaxVar::ComputeObjective(Matrix &coordinates, double *objective) { *objective=0; - for(index_t i=0; in_cols(); i++) { - for(index_t j=0; j< coordinates->n_rows(); j++) { - if (coordinates->get(j, i)<0.0) { - coordinates->set(j, i, 0.0); - } - } - } - /* Matrix u_mat, vt_mat; - Vector s; - success_t success=la::SVDInit(*coordinates, &s, &u_mat, &vt_mat); - if (success==SUCCESS_FAIL) { - FATAL("Svd failed...\n"); - } - index_t positives=0; - index_t negatives=0; - for(index_t i=0; i=negatives) { - for(index_t i=0; i0) { - vt_mat.set(0, i, vt_mat.get(0, i)); - } - } - } - - Matrix s_mat; - s_mat.Init(s.length(), s.length()); - s_mat.SetDiagonal(s); - Matrix tmp; - coordinates->Destruct(); - la::MulInit(u_mat, s_mat, &tmp); - la::MulInit(tmp, vt_mat, coordinates); -*/ - +void BigSdpNmfObjectiveMaxVar::Project(Matrix *coordinates) { + OptUtils::NonNegativeProjection(coordinates); } -void BigSdpNmfObjective::set_sigma(double sigma) { +void BigSdpNmfObjectiveMaxVar::set_sigma(double sigma) { sigma_=sigma; } -void BigSdpNmfObjective::GiveInitMatrix(Matrix *init_data) { +void BigSdpNmfObjectiveMaxVar::GiveInitMatrix(Matrix *init_data) { init_data->Init(rank_, (num_of_rows_+num_of_columns_)*new_dim_); for(index_t i=0; in_rows(); i++) { for(index_t j=0; jn_cols(); j++) { @@ -150,7 +106,240 @@ void BigSdpNmfObjective::GiveInitMatrix(Matrix *init_data) { } -bool BigSdpNmfObjective::IsDiverging(double objective) { +bool BigSdpNmfObjectiveMaxVar::IsDiverging(double objective) { return false; } +/////////////////////////////////////////////////////////////////////////// + +void BigSdpNmfObjectiveMinVar::Init(fx_module *module, + ArrayList &rows, + ArrayList &columns, + ArrayList &values) { + module_=module; + new_dim_=fx_param_int(module_, "new_dim", 5); + rank_=fx_param_int(module_, "rank", 3); + rows_.InitCopy(rows); + columns_.InitCopy(columns); + values_.InitCopy(values); + num_of_rows_=*std::max_element(rows_.begin(), rows_.end())+1; + num_of_columns_=*std::max_element(columns_.begin(), columns_.end())+1; + eq_lagrange_mult_.Init(values_.size()); + eq_lagrange_mult_.SetAll(0); + offset_h_ = num_of_rows_*new_dim_; +} + +void BigSdpNmfObjectiveMinVar::Destruct() { + rows_.Renew(); + columns_.Renew(); + values_.Renew(); + eq_lagrange_mult_.Destruct(); +} + +void BigSdpNmfObjectiveMinVar::ComputeGradient(Matrix &coordinates, + Matrix *gradient) { + // gradient of the variance + gradient->CopyValues(coordinates); + la::Scale(2.0, gradient); + // Gradient on the equalities and inequalities + for(index_t i=0; iGetColumnPtr(h)); + la::AddExpert(rank_*new_dim_, -eq_lagrange_mult_[i]+2*sigma_*diff, + coordinates.GetColumnPtr(h), gradient->GetColumnPtr(w)); + } +} + +void BigSdpNmfObjectiveMinVar::ComputeObjective(Matrix &coordinates, + double *objective) { + *objective=0; + for(index_t i=0; iInit(rank_, (num_of_rows_+num_of_columns_)*new_dim_); + for(index_t i=0; in_rows(); i++) { + for(index_t j=0; jn_cols(); j++) { + init_data->set(i, j, math::Random()); + } + } +} + + +bool BigSdpNmfObjectiveMinVar::IsDiverging(double objective) { + return false; +} + +/////////////////////////////////////////////////////////////////////////////// +void BigSdpNmfObjectiveMinVarIneq::Init(fx_module *module, + ArrayList &rows, + ArrayList &columns, + ArrayList &values) { + module_=module; + new_dim_=fx_param_int(module_, "new_dim", 5); + rank_=fx_param_int(module_, "rank", 3); + rows_.InitCopy(rows); + columns_.InitCopy(columns); + values_.InitCopy(values); + num_of_rows_=*std::max_element(rows_.begin(), rows_.end())+1; + num_of_columns_=*std::max_element(columns_.begin(), columns_.end())+1; + eq_lagrange_mult_.Init(values_.size()); + eq_lagrange_mult_.SetAll(0); + offset_h_ = num_of_rows_*new_dim_; +} + +void BigSdpNmfObjectiveMinVar::Destruct() { + rows_.Renew(); + columns_.Renew(); + values_.Renew(); + eq_lagrange_mult_.Destruct(); +} + +void BigSdpNmfObjectiveMinVarIneq::ComputeGradient(Matrix &coordinates, + Matrix *gradient) { + // gradient of the variance + gradient->CopyValues(coordinates); + la::Scale(2.0, gradient); + // Gradient on the equalities and inequalities + for(index_t i=0; iGetColumnPtr(h)); + la::AddExpert(rank_*new_dim_, -eq_lagrange_mult_[i]+2*sigma_*diff, + coordinates.GetColumnPtr(h), gradient->GetColumnPtr(w)); + } +} + +void BigSdpNmfObjectiveMinVarIneq::ComputeObjective(Matrix &coordinates, + double *objective) { + *objective=0; + for(index_t i=0; iInit(rank_, (num_of_rows_+num_of_columns_)*new_dim_); + for(index_t i=0; in_rows(); i++) { + for(index_t j=0; jn_cols(); j++) { + init_data->set(i, j, math::Random()); + } + } +} + + +bool BigSdpNmfObjectiveMinVarIneq::IsDiverging(double objective) { + return false; +} + +