diff --git a/README.md b/README.md index 020f22b..77e4d40 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,9 @@ OpenGM 2 ======== -[![Build Status](https://travis-ci.org/opengm/opengm.png?branch=master)](https://travis-ci.org/opengm/opengm) +[![Build Status](https://travis-ci.org/opengm/opengm.png?branch=master)](https://travis-ci.org/opengm/opengm) (master) + +[![Build Status](https://travis-ci.org/opengm/opengm.png?branch=learning-experimental)](https://travis-ci.org/opengm/opengm) (learning-experimental) ----------------------------------------------------------------------------------------------- diff --git a/include/opengm/functions/learnable/lunary.hxx b/include/opengm/functions/learnable/lunary.hxx index c4cc08a..cc1b930 100644 --- a/include/opengm/functions/learnable/lunary.hxx +++ b/include/opengm/functions/learnable/lunary.hxx @@ -101,8 +101,8 @@ protected: mutable const opengm::learning::Weights * weights_; - opengm::UInt16Type numberOfLabels_; - std::vector offsets_; + IndexType numberOfLabels_; + std::vector offsets_; std::vector weightIds_; std::vector features_; diff --git a/include/opengm/functions/learnable/lweightedsum_of_functions.hxx b/include/opengm/functions/learnable/lweightedsum_of_functions.hxx index f831329..62314f4 100644 --- a/include/opengm/functions/learnable/lweightedsum_of_functions.hxx +++ b/include/opengm/functions/learnable/lweightedsum_of_functions.hxx @@ -77,8 +77,11 @@ LWeightedSumOfFunctions::LWeightedSumOfFunctions : shape_(shape), weights_(&weights), weightIDs_(weightIDs),feat_(feat) { OPENGM_ASSERT( weightIDs_.size() == feat_.size() ); - for(size_t i=0 i @@ -99,7 +102,7 @@ LWeightedSumOfFunctions::weightGradient ITERATOR begin ) const { OPENGM_ASSERT(weightNumber< numberOfWeights()); - return feat_[weightNumber](*begin); + return feat_[weightNumber](begin); } template diff --git a/include/opengm/inference/lp_inference_base.hxx b/include/opengm/inference/lp_inference_base.hxx index 36fc750..cf47706 100644 --- a/include/opengm/inference/lp_inference_base.hxx +++ b/include/opengm/inference/lp_inference_base.hxx @@ -1842,7 +1842,6 @@ inline LPInferenceBase::LPInferenceBase(const GraphicalModelT if(!opengm::meta::Compare::value) { throw RuntimeError("This implementation does only supports Min-Sum-Semiring and Max-Sum-Semiring."); } - // sort factors sortFactors(); diff --git a/include/opengm/inference/lpcplex.hxx b/include/opengm/inference/lpcplex.hxx index 52712c8..07c77f4 100644 --- a/include/opengm/inference/lpcplex.hxx +++ b/include/opengm/inference/lpcplex.hxx @@ -482,7 +482,7 @@ LPCplex::infer break; } - // MIP EMPHASIS + // MIP EMPHASIS switch(parameter_.mipEmphasis_) { case MIP_EMPHASIS_BALANCED: cplex_.setParam(IloCplex::MIPEmphasis, 0); @@ -503,11 +503,11 @@ LPCplex::infer // verbose options if(parameter_.verbose_ == false) { - cplex_.setParam(IloCplex::MIPDisplay, 0); - cplex_.setParam(IloCplex::BarDisplay, 0); - cplex_.setParam(IloCplex::SimDisplay, 0); - cplex_.setParam(IloCplex::NetDisplay, 0); - cplex_.setParam(IloCplex::SiftDisplay, 0); + cplex_.setParam(IloCplex::MIPDisplay, 0); + cplex_.setParam(IloCplex::BarDisplay, 0); + cplex_.setParam(IloCplex::SimDisplay, 0); + cplex_.setParam(IloCplex::NetDisplay, 0); + cplex_.setParam(IloCplex::SiftDisplay, 0); } // tolarance settings @@ -555,11 +555,12 @@ LPCplex::infer //cplex_.setParam(IloCplex::MIRCuts, parameter_.MIRCutLevel_); // solve problem + if(!cplex_.solve()) { std::cout << "failed to optimize. " < + struct RebindGm{ + typedef LPCplex2<_GM, ACC_TYPE> type; + }; + + template + struct RebindGmAndAcc{ + typedef LPCplex2<_GM, _ACC > type; + }; }; template diff --git a/include/opengm/inference/lpgurobi2.hxx b/include/opengm/inference/lpgurobi2.hxx index a9c1a9c..192b038 100644 --- a/include/opengm/inference/lpgurobi2.hxx +++ b/include/opengm/inference/lpgurobi2.hxx @@ -25,6 +25,16 @@ public: // public member functions virtual std::string name() const; + + template + struct RebindGm{ + typedef LPGurobi2<_GM, ACC_TYPE> type; + }; + + template + struct RebindGmAndAcc{ + typedef LPGurobi2<_GM, _ACC > type; + }; }; template diff --git a/include/opengm/learning/bundle-optimizer.hxx b/include/opengm/learning/bundle-optimizer.hxx index 7b020c6..e8e5a7e 100644 --- a/include/opengm/learning/bundle-optimizer.hxx +++ b/include/opengm/learning/bundle-optimizer.hxx @@ -12,14 +12,14 @@ namespace learning { //template //std::ostream& operator<<(std::ostream& out, Weights& w) { - //out << "["; - //for (int i = 0; i < w.numberOfWeights(); i++) { - - //if (i > 0) - //out << ", "; - //out << w[i]; - //} - //out << "]"; +// out << "["; +// for (int i = 0; i < w.numberOfWeights(); i++) { + +// if (i > 0) +// out << ", "; +// out << w[i]; +// } +// out << "]"; //} enum OptimizerResult { @@ -153,15 +153,21 @@ BundleOptimizer::optimize(Oracle& oracle, Weights& w) { unsigned int t = 0; - while (true) { + while (true) { t++; - std::cout << std::endl << "----------------- iteration " << t << std::endl; + if(oracle.getInfParam().verbose_ ) + std::cout << std::endl << "----------------- iteration " << t << std::endl; Weights w_tm1 = w; - //std::cout << "current w is " << w_tm1 << std::endl; + if(oracle.getInfParam().verbose_ ){ + std::cout << "w: "; + for(size_t i=0; i::optimize(Oracle& oracle, Weights& w) { // get current value and gradient oracle(w_tm1, L_w_tm1, a_t); - std::cout << " L(w) is: " << L_w_tm1 << std::endl; - //std::cout << " ∂L(w)/∂ is: " << a_t << std::endl; + if(oracle.getInfParam().verbose_ ){ + std::cout << " L(w) is: " << L_w_tm1 << std::endl; + std::cout << "∂L(w)/∂: ("; + for(size_t i=0; i::optimize(Oracle& oracle, Weights& w) { // minimal value of lower bound T minLower; - // update w and get minimal value + // update w and get minimal value findMinLowerBound(w, minLower); - std::cout << " min_w ℒ(w) + ½λ|w|² is: " << minLower << std::endl; - //std::cout << " w* of ℒ(w) + ½λ|w|² is: " << w << std::endl; + // norm of w + double norm = 0.0; + for(size_t i=0; i::optimize(Oracle& oracle, Weights& w) { lastMinLower = minLower; - std::cout << " ε is: " << eps_t << std::endl; + if(oracle.getInfParam().verbose_ ) + std::cout << " ε is: " << eps_t << std::endl; // converged? if (eps_t <= _parameter.min_eps) diff --git a/include/opengm/learning/gradient-accumulator.hxx b/include/opengm/learning/gradient-accumulator.hxx index f605122..88e920a 100644 --- a/include/opengm/learning/gradient-accumulator.hxx +++ b/include/opengm/learning/gradient-accumulator.hxx @@ -53,9 +53,7 @@ public: for (int i = 0; i < function.numberOfWeights(); i++) { int index = function.weightIndex(i); - double g = function.weightGradient(i, Iter(accessor, 0)); - if (_mode == Add) _gradient[index] += g; else @@ -99,8 +97,6 @@ struct FeatureAccumulator{ } void resetWeights(){ - //accFeaturesGt_ = 0.0; - //accWeights_ = 0.0; for(size_t i=0; i Accessor; typedef opengm::AccessorIterator AccessorIter; - // get the number of weights_ const size_t nWeights = f.numberOfWeights(); if(nWeights>0){ @@ -129,7 +124,6 @@ struct FeatureAccumulator{ const Accessor accessorGt(begin, end, gtLabel_); const Accessor accessorMap(begin, end, mapLabel_); - if(add_){ // for gt label @@ -175,9 +169,6 @@ struct FeatureAccumulator{ double weight_; }; - - - }} // namespace opengm::learning #endif // OPENGM_LEARNING_GRADIENT_ACCUMULATOR_H__ diff --git a/include/opengm/learning/solver/CplexBackend.h b/include/opengm/learning/solver/CplexBackend.h index d330917..feda3f4 100644 --- a/include/opengm/learning/solver/CplexBackend.h +++ b/include/opengm/learning/solver/CplexBackend.h @@ -330,14 +330,14 @@ CplexBackend::solve(Solution& x, double& value, std::string& msg) { std::cerr << "Invalid value for MIP focus!" << std::endl; setNumThreads(_parameter.numThreads); - if(!cplex_.solve()) { std::cout << "failed to optimize. " << cplex_.getStatus() << std::endl; msg = "Optimal solution *NOT* found"; return false; } else - msg = "Optimal solution found"; + if(_parameter.verbose == true) + msg = "Optimal solution found"; // extract solution cplex_.getValues(sol_, x_); @@ -413,12 +413,16 @@ CplexBackend::setVerbose(bool verbose) { cplex_.setParam(IloCplex::MIPDisplay, 1); cplex_.setParam(IloCplex::SimDisplay, 1); cplex_.setParam(IloCplex::SiftDisplay, 1); + cplex_.setParam(IloCplex::BarDisplay, 1); + cplex_.setParam(IloCplex::NetDisplay, 1); } else { cplex_.setParam(IloCplex::MIPDisplay, 0); cplex_.setParam(IloCplex::SimDisplay, 0); cplex_.setParam(IloCplex::SiftDisplay, 0); + cplex_.setParam(IloCplex::BarDisplay, 0); + cplex_.setParam(IloCplex::NetDisplay, 0); } } diff --git a/include/opengm/learning/solver/QuadraticSolverFactory.h b/include/opengm/learning/solver/QuadraticSolverFactory.h index 43ca5bc..e986630 100644 --- a/include/opengm/learning/solver/QuadraticSolverFactory.h +++ b/include/opengm/learning/solver/QuadraticSolverFactory.h @@ -3,7 +3,7 @@ #ifdef WITH_GUROBI #include "GurobiBackend.h" -#elif WITH_CPLEX +#elif defined(WITH_CPLEX) #include "CplexBackend.h" #endif @@ -19,7 +19,7 @@ class QuadraticSolverFactory { #ifdef WITH_GUROBI return new GurobiBackend(); -#elif WITH_CPLEX +#elif defined(WITH_CPLEX) return new CplexBackend(); #endif diff --git a/include/opengm/learning/struct-max-margin.hxx b/include/opengm/learning/struct-max-margin.hxx index 55b03a1..815c0aa 100644 --- a/include/opengm/learning/struct-max-margin.hxx +++ b/include/opengm/learning/struct-max-margin.hxx @@ -5,6 +5,10 @@ #include "bundle-optimizer.hxx" #include "gradient-accumulator.hxx" +#ifdef WITH_OPENMP +#include +#endif + namespace opengm { namespace learning { @@ -100,12 +104,28 @@ private: // set the weights w in E(x,y) and F(x,y) _dataset.getWeights() = w; - for (int i = 0; i < _dataset.getNumberOfModels(); i++) { - - // get E(x,y) and F(x,y) - //std::cout << "locking model " << i << " of " << _dataset.getNumberOfModels() << std::endl; - _dataset.lockModel(i); - const GMType & gm = _dataset.getModel(i); + if(_infParam.verbose_ ) + std::cout << std::endl << " MODEL : "; + + #ifdef WITH_OPENMP + omp_lock_t modelLock; + omp_init_lock(&modelLock); + #pragma omp parallel for + #endif + for (int i = 0; i < _dataset.getNumberOfModels(); i++) { + if(_infParam.verbose_ ) + std::cout << i; + + // lock the model + #ifdef WITH_OPENMP + omp_set_lock(&modelLock); + _dataset.lockModel(i); + omp_unset_lock(&modelLock); + #else + _dataset.lockModel(i); + #endif + // get E(x,y) and F(x,y) + const GMType & gm = _dataset.getModel(i); const GMWITHLOSS & gml = _dataset.getModelWithLoss(i); // get the best-effort solution y' @@ -117,26 +137,39 @@ private: // find the minimizer y* of F(y,w) ConfigurationType mostViolated; InferenceType inference(gml, _infParam); - inference.infer(); - inference.arg(mostViolated); + + inference.infer(); + inference.arg(mostViolated); // the optimal value of (1) is now c - F(y*,w) - value += c - gml.evaluate(mostViolated); + #pragma omp atomic + value += c - gml.evaluate(mostViolated); // the gradients are typedef GradientAccumulator GA; - GA gaBestEffort(gradient, bestEffort, GA::Add); - GA gaMostViolated(gradient, mostViolated, GA::Subtract); - for (size_t j = 0; j < gm.numberOfFactors(); j++) { + GA gaBestEffort(gradient, bestEffort, GA::Add); + GA gaMostViolated(gradient, mostViolated, GA::Subtract); + for (size_t j = 0; j < gm.numberOfFactors(); j++) { gm[j].callViFunctor(gaBestEffort); gm[j].callViFunctor(gaMostViolated); } - _dataset.unlockModel(i); - } + // unlock the model + #ifdef WITH_OPENMP + omp_set_lock(&modelLock); + _dataset.unlockModel(i); + omp_unset_lock(&modelLock); + #else + _dataset.unlockModel(i); + #endif + } // end for model } + const typename InferenceType::Parameter& getInfParam(){ + return _infParam; + } + private: DatasetType& _dataset; diff --git a/src/interfaces/python/opengm/learning/CMakeLists.txt b/src/interfaces/python/opengm/learning/CMakeLists.txt index 05bc47c..a594ea4 100644 --- a/src/interfaces/python/opengm/learning/CMakeLists.txt +++ b/src/interfaces/python/opengm/learning/CMakeLists.txt @@ -24,7 +24,7 @@ set(PY_OPENGM_CORE_SOURCES pyDataset.cxx pyLoss.cxx pyGridSearchLearner.cxx - pyMaxLikelihoodLearner.cxx + #pyMaxLikelihoodLearner.cxx pyStructMaxMarginLearner.cxx pySubgradientSSVM.cxx pyStructPerceptron.cxx diff --git a/src/interfaces/python/opengm/learning/learning.cxx b/src/interfaces/python/opengm/learning/learning.cxx index a45d3a9..195b2ac 100644 --- a/src/interfaces/python/opengm/learning/learning.cxx +++ b/src/interfaces/python/opengm/learning/learning.cxx @@ -37,8 +37,8 @@ namespace opengm{ template void export_struct_max_margin_bundle_learner(const std::string & clsName); - template - void export_max_likelihood_learner(const std::string & clsName); + //template + //void export_max_likelihood_learner(const std::string & clsName); template void export_struct_perceptron_learner(const std::string & clsName); @@ -82,7 +82,7 @@ BOOST_PYTHON_MODULE_INIT(_learning) { opengm::export_grid_search_learner("GridSearch_FlexibleLoss"); opengm::export_struct_perceptron_learner("StructPerceptron_FlexibleLoss"); opengm::export_subgradient_ssvm_learner("SubgradientSSVM_FlexibleLoss"); - opengm::export_max_likelihood_learner("MaxLikelihood_FlexibleLoss"); + //opengm::export_max_likelihood_learner("MaxLikelihood_FlexibleLoss"); opengm::export_rws_learner("Rws_FlexibleLoss"); #if defined(WITH_CPLEX) || defined(WITH_GUROBI) diff --git a/src/unittest/test_gm_learning_functions.cxx b/src/unittest/test_gm_learning_functions.cxx index 653e0d6..b797175 100644 --- a/src/unittest/test_gm_learning_functions.cxx +++ b/src/unittest/test_gm_learning_functions.cxx @@ -40,8 +40,8 @@ struct GraphicalModelTest { ValueType, //value type (should be float double or long double) opengm::Multiplier, //operator (something like Adder or Multiplier) typename opengm::meta::TypeListGenerator< - opengm::ExplicitFunction, - opengm::PottsNFunction + opengm::ExplicitFunction, + opengm::PottsNFunction >::type, //implicit function functor opengm::DiscreteSpace > GraphicalModelType;