Commit 486c4ff7 authored by Davis King's avatar Davis King

Added the svm_c_ekm_trainer object. It's just a simple wrapper

around the empirical_kernel_map and svm_c_linear_trainer.

--HG--
extra : convert_revision : svn%3Afdd8eb12-d10e-0410-9acb-85c331704f74/trunk%403573
parent e59432bb
......@@ -20,6 +20,7 @@
#include "svm/kernel_matrix.h"
#include "svm/empirical_kernel_map.h"
#include "svm/svm_c_linear_trainer.h"
#include "svm/svm_c_ekm_trainer.h"
#endif // DLIB_SVm_HEADER
......
// Copyright (C) 2010 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_SVM_C_EKm_TRAINER_H__
#define DLIB_SVM_C_EKm_TRAINER_H__
#include "../algs.h"
#include "function.h"
#include "kernel.h"
#include "empirical_kernel_map.h"
#include "svm_c_linear_trainer.h"
#include "svm_c_ekm_trainer_abstract.h"
#include "../statistics.h"
#include <vector>
namespace dlib
{
template <
typename K
>
class svm_c_ekm_trainer
{
public:
typedef K kernel_type;
typedef typename kernel_type::scalar_type scalar_type;
typedef typename kernel_type::sample_type sample_type;
typedef typename kernel_type::mem_manager_type mem_manager_type;
typedef decision_function<kernel_type> trained_function_type;
svm_c_ekm_trainer (
)
{
verbose = false;
ekm_stale = true;
}
explicit svm_c_ekm_trainer (
const scalar_type& C
)
{
// make sure requires clause is not broken
DLIB_ASSERT(C > 0,
"\t svm_c_ekm_trainer::svm_c_ekm_trainer()"
<< "\n\t C must be greater than 0"
<< "\n\t C: " << C
<< "\n\t this: " << this
);
ocas.set_c(C);
verbose = false;
ekm_stale = true;
}
void set_epsilon (
scalar_type eps
)
{
// make sure requires clause is not broken
DLIB_ASSERT(eps > 0,
"\t void svm_c_ekm_trainer::set_epsilon()"
<< "\n\t eps must be greater than 0"
<< "\n\t eps: " << eps
<< "\n\t this: " << this
);
ocas.set_epsilon(eps);
}
const scalar_type get_epsilon (
) const
{
return ocas.get_epsilon();
}
void be_verbose (
)
{
verbose = true;
ocas.be_quiet();
}
void be_very_verbose (
)
{
verbose = true;
ocas.be_verbose();
}
void be_quiet (
)
{
verbose = false;
ocas.be_quiet();
}
void set_oca (
const oca& item
)
{
ocas.set_oca(item);
}
const oca get_oca (
) const
{
return ocas.get_oca();
}
const kernel_type get_kernel (
) const
{
return kern;
}
void set_kernel (
const kernel_type& k
)
{
kern = k;
ekm_stale = true;
}
template <typename T>
void set_basis (
const T& basis_samples
)
{
// make sure requires clause is not broken
DLIB_ASSERT(basis_samples.size() > 0 && is_vector(vector_to_matrix(basis_samples)),
"\tvoid svm_c_ekm_trainer::set_basis(basis_samples)"
<< "\n\t You have to give a non-empty set of basis_samples and it must be a vector"
<< "\n\t basis_samples.size(): " << basis_samples.size()
<< "\n\t is_vector(vector_to_matrix(basis_samples)): " << is_vector(vector_to_matrix(basis_samples))
<< "\n\t this: " << this
);
basis = vector_to_matrix(basis_samples);
ekm_stale = true;
}
bool basis_loaded(
) const
{
return (basis.size() != 0);
}
void set_c (
scalar_type C
)
{
// make sure requires clause is not broken
DLIB_ASSERT(C > 0,
"\t void svm_c_ekm_trainer::set_c()"
<< "\n\t C must be greater than 0"
<< "\n\t C: " << C
<< "\n\t this: " << this
);
ocas.set_c(C);
}
const scalar_type get_c_class1 (
) const
{
return ocas.get_c_class1();
}
const scalar_type get_c_class2 (
) const
{
return ocas.get_c_class2();
}
void set_c_class1 (
scalar_type C
)
{
// make sure requires clause is not broken
DLIB_ASSERT(C > 0,
"\t void svm_c_ekm_trainer::set_c_class1()"
<< "\n\t C must be greater than 0"
<< "\n\t C: " << C
<< "\n\t this: " << this
);
ocas.set_c_class1(C);
}
void set_c_class2 (
scalar_type C
)
{
// make sure requires clause is not broken
DLIB_ASSERT(C > 0,
"\t void svm_c_ekm_trainer::set_c_class2()"
<< "\n\t C must be greater than 0"
<< "\n\t C: " << C
<< "\n\t this: " << this
);
ocas.set_c_class2(C);
}
template <
typename in_sample_vector_type,
typename in_scalar_vector_type
>
const decision_function<kernel_type> train (
const in_sample_vector_type& x,
const in_scalar_vector_type& y
) const
{
scalar_type obj;
return do_train(vector_to_matrix(x),vector_to_matrix(y),obj);
}
template <
typename in_sample_vector_type,
typename in_scalar_vector_type
>
const decision_function<kernel_type> train (
const in_sample_vector_type& x,
const in_scalar_vector_type& y,
scalar_type& svm_objective
) const
{
return do_train(vector_to_matrix(x),vector_to_matrix(y),svm_objective);
}
private:
template <
typename in_sample_vector_type,
typename in_scalar_vector_type
>
const decision_function<kernel_type> do_train (
const in_sample_vector_type& x,
const in_scalar_vector_type& y,
scalar_type& svm_objective
) const
{
// make sure requires clause is not broken
DLIB_ASSERT(basis_loaded() == true && is_binary_classification_problem(x,y) == true,
"\t decision_function svm_c_ekm_trainer::train(x,y)"
<< "\n\t invalid inputs were given to this function"
<< "\n\t x.nr(): " << x.nr()
<< "\n\t y.nr(): " << y.nr()
<< "\n\t x.nc(): " << x.nc()
<< "\n\t y.nc(): " << y.nc()
<< "\n\t is_binary_classification_problem(x,y): " << is_binary_classification_problem(x,y)
<< "\n\t basis_loaded(): " << basis_loaded()
);
if (ekm_stale)
{
ekm.load(kern, basis);
ekm_stale = false;
}
// project all the samples with the ekm
running_stats<scalar_type> rs;
std::vector<matrix<scalar_type,0,1, mem_manager_type> > proj_samples;
proj_samples.reserve(x.size());
for (long i = 0; i < x.size(); ++i)
{
if (verbose)
{
scalar_type err;
proj_samples.push_back(ekm.project(x(i), err));
rs.add(err);
}
else
{
proj_samples.push_back(ekm.project(x(i)));
}
}
if (verbose)
{
std::cout << "\nMean EKM projection error: " << rs.mean() << std::endl;
std::cout << "Standard deviaion of EKM projection error: " << rs.stddev() << std::endl;
}
// now do the training
decision_function<linear_kernel<matrix<scalar_type,0,1, mem_manager_type> > > df;
df = ocas.train(proj_samples, y, svm_objective);
if (verbose)
{
std::cout << "Final svm objective: " << svm_objective << std::endl;
}
decision_function<kernel_type> final_df;
final_df = ekm.convert_to_decision_function(df.basis_vectors(0));
final_df.b = df.b;
return final_df;
}
/*!
CONVENTION
- if (ekm_stale) then
- kern or basis have changed since the last time
they were loaded into the ekm
!*/
svm_c_linear_trainer<linear_kernel<matrix<scalar_type,0,1,mem_manager_type> > > ocas;
bool verbose;
kernel_type kern;
matrix<sample_type,0,1,mem_manager_type> basis;
mutable empirical_kernel_map<kernel_type> ekm;
mutable bool ekm_stale;
};
}
#endif // DLIB_SVM_C_EKm_TRAINER_H__
// Copyright (C) 2010 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_SVM_C_EKm_TRAINER_ABSTRACT_H__
#ifdef DLIB_SVM_C_EKm_TRAINER_ABSTRACT_H__
#include "../algs.h"
#include "function_abstract.h"
#include "kernel_abstract.h"
#include "empirical_kernel_map_abstract.h"
#include "svm_c_linear_trainer_abstract.h"
namespace dlib
{
template <
typename K
>
class svm_c_ekm_trainer
{
/*!
REQUIREMENTS ON K
is a kernel function object as defined in dlib/svm/kernel_abstract.h
WHAT THIS OBJECT REPRESENTS
This object represents a tool for training the C formulation of
a support vector machine. It is implemented using the empirical_kernel_map
to kernelize the svm_c_linear_trainer. This makes it a very fast algorithm
but means the user must supply a set of basis vectors.
For details about the "basis vectors" see the empirical_kernel_map
documentation. In particular, see it's example program.
!*/
public:
typedef K kernel_type;
typedef typename kernel_type::scalar_type scalar_type;
typedef typename kernel_type::sample_type sample_type;
typedef typename kernel_type::mem_manager_type mem_manager_type;
typedef decision_function<kernel_type> trained_function_type;
svm_c_ekm_trainer (
);
/*!
ensures
- This object is properly initialized and ready to be used
to train a support vector machine.
- #get_oca() == oca() (i.e. an instance of oca with default parameters)
- #get_c_class1() == 1
- #get_c_class2() == 1
- #get_epsilon() == 0.001
- #basis_loaded() == false
- this object will not be verbose unless be_verbose() is called
!*/
explicit svm_c_ekm_trainer (
const scalar_type& C
);
/*!
requires
- C > 0
ensures
- This object is properly initialized and ready to be used
to train a support vector machine.
- #get_oca() == oca() (i.e. an instance of oca with default parameters)
- #get_c_class1() == C
- #get_c_class2() == C
- #get_epsilon() == 0.001
- #basis_loaded() == false
- this object will not be verbose unless be_verbose() is called
!*/
void set_epsilon (
scalar_type eps
);
/*!
requires
- eps > 0
ensures
- #get_epsilon() == eps
!*/
const scalar_type 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 be_verbose (
);
/*!
ensures
- This object will print status messages to standard out so that a
user can observe the progress of the algorithm.
!*/
void be_very_verbose (
);
/*!
ensures
- This object will print a lot of status messages to standard out so that a
user can observe the progress of the algorithm. In addition to the
few status messages normal verbosity produces this setting also causes
the underlying svm_c_linear_trainer to be verbose.
!*/
void be_quiet (
);
/*!
ensures
- this object will not print anything to standard out
!*/
void set_oca (
const oca& item
);
/*!
ensures
- #get_oca() == item
!*/
const oca get_oca (
) const;
/*!
ensures
- returns a copy of the optimizer used to solve the SVM problem.
!*/
const kernel_type get_kernel (
) const;
/*!
ensures
- returns a copy of the kernel function in use by this object
!*/
void set_kernel (
const kernel_type& k
);
/*!
ensures
- #get_kernel() == k
!*/
template <typename T>
void set_basis (
const T& basis_samples
);
/*!
requires
- T must be a dlib::matrix type or something convertible to a matrix via vector_to_matrix()
(e.g. a std::vector)
- is_vector(basis_samples) == true
- basis_samples.size() > 0
- get_kernel() must be capable of operating on the elements of basis_samples. That is,
expressions such as get_kernel()(basis_samples(0), basis_samples(0)) should make sense.
ensures
- #basis_loaded() == true
!*/
bool basis_size (
) const;
/*!
ensures
- returns true if this object has been loaded with basis vectors and false otherwise.
!*/
void set_c (
scalar_type C
);
/*!
requires
- C > 0
ensures
- #get_c_class1() == C
- #get_c_class2() == C
!*/
const scalar_type get_c_class1 (
) const;
/*!
ensures
- returns the SVM regularization parameter for the +1 class.
It is the parameter that determines the trade off between
trying to fit the +1 training data exactly or allowing more errors
but hopefully improving the generalization ability of the
resulting classifier. Larger values encourage exact fitting
while smaller values of C may encourage better generalization.
!*/
const scalar_type get_c_class2 (
) const;
/*!
ensures
- returns the SVM regularization parameter for the -1 class.
It is the parameter that determines the trade off between
trying to fit the -1 training data exactly or allowing more errors
but hopefully improving the generalization ability of the
resulting classifier. Larger values encourage exact fitting
while smaller values of C may encourage better generalization.
!*/
void set_c_class1 (
scalar_type C
);
/*!
requires
- C > 0
ensures
- #get_c_class1() == C
!*/
void set_c_class2 (
scalar_type C
);
/*!
requires
- C > 0
ensures
- #get_c_class2() == C
!*/
template <
typename in_sample_vector_type,
typename in_scalar_vector_type
>
const decision_function<kernel_type> train (
const in_sample_vector_type& x,
const in_scalar_vector_type& y
) const;
/*!
requires
- basis_loaded() == true
- is_binary_classification_problem(x,y) == true
- x == a matrix or something convertible to a matrix via vector_to_matrix().
Also, x should contain sample_type objects.
- y == a matrix or something convertible to a matrix via vector_to_matrix().
Also, y should contain scalar_type objects.
ensures
- trains a C support vector classifier given the training samples in x and
labels in y.
- returns a decision function F with the following properties:
- if (new_x is a sample predicted have +1 label) then
- F(new_x) >= 0
- else
- F(new_x) < 0
!*/
template <
typename in_sample_vector_type,
typename in_scalar_vector_type
>
const decision_function<kernel_type> train (
const in_sample_vector_type& x,
const in_scalar_vector_type& y,
scalar_type& svm_objective
) const;
/*!
requires
- basis_loaded() == true
- is_binary_classification_problem(x,y) == true
- x == a matrix or something convertible to a matrix via vector_to_matrix().
Also, x should contain sample_type objects.
- y == a matrix or something convertible to a matrix via vector_to_matrix().
Also, y should contain scalar_type objects.
ensures
- trains a C support vector classifier given the training samples in x and
labels in y.
- #svm_objective == the final value of the SVM objective function
- returns a decision function F with the following properties:
- if (new_x is a sample predicted have +1 label) then
- F(new_x) >= 0
- else
- F(new_x) < 0
!*/
};
}
#endif // DLIB_SVM_C_EKm_TRAINER_ABSTRACT_H__
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