307 lines
11 KiB
C++
307 lines
11 KiB
C++
// Copyright (C) 2013 Davis E. King (davis@dlib.net)
|
|
// License: Boost Software License See LICENSE.txt for the full license.
|
|
#undef DLIB_VECTOR_NORMALIZER_FRoBMETRIC_ABSTRACT_Hh_
|
|
#ifdef DLIB_VECTOR_NORMALIZER_FRoBMETRIC_ABSTRACT_Hh_
|
|
|
|
#include "../matrix.h"
|
|
|
|
namespace dlib
|
|
{
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
template <
|
|
typename matrix_type
|
|
>
|
|
struct frobmetric_training_sample
|
|
{
|
|
/*!
|
|
WHAT THIS OBJECT REPRESENTS
|
|
This object represents a training data sample for the
|
|
vector_normalizer_frobmetric object. It defines a set of training triplets
|
|
relative to a single anchor_vect vector. That is, it specifies that the
|
|
learned distance metric should satisfy num_triples() constraints which are,
|
|
for all valid i and j:
|
|
length(T*anchor_vect-T*near_vects[i]) + 1 < length(T*anchor_vect - T*far_vects[j])
|
|
for some appropriate linear transformation T which will be learned by
|
|
vector_normalizer_frobmetric.
|
|
!*/
|
|
|
|
matrix_type anchor_vect;
|
|
std::vector<matrix_type> near_vects;
|
|
std::vector<matrix_type> far_vects;
|
|
|
|
unsigned long num_triples (
|
|
) const { return near_vects.size() * far_vects.size(); }
|
|
/*!
|
|
ensures
|
|
- returns the number of training triplets defined by this object.
|
|
!*/
|
|
|
|
void clear()
|
|
/*!
|
|
ensures
|
|
- #near_vects.size() == 0
|
|
- #far_vects.size() == 0
|
|
!*/
|
|
};
|
|
|
|
template < typename matrix_type >
|
|
void serialize(const frobmetric_training_sample<matrix_type>& item, std::ostream& out)
|
|
template < typename matrix_type >
|
|
void deserialize(frobmetric_training_sample<matrix_type>& item, std::istream& in)
|
|
/*!
|
|
provides serialisation support.
|
|
!*/
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
template <
|
|
typename matrix_type
|
|
>
|
|
class vector_normalizer_frobmetric
|
|
{
|
|
/*!
|
|
REQUIREMENTS ON matrix_type
|
|
- must be a dlib::matrix object capable of representing column
|
|
vectors
|
|
|
|
INITIAL VALUE
|
|
- in_vector_size() == 0
|
|
- out_vector_size() == 0
|
|
- get_epsilon() == 0.1
|
|
- get_c() == 1
|
|
- get_max_iterations() == 5000
|
|
- This object is not verbose
|
|
|
|
WHAT THIS OBJECT REPRESENTS
|
|
This object is a tool for performing the FrobMetric distance metric
|
|
learning algorithm described in the following paper:
|
|
A Scalable Dual Approach to Semidefinite Metric Learning
|
|
By Chunhua Shen, Junae Kim, Lei Wang, in CVPR 2011
|
|
|
|
Therefore, this object is a tool that takes as input training triplets
|
|
(anchor_vect, near, far) of vectors and attempts to learn a linear
|
|
transformation T such that:
|
|
length(T*anchor_vect-T*near) + 1 < length(T*anchor_vect - T*far)
|
|
That is, you give a bunch of anchor_vect vectors and for each anchor_vect
|
|
you specify some vectors which should be near to it and some that should be
|
|
far form it. This object then tries to find a transformation matrix that
|
|
makes the "near" vectors close to their anchors while the "far" vectors are
|
|
farther away.
|
|
|
|
THREAD SAFETY
|
|
Note that this object contains a cached matrix object it uses
|
|
to store intermediate results for normalization. This avoids
|
|
needing to reallocate it every time this object performs normalization
|
|
but also makes it non-thread safe. So make sure you don't share
|
|
instances of this object between threads.
|
|
!*/
|
|
|
|
public:
|
|
typedef typename matrix_type::mem_manager_type mem_manager_type;
|
|
typedef typename matrix_type::type scalar_type;
|
|
typedef matrix_type result_type;
|
|
|
|
vector_normalizer_frobmetric (
|
|
);
|
|
/*!
|
|
ensures
|
|
- this object is properly initialized
|
|
!*/
|
|
|
|
void be_verbose(
|
|
);
|
|
/*!
|
|
ensures
|
|
- This object will print status messages to standard out so the user can
|
|
observe the progress of the train() routine.
|
|
!*/
|
|
|
|
void be_quiet (
|
|
);
|
|
/*!
|
|
ensures
|
|
- this object will not print anything to standard out.
|
|
!*/
|
|
|
|
void set_epsilon (
|
|
double eps
|
|
);
|
|
/*!
|
|
requires
|
|
- eps > 0
|
|
ensures
|
|
- #get_epsilon() == eps
|
|
!*/
|
|
|
|
double get_epsilon (
|
|
) const;
|
|
/*!
|
|
ensures
|
|
- returns the error epsilon that determines when training should stop.
|
|
Smaller values may result in a more accurate solution but take longer to
|
|
execute.
|
|
!*/
|
|
|
|
void set_c (
|
|
double C
|
|
);
|
|
/*!
|
|
requires
|
|
- C > 0
|
|
ensures
|
|
- #set_c() == C
|
|
!*/
|
|
|
|
double get_c (
|
|
) const;
|
|
/*!
|
|
ensures
|
|
- returns the regularization parameter. It is the parameter that
|
|
determines the trade-off between trying to fit the training data exactly
|
|
or allowing more errors but hopefully improving the generalization of the
|
|
resulting distance metric. Larger values encourage exact fitting while
|
|
smaller values of C may encourage better generalization.
|
|
!*/
|
|
|
|
void set_max_iterations (
|
|
unsigned long max_iterations
|
|
);
|
|
/*!
|
|
ensures
|
|
- #get_max_iterations() == max_iterations
|
|
!*/
|
|
|
|
unsigned long get_max_iterations (
|
|
) const;
|
|
/*!
|
|
ensures
|
|
- The train() routine uses an iterative numerical solver to find the best
|
|
distance metric. This function returns the maximum allowable number of
|
|
iterations it will use before terminating. Note that typically the
|
|
solver terminates prior to the max iteration count limit due to the error
|
|
dropping below get_epsilon().
|
|
!*/
|
|
|
|
void train (
|
|
const std::vector<frobmetric_training_sample<matrix_type> >& samples
|
|
);
|
|
/*!
|
|
requires
|
|
- samples.size() != 0
|
|
- All matrices inside samples (i.e. anchors and elements of near_vects and far_vects)
|
|
are column vectors with the same non-zero dimension.
|
|
- All the vectors in samples contain finite values.
|
|
- All elements of samples contain data, specifically, for all valid i:
|
|
- samples[i].num_triples() != 0
|
|
ensures
|
|
- learns a distance metric from the given training samples. After train
|
|
finishes you can use this object's operator() to transform vectors
|
|
according to the learned distance metric. In particular, we will have:
|
|
- #transform() == The linear transformation learned by the FrobMetric
|
|
learning procedure.
|
|
- #in_vector_size() == samples[0].anchor_vect.size()
|
|
- You can call (*this)(x) to transform a vector according to the learned
|
|
distance metric. That is, it should generally be the case that:
|
|
- length((*this)(anchor_vect) - (*this)(near)) + 1 < length((*this)(anchor_vect) - (*this)(far))
|
|
for the anchor_vect, near, and far vectors in the training data.
|
|
- #transformed_means() == the mean of the input anchor_vect vectors
|
|
after being transformed by #transform()
|
|
!*/
|
|
|
|
long in_vector_size (
|
|
) const;
|
|
/*!
|
|
ensures
|
|
- returns the number of rows that input vectors are required to contain if
|
|
they are to be normalized by this object.
|
|
!*/
|
|
|
|
long out_vector_size (
|
|
) const;
|
|
/*!
|
|
ensures
|
|
- returns the number of rows in the normalized vectors that come out of
|
|
this object.
|
|
- The value returned is always in_vector_size(). So out_vector_size() is
|
|
just provided to maintain interface consistency with other vector
|
|
normalizer objects. That is, the transformations applied by this object
|
|
do not change the dimensionality of the vectors.
|
|
!*/
|
|
|
|
const matrix<scalar_type,0,1,mem_manager_type>& transformed_means (
|
|
) const;
|
|
/*!
|
|
ensures
|
|
- returns a column vector V such that:
|
|
- V.size() == in_vector_size()
|
|
- V is a vector such that subtracting it from transformed vectors
|
|
results in them having an expected value of 0. Therefore, it is
|
|
equal to transform() times the mean of the input anchor_vect vectors
|
|
given to train().
|
|
!*/
|
|
|
|
const matrix<scalar_type,0,0,mem_manager_type>& transform (
|
|
) const;
|
|
/*!
|
|
ensures
|
|
- returns a copy of the transformation matrix we learned during the last
|
|
call to train().
|
|
- The returned matrix is square and has in_vector_size() by in_vector_size()
|
|
dimensions.
|
|
!*/
|
|
|
|
const result_type& operator() (
|
|
const matrix_type& x
|
|
) const;
|
|
/*!
|
|
requires
|
|
- in_vector_size() != 0
|
|
- in_vector_size() == x.size()
|
|
- is_col_vector(x) == true
|
|
ensures
|
|
- returns a normalized version of x, call it Z, that has the following
|
|
properties:
|
|
- Z == The result of applying the linear transform we learned during
|
|
train() to the input vector x.
|
|
- Z == transform()*x-transformed_means()
|
|
- is_col_vector(Z) == true
|
|
- Z.size() == x.size()
|
|
- The expected value of each element of Z is 0.
|
|
!*/
|
|
};
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
template <
|
|
typename matrix_type
|
|
>
|
|
void serialize (
|
|
const vector_normalizer_frobmetric<matrix_type>& item,
|
|
std::ostream& out
|
|
);
|
|
/*!
|
|
provides serialization support
|
|
!*/
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
template <
|
|
typename matrix_type
|
|
>
|
|
void deserialize (
|
|
vector_normalizer_frobmetric<matrix_type>& item,
|
|
std::istream& in
|
|
);
|
|
/*!
|
|
provides deserialization support
|
|
!*/
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
}
|
|
|
|
#endif // DLIB_VECTOR_NORMALIZER_FRoBMETRIC_ABSTRACT_Hh_
|
|
|