Commit 53e4efab authored by Davis King's avatar Davis King

Added a version of the structural_svm_problem which can use multiple threads to

call the separation_oracle() function.

--HG--
extra : convert_revision : svn%3Afdd8eb12-d10e-0410-9acb-85c331704f74/trunk%404264
parent dbb6533d
...@@ -222,6 +222,22 @@ namespace dlib ...@@ -222,6 +222,22 @@ namespace dlib
subgradient = psi_true; subgradient = psi_true;
scalar_type total_loss = 0; scalar_type total_loss = 0;
call_separation_oracle_on_all_samples(w,subgradient,total_loss);
subgradient /= num;
total_loss /= num;
// Include a sanity check that the risk is always non-negative.
risk = std::max<scalar_type>(total_loss + dot(subgradient,w), 0);
}
virtual void call_separation_oracle_on_all_samples (
matrix_type& w,
matrix_type& subgradient,
scalar_type& total_loss
) const
{
feature_vector_type ftemp;
const unsigned long num = get_num_samples();
for (unsigned long i = 0; i < num; ++i) for (unsigned long i = 0; i < num; ++i)
{ {
scalar_type loss; scalar_type loss;
...@@ -229,13 +245,9 @@ namespace dlib ...@@ -229,13 +245,9 @@ namespace dlib
total_loss += loss; total_loss += loss;
sparse_vector::add_to(subgradient, ftemp); sparse_vector::add_to(subgradient, ftemp);
} }
subgradient /= num;
total_loss /= num;
// Include a sanity check that the risk is always non-negative.
risk = std::max<scalar_type>(total_loss + dot(subgradient,w), 0);
} }
protected:
void separation_oracle_cached ( void separation_oracle_cached (
const long idx, const long idx,
const matrix_type& current_solution, const matrix_type& current_solution,
...@@ -312,6 +324,7 @@ namespace dlib ...@@ -312,6 +324,7 @@ namespace dlib
} }
} }
} }
private:
struct cache_record struct cache_record
{ {
......
// Copyright (C) 2011 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_STRUCTURAL_SVM_PRObLEM_THREADED_H__
#define DLIB_STRUCTURAL_SVM_PRObLEM_THREADED_H__
#include "structural_svm_problem_threaded_abstract.h"
#include "../algs.h"
#include <vector>
#include "structural_svm_problem.h"
#include "../matrix.h"
#include "sparse_vector.h"
#include <iostream>
#include "../threads.h"
namespace dlib
{
// ----------------------------------------------------------------------------------------
template <
typename matrix_type,
typename feature_vector_type_ = matrix_type
>
class structural_svm_problem_threaded : public structural_svm_problem<matrix_type,feature_vector_type_>
{
public:
typedef typename matrix_type::type scalar_type;
typedef feature_vector_type_ feature_vector_type;
explicit structural_svm_problem_threaded (
unsigned long num_threads
) :
tp(num_threads)
{}
private:
struct binder
{
binder (
const structural_svm_problem_threaded& self_,
matrix_type& w_,
matrix_type& subgradient_,
scalar_type& total_loss_
) : self(self_), w(w_), subgradient(subgradient_), total_loss(total_loss_) {}
void call_oracle (
long i
)
{
scalar_type loss;
feature_vector_type ftemp;
self.separation_oracle_cached(i, w, loss, ftemp);
auto_mutex lock(self.accum_mutex);
total_loss += loss;
sparse_vector::add_to(subgradient, ftemp);
}
const structural_svm_problem_threaded& self;
matrix_type& w;
matrix_type& subgradient;
scalar_type& total_loss;
};
virtual void call_separation_oracle_on_all_samples (
matrix_type& w,
matrix_type& subgradient,
scalar_type& total_loss
) const
{
const long num = this->get_num_samples();
binder b(*this, w, subgradient, total_loss);
for (long i = 0; i < num; ++i)
{
tp.add_task(b, &binder::call_oracle, i);
}
tp.wait_for_all_tasks();
}
mutable thread_pool tp;
mutable mutex accum_mutex;
};
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_STRUCTURAL_SVM_PRObLEM_THREADED_H__
// Copyright (C) 2011 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_STRUCTURAL_SVM_PRObLEM_THREADED_ABSTRACT_H__
#ifdef DLIB_STRUCTURAL_SVM_PRObLEM_THREADED_ABSTRACT_H__
#include "structural_svm_problem_abstract.h"
#include "../matrix.h"
namespace dlib
{
// ----------------------------------------------------------------------------------------
template <
typename matrix_type,
typename feature_vector_type_ = matrix_type
>
class structural_svm_problem_threaded : public structural_svm_problem<matrix_type,feature_vector_type_>
{
public:
/*!
WHAT THIS OBJECT REPRESENTS
This object is identical to the structural_svm_problem object defined in
dlib/svm/structural_svm_problem_abstract.h except that its constructor
takes a number which defines how many threads will be used to make concurrent
calls to the separation_oracle() routine.
So this object lets you take advantage of a multi-core system. You should
set the num_threads parameter equal to the number of available cores. Note
that the separation_oracle() function which you provide must be thread safe
if you are to use this version of the structural_svm_problem.
!*/
typedef typename matrix_type::type scalar_type;
typedef feature_vector_type_ feature_vector_type;
structural_svm_problem (
unsigned long num_threads
);
/*!
ensures
- this object is properly initialized
- This object will use num_threads threads at a time to call the
separation_oracle() function.
!*/
};
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_STRUCTURAL_SVM_PRObLEM_THREADED_ABSTRACT_H__
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "svm.h" #include "svm.h"
#include "svm/svm_threaded.h" #include "svm/svm_threaded.h"
#include "svm/structural_svm_problem_threaded.h"
#endif // DLIB_SVm_THREADED_HEADER #endif // DLIB_SVm_THREADED_HEADER
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment