mirror of https://github.com/davisking/dlib.git
Added the get_transformation_to() function to the empirical_kernel_map. I also changed the
epsilon value used to tell if something is essentially zero to a more reasonable value. --HG-- extra : convert_revision : svn%3Afdd8eb12-d10e-0410-9acb-85c331704f74/trunk%403369
This commit is contained in:
parent
a5e6f0a714
commit
8f26951cc8
|
@ -95,7 +95,7 @@ namespace dlib
|
|||
// 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*std::numeric_limits<scalar_type>::epsilon();
|
||||
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
|
||||
|
@ -218,6 +218,25 @@ namespace dlib
|
|||
return projection_function<kernel_type>(weights, kernel, vector_to_matrix(basis));
|
||||
}
|
||||
|
||||
const matrix<scalar_type,0,0,mem_manager_type> get_transformation_to (
|
||||
const empirical_kernel_map& target
|
||||
) const
|
||||
{
|
||||
// make sure requires clause is not broken
|
||||
DLIB_ASSERT(out_vector_size() != 0 &&
|
||||
target.out_vector_size() != 0 &&
|
||||
get_kernel() == target.get_kernel(),
|
||||
"\t const matrix empirical_kernel_map::get_transformation_to(target)"
|
||||
<< "\n\t Invalid inputs were given to this function"
|
||||
<< "\n\t out_vector_size(): " << out_vector_size()
|
||||
<< "\n\t target.out_vector_size(): " << target.out_vector_size()
|
||||
<< "\n\t get_kernel()==target.get_kernel(): " << (get_kernel()==target.get_kernel())
|
||||
<< "\n\t this: " << this
|
||||
);
|
||||
|
||||
return target.weights * kernel_matrix(target.get_kernel(),target.basis, basis)*trans(weights);
|
||||
}
|
||||
|
||||
const matrix<scalar_type,0,1,mem_manager_type>& project (
|
||||
const sample_type& samp
|
||||
) const
|
||||
|
|
|
@ -256,6 +256,37 @@ namespace dlib
|
|||
this->project() on that sample.
|
||||
!*/
|
||||
|
||||
const matrix<scalar_type,0,0,mem_manager_type> get_transformation_to (
|
||||
const empirical_kernel_map& target
|
||||
) const;
|
||||
/*!
|
||||
requires
|
||||
- get_kernel() == target.get_kernel()
|
||||
- out_vector_size() != 0
|
||||
- target.out_vector_size() != 0
|
||||
ensures
|
||||
- A point in the kernel feature space defined by the kernel get_kernel() typically
|
||||
has different representations with respect to different empirical_kernel_maps.
|
||||
This function lets you obtain a transformation matrix that will allow you
|
||||
to map between these different representations. That is, this function returns
|
||||
a matrix M with the following properties:
|
||||
- M maps vectors represented according to *this into the representation used by target.
|
||||
- M.nr() == target.out_vector_size()
|
||||
- M.nc() == this->out_vector_size()
|
||||
- Let V be a vector of this->out_vector_size() length. Then define two distance_functions
|
||||
DF1 = this->convert_to_distance_function(V)
|
||||
DF2 = target.convert_to_distance_function(M*V)
|
||||
|
||||
Then DF1(DF2) == 0 // i.e. the distance between these two points should be 0
|
||||
|
||||
That is, DF1 and DF2 both represent the same point in kernel feature space. Note
|
||||
that the above equality is only approximate. If the vector V represents a point in
|
||||
kernel space that isn't in the span of the basis samples used by target then the
|
||||
equality is approximate. However, if it is in their span then the equality will
|
||||
be exact. For example, if target's basis samples are a superset of the basis samples
|
||||
used by *this then the equality will always be exact (within rounding error).
|
||||
!*/
|
||||
|
||||
void swap (
|
||||
empirical_kernel_map& item
|
||||
);
|
||||
|
|
|
@ -96,7 +96,7 @@ namespace
|
|||
|
||||
// make sure the distances match
|
||||
const double dist_error = abs(length(proj_samples[idx1] - proj_samples[idx2]) - dist_funct(samples[idx2]));
|
||||
DLIB_TEST_MSG( dist_error < 1e-7, dist_error);
|
||||
DLIB_TEST_MSG( dist_error < 1e-6, dist_error);
|
||||
// make sure the dot products match
|
||||
DLIB_TEST(abs(dot(proj_samples[idx1],proj_samples[idx2]) - dec_funct(samples[idx2])) < 1e-10);
|
||||
|
||||
|
@ -160,6 +160,87 @@ namespace
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
for (int j = 1; j <= 20; ++j)
|
||||
{
|
||||
dlog << LTRACE << "j: " << j;
|
||||
sample_type samp, samp2;
|
||||
std::vector<sample_type> samples1;
|
||||
std::vector<sample_type> samples2;
|
||||
print_spinner();
|
||||
// make some random samples. At the end samples1 will be a subset of samples2
|
||||
for (int i = 0; i < 5*j; ++i)
|
||||
{
|
||||
samples1.push_back(randm(10,1,rnd));
|
||||
samples2.push_back(samples1.back());
|
||||
}
|
||||
for (int i = 0; i < 5*j; ++i)
|
||||
{
|
||||
samples2.push_back(randm(10,1,rnd));
|
||||
}
|
||||
// add on a little bit to make sure there is at least one non-zero sample. If all the
|
||||
// samples are zero then empirical_kernel_map_error will be thrown and we don't want that.
|
||||
samples1.front()(0) += 0.001;
|
||||
samples2.front()(0) += 0.001;
|
||||
|
||||
ekm.load(kern, samples1);
|
||||
ekm2.load(kern, samples2);
|
||||
|
||||
dlog << LTRACE << "ekm.out_vector_size(): " << ekm.out_vector_size();
|
||||
dlog << LTRACE << "ekm2.out_vector_size(): " << ekm2.out_vector_size();
|
||||
const double eps = 1e-6;
|
||||
|
||||
matrix<double> transform;
|
||||
// Make sure transformations back to yourself work right. Note that we can't just
|
||||
// check that transform is the identity matrix since it might be an identity transform
|
||||
// for only a subspace of vectors (this happens if the ekm maps points into a subspace of
|
||||
// all possible ekm.out_vector_size() vectors).
|
||||
transform = ekm.get_transformation_to(ekm);
|
||||
DLIB_TEST(transform.nr() == ekm.out_vector_size());
|
||||
DLIB_TEST(transform.nc() == ekm.out_vector_size());
|
||||
for (unsigned long i = 0; i < samples1.size(); ++i)
|
||||
{
|
||||
samp = ekm.project(samples1[i]);
|
||||
DLIB_TEST_MSG(length(samp - transform*samp) < eps, length(samp - transform*samp));
|
||||
samp = ekm.project((samples1[0] + samples1[i])/2);
|
||||
DLIB_TEST_MSG(length(samp - transform*samp) < eps, length(samp - transform*samp));
|
||||
}
|
||||
|
||||
transform = ekm2.get_transformation_to(ekm2);
|
||||
DLIB_TEST(transform.nr() == ekm2.out_vector_size());
|
||||
DLIB_TEST(transform.nc() == ekm2.out_vector_size());
|
||||
for (unsigned long i = 0; i < samples2.size(); ++i)
|
||||
{
|
||||
samp = ekm2.project(samples2[i]);
|
||||
DLIB_TEST_MSG(length(samp - transform*samp) < eps, length(samp - transform*samp));
|
||||
samp = ekm2.project((samples2[0] + samples2[i])/2);
|
||||
DLIB_TEST_MSG(length(samp - transform*samp) < eps, length(samp - transform*samp));
|
||||
//dlog << LTRACE << "mapping error: " << length(samp - transform*samp);
|
||||
}
|
||||
|
||||
|
||||
// now test the transform from ekm to ekm2
|
||||
transform = ekm.get_transformation_to(ekm2);
|
||||
DLIB_TEST(transform.nr() == ekm2.out_vector_size());
|
||||
DLIB_TEST(transform.nc() == ekm.out_vector_size());
|
||||
for (unsigned long i = 0; i < samples1.size(); ++i)
|
||||
{
|
||||
samp = ekm.project(samples1[i]);
|
||||
distance_function<kernel_type> df1 = ekm.convert_to_distance_function(samp);
|
||||
distance_function<kernel_type> df2 = ekm2.convert_to_distance_function(transform*samp);
|
||||
DLIB_TEST_MSG(df1(df2) < eps, df1(df2));
|
||||
//dlog << LTRACE << "mapping error: " << df1(df2);
|
||||
|
||||
|
||||
samp = ekm.project((samples1[0] + samples1[i])/2);
|
||||
df1 = ekm.convert_to_distance_function(samp);
|
||||
df2 = ekm2.convert_to_distance_function(transform*samp);
|
||||
DLIB_TEST_MSG(df1(df2) < eps, df1(df2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -172,8 +253,10 @@ namespace
|
|||
rnd.set_seed(cast_to_string(thetime));
|
||||
|
||||
print_spinner();
|
||||
dlog << LINFO << "test with linear kernel";
|
||||
test_with_kernel(linear_kernel<sample_type>());
|
||||
print_spinner();
|
||||
dlog << LINFO << "test with rbf kernel";
|
||||
test_with_kernel(radial_basis_kernel<sample_type>(0.2));
|
||||
print_spinner();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue