[opengm] 70/386: fixed gradient computation in struct-max-margin, re-enabled test
Ghislain Vaillant
ghisvail-guest at moszumanska.debian.org
Wed Aug 31 08:35:06 UTC 2016
This is an automated email from the git hooks/post-receive script.
ghisvail-guest pushed a commit to branch debian/master
in repository opengm.
commit 7194ff36c56e26f92f75280b27ed4756319141c3
Author: Jan Funke <funke at ini.ch>
Date: Tue Dec 16 16:04:21 2014 +0100
fixed gradient computation in struct-max-margin, re-enabled test
---
include/opengm/learning/gradient-accumulator.hxx | 24 +++-
include/opengm/learning/struct-max-margin.hxx | 74 +++++++++---
src/unittest/CMakeLists.txt | 10 +-
src/unittest/test_learning.cxx | 143 +++--------------------
4 files changed, 104 insertions(+), 147 deletions(-)
diff --git a/include/opengm/learning/gradient-accumulator.hxx b/include/opengm/learning/gradient-accumulator.hxx
index fd54314..151967c 100644
--- a/include/opengm/learning/gradient-accumulator.hxx
+++ b/include/opengm/learning/gradient-accumulator.hxx
@@ -14,14 +14,25 @@ class GradientAccumulator {
public:
/**
+ * How to accumulate the gradient on the provided ModelWeights.
+ */
+ enum Mode {
+
+ Add,
+
+ Subtract
+ };
+
+ /**
* @param gradient
* ModelWeights reference to store the gradients.
* @param configuration
* Current configuration of the variables in the model.
*/
- GradientAccumulator(ModelWeights& gradient, ConfigurationType& configuration) :
+ GradientAccumulator(ModelWeights& gradient, const ConfigurationType& configuration, Mode mode = Add) :
_gradient(gradient),
- _configuration(configuration) {
+ _configuration(configuration),
+ _mode(mode) {
for (size_t i = 0; i < gradient.numberOfWeights(); i++)
gradient[i] = 0;
@@ -34,14 +45,19 @@ public:
int index = function.weightIndex(i);
- _gradient[index] += function.weightGradient(i, _configuration.begin());
+ double g = function.weightGradient(i, _configuration.begin());
+ if (_mode == Add)
+ _gradient[index] += g;
+ else
+ _gradient[index] -= g;
}
}
private:
ModelWeights& _gradient;
- ConfigurationType& _configuration;
+ const ConfigurationType& _configuration;
+ Mode _mode;
};
}} // namespace opengm::learning
diff --git a/include/opengm/learning/struct-max-margin.hxx b/include/opengm/learning/struct-max-margin.hxx
index a6d0321..e5b3baf 100644
--- a/include/opengm/learning/struct-max-margin.hxx
+++ b/include/opengm/learning/struct-max-margin.hxx
@@ -65,29 +65,77 @@ private:
typedef std::vector<typename InferenceType::LabelType> ConfigurationType;
- // initialize gradient with zero
+ // initialize gradient and value with zero
+ for (int i = 0; i < gradient.numberOfWeights(); i++)
+ gradient[i] = 0;
+ value = 0;
+
+ // For each model E(y,w), we have to compute the value and
+ // gradient of
+ //
+ // max_y E(y',w) - E(y,w) + Δ(y',y) (1)
+ // =
+ // max_y L(y,w)
+ //
+ // where y' is the best-effort solution (also known as
+ // groundtruth) and w are the current weights. The loss
+ // augmented model given by the dataset is
+ //
+ // F(y,w) = E(y,w) - Δ(y',y).
+ //
+ // Let c = E(y',w) be the constant contribution of the
+ // best-effort solution. (1) is equal to
+ //
+ // -min_y -c + F(y,w).
+ //
+ // The gradient of the maximand in (1) at y* is
+ //
+ // ∂L(y,w)/∂w = ∂E(y',w)/∂w -
+ // ∂E(y,w)/∂w
+ //
+ // = Σ_θ ∂θ(y'_θ,w)/∂w -
+ // Σ_θ ∂θ(y_θ,w)/∂w,
+ //
+ // which is a positive gradient contribution for the
+ // best-effort, and a negative contribution for the maximizer
+ // y*.
for (int i = 0; i < _dataset.getNumberOfModels(); i++) {
- // NOT IMPLEMENTED, YET
- //_dataset.lockModel(i);
- //const typename DatasetType::GMWITHLOSS& gm = _dataset.getModelWithLoss(i);
- const typename DatasetType::GMType& gm = _dataset.getModel(i);
+ // get E(x,y) and F(x,y)
+ _dataset.lockModel(i);
+ const typename DatasetType::GMType& gm = _dataset.getModel(i);
+ const typename DatasetType::GMWITHLOSS& gml = _dataset.getModelWithLoss(i);
+ // set the weights w in E(x,y) and F(x,y)
_dataset.getWeights() = w;
- InferenceType inference(gm);
+ // get the best-effort solution y'
+ const ConfigurationType& bestEffort = _dataset.getGT(i);
- ConfigurationType configuration;
+ // compute constant c for current w
+ ValueType c = gm.evaluate(bestEffort);
+
+ // find the minimizer y* of F(y,w)
+ ConfigurationType mostViolated;
+ InferenceType inference(gml);
inference.infer();
- inference.arg(configuration);
+ inference.arg(mostViolated);
+
+ // the optimal value of (1) is now c - F(y*,w)
+ value += c - gml.evaluate(mostViolated);
+
+ // the gradients are
+ typedef GradientAccumulator<Weights, ConfigurationType> GA;
+ GA gaBestEffort(gradient, bestEffort, GA::Add);
+ GA gaMostViolated(gradient, mostViolated, GA::Subtract);
+ for (size_t j = 0; j < gm.numberOfFactors(); j++) {
- GradientAccumulator<Weights, ConfigurationType> ga(gradient, configuration);
- for (size_t i = 0; i < gm.numberOfFactors(); i++)
- gm[i].callFunctor(ga);
+ gm[j].callFunctor(gaBestEffort);
+ gm[j].callFunctor(gaMostViolated);
+ }
- // NOT IMPLEMENTED, YET
- //_dataset.unlockModel(i);
+ _dataset.unlockModel(i);
}
}
diff --git a/src/unittest/CMakeLists.txt b/src/unittest/CMakeLists.txt
index 7eeb1eb..535880b 100644
--- a/src/unittest/CMakeLists.txt
+++ b/src/unittest/CMakeLists.txt
@@ -80,11 +80,11 @@ if(BUILD_TESTING)
endif()
# Loop forever - fix and move to subfolder learning
-# if(WITH_GUROBI)
-# ADD_EXECUTABLE(test-learning test_learning.cxx ${headers})
-# target_link_libraries(test-learning ${GUROBI_CXX_LIBRARY} ${GUROBI_LIBRARY})
-# add_test(test-learning ${CMAKE_CURRENT_BINARY_DIR}/test-learning)
-# endif()
+ if(WITH_GUROBI)
+ ADD_EXECUTABLE(test-learning test_learning.cxx ${headers})
+ target_link_libraries(test-learning ${GUROBI_CXX_LIBRARY} ${GUROBI_LIBRARY})
+ add_test(test-learning ${CMAKE_CURRENT_BINARY_DIR}/test-learning)
+ endif()
add_subdirectory(inference)
add_subdirectory(learning)
diff --git a/src/unittest/test_learning.cxx b/src/unittest/test_learning.cxx
index a101aeb..ec69b10 100644
--- a/src/unittest/test_learning.cxx
+++ b/src/unittest/test_learning.cxx
@@ -12,8 +12,9 @@
#include <opengm/functions/learnable/sum_of_experts.hxx>
#include <opengm/learning/struct-max-margin.hxx>
#include <opengm/learning/loss/hammingloss.hxx>
-#include <opengm/learning/dataset/testdataset.hxx>
-#include <opengm/learning/dataset/testdataset2.hxx>
+//#include <opengm/learning/dataset/testdataset.hxx>
+//#include <opengm/learning/dataset/testdataset2.hxx>
+#include <opengm/learning/dataset/testdatasets.hxx>
//*************************************
@@ -22,142 +23,30 @@ typedef size_t IndexType;
typedef size_t LabelType;
typedef opengm::meta::TypeListGenerator<opengm::ExplicitFunction<ValueType,IndexType,LabelType>, opengm::functions::learnable::LPotts<ValueType,IndexType,LabelType>, opengm::functions::learnable::SumOfExperts<ValueType,IndexType,LabelType> >::type FunctionListType;
typedef opengm::GraphicalModel<ValueType,opengm::Adder, FunctionListType, opengm::DiscreteSpace<IndexType,LabelType> > GM;
-typedef opengm::datasets::TestDataset<GM> DS;
-typedef opengm::datasets::TestDataset2<GM> DS2;
+//typedef opengm::datasets::TestDataset<GM> DS;
+//typedef opengm::datasets::TestDataset2<GM> DS2;
typedef opengm::learning::HammingLoss LOSS;
typedef opengm::ICM<GM,opengm::Minimizer> INF;
+typedef opengm::datasets::TestDataset1<GM,LOSS> DS1;
+typedef opengm::datasets::TestDataset2<GM,LOSS> DS2;
//*************************************
-template<class T>
-struct LearningTest{
-
- typedef T ValueType;
- typedef OPENGM_TYPELIST_2(
- opengm::ExplicitFunction<T>,
- opengm::functions::learnable::LPotts<T>) FunctionTypeList;
- typedef opengm::GraphicalModel<ValueType, opengm::Adder, FunctionTypeList> GraphicalModelType;
- typedef opengm::datasets::TestDataset<GraphicalModelType> DatasetType;
- typedef typename DatasetType::Weights Weights;
- typedef opengm::learning::HammingLoss LossGeneratorType;
- typedef opengm::Bruteforce<GraphicalModelType, opengm::Minimizer> InferenceType;
-
- void testStructMaxMargin()
- {
-
- // create a dataset
- DatasetType dataset;
-
- // create a learning algorithm
- opengm::learning::StructMaxMargin<DatasetType, LossGeneratorType> structMaxMargin(dataset);
-
- // train
- typename InferenceType::Parameter infParams;
- structMaxMargin.template learn<InferenceType>(infParams);
-
- // get the result
- const Weights &learntParameters = structMaxMargin.getWeights();
- std::cout << learntParameters.numberOfWeights() << std::endl;
- for (size_t i = 0; i < learntParameters.numberOfWeights(); ++i)
- std::cout << learntParameters[i] << " ";
- std::cout << std::endl;
- }
-
-
- void testStructMaxMargin_prediction()
- {
-
- // create a dataset
- DatasetType dataset;
-
- std::vector< std::vector<size_t> >GTSolutionVector;
-
- std::cout << "inference with fixed, arbitrary weights to generate solution" << std::endl;
-
- Weights weightVector = dataset.getWeights();
- // std::srand(std::time(0));
-
- for (int i = 0; i < weightVector.numberOfWeights(); i++)
- {
- weightVector.setWeight(i, double(std::rand()) / RAND_MAX * 100);
- std::cout << weightVector[i] << std::endl;
- }
-
- for (size_t modelIndex = 0; modelIndex < dataset.getNumberOfModels(); modelIndex++)
- {
-
- std::cout << "starting inference on GM " << modelIndex << std::endl;
- InferenceType solver(dataset.getModel(modelIndex));
- solver.infer();
- std::vector<size_t> sol1;
- OPENGM_TEST(solver.arg(sol1) == opengm::NORMAL);
- GTSolutionVector.push_back(sol1);
- std::cout << "add solution to GM " << modelIndex << std::endl;
- for (size_t j = 0; j < sol1.size(); j++)
- {
- // TODO: find way to set GT weights
- // dataset.getGT(modelIndex)[j] = sol1[j]; does not work
- }
- }
-
- std::cout << "learn weights (without regularization)" << std::endl;
- // create a learning algorithm
- opengm::learning::StructMaxMargin<DatasetType, LossGeneratorType> structMaxMargin(dataset);
- // train
- typename InferenceType::Parameter infParams;
- structMaxMargin.template learn<InferenceType>(infParams);
-
- // get the result
- const Weights &learntParameters = structMaxMargin.getWeights();
- std::cout << learntParameters.numberOfWeights() << std::endl;
- std::cout << "learntParameters: ";
- for (size_t i = 0; i < learntParameters.numberOfWeights(); ++i)
- {
- std::cout << learntParameters[i] << " ";
- weightVector.setWeight(i, learntParameters[i]);
- }
- std::cout << std::endl;
-
- std::cout << "inference with new weights" << std::endl;
- for (size_t modelIndex = 0; modelIndex < dataset.getNumberOfModels(); modelIndex++)
- {
- std::cout << "starting inference on GM " << modelIndex << "with learned weights" << std::endl;
- InferenceType solver(dataset.getModel(modelIndex));
- solver.infer();
- std::vector<size_t> sol2;
- OPENGM_TEST(solver.arg(sol2) == opengm::NORMAL);
- for (size_t j = 0; j < sol2.size(); j++)
- {
- OPENGM_TEST(sol2[j] == GTSolutionVector[modelIndex][j]);
- }
- }
- }
-
- void run()
- {
- this->testStructMaxMargin();
- this->testStructMaxMargin_prediction();
- }
-};
int main() {
std::cout << " Includes are fine :-) " << std::endl;
-
- // {
- // LearningTest<double >t;
- // t.run();
- // }
-
- {
- DS dataset;
+ {
+ DS1 dataset;
std::cout << "Dataset includes " << dataset.getNumberOfModels() << " instances and has " << dataset.getNumberOfWeights() << " parameters."<<std::endl;
- opengm::learning::StructMaxMargin<DS,LOSS> learner(dataset);
+ opengm::learning::StructMaxMargin<DS1,LOSS>::Parameter para;
+ opengm::learning::StructMaxMargin<DS1,LOSS> learner(dataset,para);
INF::Parameter infPara;
learner.learn<INF>(infPara);
+
}
{
@@ -165,10 +54,14 @@ int main() {
std::cout << "Dataset includes " << dataset.getNumberOfModels() << " instances and has " << dataset.getNumberOfWeights() << " parameters."<<std::endl;
- opengm::learning::StructMaxMargin<DS2,LOSS> learner(dataset);
+ opengm::learning::StructMaxMargin<DS2,LOSS>::Parameter para;
+ opengm::learning::StructMaxMargin<DS2,LOSS> learner(dataset,para);
INF::Parameter infPara;
learner.learn<INF>(infPara);
}
-}
\ No newline at end of file
+
+
+}
+
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/opengm.git
More information about the debian-science-commits
mailing list