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.
This commit is contained in:
Davis King 2012-12-05 23:11:55 -05:00
parent 3956330d1f
commit 55d21096de
6 changed files with 114 additions and 39 deletions

View File

@ -75,6 +75,23 @@ namespace dlib
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.
!*/
};
// ----------------------------------------------------------------------------------------

View File

@ -0,0 +1,76 @@
// 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__

View File

@ -146,6 +146,23 @@ namespace dlib
- 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.
!*/
};
// ----------------------------------------------------------------------------------------

View File

@ -7,6 +7,7 @@
#include "../algs.h"
#include "../optimization.h"
#include "structural_svm_assignment_problem.h"
#include "num_nonnegative_weights.h"
namespace dlib
@ -55,16 +56,6 @@ namespace dlib
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 (
double eps_
)
@ -193,13 +184,7 @@ namespace dlib
matrix<double,0,1> weights;
unsigned long num_nonnegative = 0;
if (learn_nonnegative_weights)
{
num_nonnegative = fe.num_features();
}
solver(prob, weights, num_nonnegative);
solver(prob, weights, num_nonnegative_weights(fe));
return assignment_function<feature_extractor>(weights,fe,force_assignment);
@ -208,7 +193,6 @@ namespace dlib
private:
bool learn_nonnegative_weights;
bool force_assignment;
double C;
oca solver;
@ -225,7 +209,6 @@ namespace dlib
eps = 0.1;
num_threads = 2;
max_cache_size = 40;
learn_nonnegative_weights = false;
}
feature_extractor fe;

View File

@ -52,7 +52,6 @@ namespace dlib
- #get_max_cache_size() == 40
- #get_feature_extractor() == a default initialized feature_extractor
- #forces_assignment() == false
- #learns_nonnegative_weights() == false
!*/
explicit structural_assignment_trainer (
@ -67,7 +66,6 @@ namespace dlib
- #get_max_cache_size() == 40
- #get_feature_extractor() == fe
- #forces_assignment() == false
- #learns_nonnegative_weights() == false
!*/
const feature_extractor& get_feature_extractor (
@ -164,23 +162,6 @@ namespace dlib
- 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 (
double C
);

View File

@ -7,6 +7,7 @@
#include "../algs.h"
#include "../optimization.h"
#include "structural_svm_sequence_labeling_problem.h"
#include "num_nonnegative_weights.h"
namespace dlib
@ -219,7 +220,7 @@ namespace dlib
for (unsigned long i = 0; i < loss_values.size(); ++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);
}