Commit 55d21096 authored by Davis King's avatar Davis King
Browse files

Changed the feature extraction interfaces for the sequence labeling and

assignment problem learning tools to also include an optional
num_nonnegative_weights() method.  This method can be used to tell any machine
learning tools which elements of the learned parameter vector should be
non-negative.  As part of this change, I also removed the previous methods for
doing this from the structural_assignment_trainer since they are now redundant.
parent 3956330d
...@@ -75,6 +75,23 @@ namespace dlib ...@@ -75,6 +75,23 @@ namespace dlib
is "good"). is "good").
!*/ !*/
unsigned long num_nonnegative_weights (
) const;
/*!
ensures
- returns the number of elements of the w parameter vector which should be
non-negative. That is, this feature extractor is intended to be used
with w vectors where the first num_nonnegative_weights() elements of w
are >= 0. That is, it should be the case that w(i) >= 0 for all i <
num_nonnegative_weights().
- Note that num_nonnegative_weights() is just an optional method to allow
you to tell a tool like the structural_assignment_trainer that the
learned w should have a certain number of non-negative elements.
Therefore, if you do not provide a num_nonnegative_weights() method in
your feature extractor then it will default to a value of 0, indicating
that all elements of the w parameter vector may be any value.
!*/
}; };
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
......
// Copyright (C) 2012 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_NUM_NONNEGATIVE_WEIGHtS_H__
#define DLIB_NUM_NONNEGATIVE_WEIGHtS_H__
#include "../enable_if.h"
namespace dlib
{
namespace impl2
{
template <
typename T,
unsigned long (T::*funct)()const
>
struct hnnf_helper
{
typedef char type;
};
template <typename T>
char has_num_nonnegative_weights_helper( typename hnnf_helper<T,&T::num_nonnegative_weights>::type = 0 ) { return 0;}
struct two_bytes
{
char a[2];
};
template <typename T>
two_bytes has_num_nonnegative_weights_helper(int) { return two_bytes();}
template <typename T>
struct work_around_visual_studio_bug
{
const static unsigned long U = sizeof(has_num_nonnegative_weights_helper<T>('a'));
};
// This is a template to tell you if a feature_extractor has a num_nonnegative_weights function or not.
template <typename T, unsigned long U = work_around_visual_studio_bug<T>::U >
struct has_num_nonnegative_weights
{
static const bool value = false;
};
template <typename T>
struct has_num_nonnegative_weights <T,1>
{
static const bool value = true;
};
}
// call fe.num_nonnegative_weights() if it exists, otherwise return 0.
template <typename feature_extractor>
typename enable_if<impl2::has_num_nonnegative_weights<feature_extractor>,unsigned long>::type num_nonnegative_weights (
const feature_extractor& fe
)
{
return fe.num_nonnegative_weights();
}
template <typename feature_extractor>
typename disable_if<impl2::has_num_nonnegative_weights<feature_extractor>,unsigned long>::type num_nonnegative_weights (
const feature_extractor& /*fe*/
)
{
return 0;
}
}
#endif // DLIB_NUM_NONNEGATIVE_WEIGHtS_H__
...@@ -146,6 +146,23 @@ namespace dlib ...@@ -146,6 +146,23 @@ namespace dlib
- This function only calls set_feature() with feature_index values < num_features() - This function only calls set_feature() with feature_index values < num_features()
!*/ !*/
unsigned long num_nonnegative_weights (
) const;
/*!
ensures
- returns the number of elements of the w parameter vector which should be
non-negative. That is, this feature extractor is intended to be used
with w vectors where the first num_nonnegative_weights() elements of w
are >= 0. That is, it should be the case that w(i) >= 0 for all i <
num_nonnegative_weights().
- Note that num_nonnegative_weights() is just an optional method to allow
you to tell a tool like the structural_sequence_labeling_trainer that the
learned w should have a certain number of non-negative elements.
Therefore, if you do not provide a num_nonnegative_weights() method in
your feature extractor then it will default to a value of 0, indicating
that all elements of the w parameter vector may be any value.
!*/
}; };
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "../algs.h" #include "../algs.h"
#include "../optimization.h" #include "../optimization.h"
#include "structural_svm_assignment_problem.h" #include "structural_svm_assignment_problem.h"
#include "num_nonnegative_weights.h"
namespace dlib namespace dlib
...@@ -55,16 +56,6 @@ namespace dlib ...@@ -55,16 +56,6 @@ namespace dlib
return num_threads; return num_threads;
} }
bool learns_nonnegative_weights (
) const { return learn_nonnegative_weights; }
void set_learns_nonnegative_weights (
bool value
)
{
learn_nonnegative_weights = value;
}
void set_epsilon ( void set_epsilon (
double eps_ double eps_
) )
...@@ -193,13 +184,7 @@ namespace dlib ...@@ -193,13 +184,7 @@ namespace dlib
matrix<double,0,1> weights; matrix<double,0,1> weights;
unsigned long num_nonnegative = 0; solver(prob, weights, num_nonnegative_weights(fe));
if (learn_nonnegative_weights)
{
num_nonnegative = fe.num_features();
}
solver(prob, weights, num_nonnegative);
return assignment_function<feature_extractor>(weights,fe,force_assignment); return assignment_function<feature_extractor>(weights,fe,force_assignment);
...@@ -208,7 +193,6 @@ namespace dlib ...@@ -208,7 +193,6 @@ namespace dlib
private: private:
bool learn_nonnegative_weights;
bool force_assignment; bool force_assignment;
double C; double C;
oca solver; oca solver;
...@@ -225,7 +209,6 @@ namespace dlib ...@@ -225,7 +209,6 @@ namespace dlib
eps = 0.1; eps = 0.1;
num_threads = 2; num_threads = 2;
max_cache_size = 40; max_cache_size = 40;
learn_nonnegative_weights = false;
} }
feature_extractor fe; feature_extractor fe;
......
...@@ -52,7 +52,6 @@ namespace dlib ...@@ -52,7 +52,6 @@ namespace dlib
- #get_max_cache_size() == 40 - #get_max_cache_size() == 40
- #get_feature_extractor() == a default initialized feature_extractor - #get_feature_extractor() == a default initialized feature_extractor
- #forces_assignment() == false - #forces_assignment() == false
- #learns_nonnegative_weights() == false
!*/ !*/
explicit structural_assignment_trainer ( explicit structural_assignment_trainer (
...@@ -67,7 +66,6 @@ namespace dlib ...@@ -67,7 +66,6 @@ namespace dlib
- #get_max_cache_size() == 40 - #get_max_cache_size() == 40
- #get_feature_extractor() == fe - #get_feature_extractor() == fe
- #forces_assignment() == false - #forces_assignment() == false
- #learns_nonnegative_weights() == false
!*/ !*/
const feature_extractor& get_feature_extractor ( const feature_extractor& get_feature_extractor (
...@@ -164,23 +162,6 @@ namespace dlib ...@@ -164,23 +162,6 @@ namespace dlib
- returns a copy of the optimizer used to solve the structural SVM problem. - returns a copy of the optimizer used to solve the structural SVM problem.
!*/ !*/
bool learns_nonnegative_weights (
) const;
/*!
ensures
- The output of training is a weight vector that defines the behavior of an
assignment_function object. If learns_nonnegative_weights() == true then
the resulting weight vector will always have non-negative entries.
!*/
void set_learns_nonnegative_weights (
bool value
);
/*!
ensures
- #learns_nonnegative_weights() == value
!*/
void set_c ( void set_c (
double C double C
); );
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "../algs.h" #include "../algs.h"
#include "../optimization.h" #include "../optimization.h"
#include "structural_svm_sequence_labeling_problem.h" #include "structural_svm_sequence_labeling_problem.h"
#include "num_nonnegative_weights.h"
namespace dlib namespace dlib
...@@ -219,7 +220,7 @@ namespace dlib ...@@ -219,7 +220,7 @@ namespace dlib
for (unsigned long i = 0; i < loss_values.size(); ++i) for (unsigned long i = 0; i < loss_values.size(); ++i)
prob.set_loss(i,loss_values[i]); prob.set_loss(i,loss_values[i]);
solver(prob, weights); solver(prob, weights, num_nonnegative_weights(fe));
return sequence_labeler<feature_extractor>(weights,fe); return sequence_labeler<feature_extractor>(weights,fe);
} }
......
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