Commit c49e76ad authored by Davis King's avatar Davis King

Changed the load() function's signature so that it works with

any type at all so long as it is convertible to a matrix via vector_to_matrix().

--HG--
extra : convert_revision : svn%3Afdd8eb12-d10e-0410-9acb-85c331704f74/trunk%403426
parent 125f6eb8
......@@ -62,92 +62,13 @@ namespace dlib
empirical_kernel_map().swap(*this);
}
template <typename T>
void load(
const kernel_type& kernel_,
const std::vector<sample_type>& basis_samples
const T& basis_samples
)
{
load(kernel_, vector_to_matrix(basis_samples));
}
template <typename EXP>
void load(
const kernel_type& kernel_,
const matrix_exp<EXP>& basis_samples
)
{
// make sure requires clause is not broken
DLIB_ASSERT(basis_samples.size() > 0 && is_vector(basis_samples),
"\tvoid empirical_kernel_map::load(kernel,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(basis_samples): " << is_vector(basis_samples)
<< "\n\t this: " << this
);
// clear out the weights before we begin. This way if an exception throws
// this object will already be in the right state.
weights.set_size(0,0);
kernel = kernel_;
basis.clear();
basis.reserve(basis_samples.size());
// find out the value of the largest norm of the elements in basis_samples.
const scalar_type max_norm = max(diag(kernel_matrix(kernel, basis_samples)));
// we will consider anything less than or equal to this number to be 0
const scalar_type eps = max_norm*100*std::numeric_limits<scalar_type>::epsilon();
// Copy all the basis_samples into basis but make sure we don't copy any samples
// that have length 0
for (long i = 0; i < basis_samples.size(); ++i)
{
const scalar_type norm = kernel(basis_samples(i), basis_samples(i));
if (norm > eps)
{
basis.push_back(basis_samples(i));
}
}
if (basis.size() == 0)
{
clear();
throw empirical_kernel_map_error("All basis_samples given to empirical_kernel_map::load() were zero vectors");
}
matrix<scalar_type,0,0,mem_manager_type> K(kernel_matrix(kernel, basis)), U,W,V;
if (svd2(false,true,K,U,W,V))
{
clear();
throw empirical_kernel_map_error("While loading empirical_kernel_map with data, SVD failed to converge.");
}
// now count how many elements of W are non-zero
const long num_not_zero = static_cast<long>(sum(W>eps));
// Really, this should never happen. But I'm checking for good measure.
if (num_not_zero == 0)
{
clear();
throw empirical_kernel_map_error("While loading empirical_kernel_map with data, SVD failed");
}
weights.set_size(num_not_zero, basis.size());
// now fill the weights matrix with the output of the SVD
long counter = 0;
for (long i =0; i < W.size(); ++i)
{
double val = W(i);
if (val > eps)
{
val = std::sqrt(val);
set_rowm(weights,counter) = rowm(trans(V),i)/val;
++counter;
}
}
load_impl(kernel_, vector_to_matrix(basis_samples));
}
const kernel_type get_kernel (
......@@ -310,6 +231,87 @@ namespace dlib
private:
template <typename T>
void load_impl(
const kernel_type& kernel_,
const T& basis_samples
)
{
// make sure requires clause is not broken
DLIB_ASSERT(basis_samples.size() > 0 && is_vector(basis_samples),
"\tvoid empirical_kernel_map::load(kernel,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(basis_samples): " << is_vector(basis_samples)
<< "\n\t this: " << this
);
// clear out the weights before we begin. This way if an exception throws
// this object will already be in the right state.
weights.set_size(0,0);
kernel = kernel_;
basis.clear();
basis.reserve(basis_samples.size());
// find out the value of the largest norm of the elements in basis_samples.
const scalar_type max_norm = max(diag(kernel_matrix(kernel, basis_samples)));
// we will consider anything less than or equal to this number to be 0
const scalar_type eps = max_norm*100*std::numeric_limits<scalar_type>::epsilon();
// Copy all the basis_samples into basis but make sure we don't copy any samples
// that have length 0
for (long i = 0; i < basis_samples.size(); ++i)
{
const scalar_type norm = kernel(basis_samples(i), basis_samples(i));
if (norm > eps)
{
basis.push_back(basis_samples(i));
}
}
if (basis.size() == 0)
{
clear();
throw empirical_kernel_map_error("All basis_samples given to empirical_kernel_map::load() were zero vectors");
}
matrix<scalar_type,0,0,mem_manager_type> K(kernel_matrix(kernel, basis)), U,W,V;
if (svd2(false,true,K,U,W,V))
{
clear();
throw empirical_kernel_map_error("While loading empirical_kernel_map with data, SVD failed to converge.");
}
// now count how many elements of W are non-zero
const long num_not_zero = static_cast<long>(sum(W>eps));
// Really, this should never happen. But I'm checking for good measure.
if (num_not_zero == 0)
{
clear();
throw empirical_kernel_map_error("While loading empirical_kernel_map with data, SVD failed");
}
weights.set_size(num_not_zero, basis.size());
// now fill the weights matrix with the output of the SVD
long counter = 0;
for (long i =0; i < W.size(); ++i)
{
double val = W(i);
if (val > eps)
{
val = std::sqrt(val);
set_rowm(weights,counter) = rowm(trans(V),i)/val;
++counter;
}
}
}
std::vector<sample_type> basis;
matrix<scalar_type,0,0,mem_manager_type> weights;
kernel_type kernel;
......
......@@ -115,13 +115,15 @@ namespace dlib
- this object has its initial value
!*/
template <typename EXP>
template <typename T>
void load(
const kernel_type& kernel,
const matrix_exp<EXP>& basis_samples
const T& basis_samples
);
/*!
requires
- T must be a dlib::matrix type or something convertable to a matrix via vector_to_matrix()
(e.g. a std::vector)
- is_vector(basis_samples) == true
- basis_samples.size() > 0
- kernel must be capable of operating on the elements of basis_samples. That is,
......@@ -140,19 +142,6 @@ namespace dlib
If this happens then this object will revert back to its initial value.
!*/
void load(
const kernel_type& kernel,
const std::vector<sample_type>& basis_samples
);
/*!
requires
- basis_samples.size() > 0
ensures
- performs load(kernel,vector_to_matrix(basis_samples)). I.e. This function
does the exact same thing as the above load() function but lets you use
a std::vector of basis samples instead of a row/column matrix of basis samples.
!*/
const kernel_type get_kernel (
) const;
/*!
......
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