Commit 9427dd23 authored by Davis King's avatar Davis King

Just renamed some variables to avoid a name conflict with a #define in vistual studio.

parent 6d7f25bf
...@@ -17,17 +17,17 @@ namespace dlib ...@@ -17,17 +17,17 @@ namespace dlib
> >
struct frobmetric_training_sample struct frobmetric_training_sample
{ {
matrix_type anchor; matrix_type anchor_vect;
std::vector<matrix_type> near; std::vector<matrix_type> near_vects;
std::vector<matrix_type> far; std::vector<matrix_type> far_vects;
unsigned long num_triples ( unsigned long num_triples (
) const { return near.size() * far.size(); } ) const { return near_vects.size() * far_vects.size(); }
void clear() void clear()
{ {
near.clear(); near_vects.clear();
far.clear(); far_vects.clear();
} }
}; };
...@@ -47,8 +47,8 @@ namespace dlib ...@@ -47,8 +47,8 @@ namespace dlib
private: private:
struct compact_frobmetric_training_sample struct compact_frobmetric_training_sample
{ {
std::vector<matrix_type> near; std::vector<matrix_type> near_vects;
std::vector<matrix_type> far; std::vector<matrix_type> far_vects;
}; };
struct objective struct objective
...@@ -61,7 +61,7 @@ namespace dlib ...@@ -61,7 +61,7 @@ namespace dlib
double operator()(const matrix<double,0,1,mem_manager_type>& u) const double operator()(const matrix<double,0,1,mem_manager_type>& u) const
{ {
long idx = 0; long idx = 0;
const long dims = samples[0].far[0].size(); const long dims = samples[0].far_vects[0].size();
// Here we compute \hat A from the paper, which we refer to as just A in // Here we compute \hat A from the paper, which we refer to as just A in
// the code. // the code.
matrix<double,0,0,mem_manager_type> A(dims,dims); matrix<double,0,0,mem_manager_type> A(dims,dims);
...@@ -69,8 +69,8 @@ namespace dlib ...@@ -69,8 +69,8 @@ namespace dlib
std::vector<double> ufar, unear; std::vector<double> ufar, unear;
for (unsigned long i = 0; i < samples.size(); ++i) for (unsigned long i = 0; i < samples.size(); ++i)
{ {
ufar.assign(samples[i].far.size(),0); ufar.assign(samples[i].far_vects.size(),0);
unear.assign(samples[i].near.size(),0); unear.assign(samples[i].near_vects.size(),0);
for (unsigned long j = 0; j < unear.size(); ++j) for (unsigned long j = 0; j < unear.size(); ++j)
{ {
for (unsigned long k = 0; k < ufar.size(); ++k) for (unsigned long k = 0; k < ufar.size(); ++k)
...@@ -81,9 +81,9 @@ namespace dlib ...@@ -81,9 +81,9 @@ namespace dlib
} }
} }
for (unsigned long j = 0; j < unear.size(); ++j) for (unsigned long j = 0; j < unear.size(); ++j)
A += unear[j]*samples[i].near[j]*trans(samples[i].near[j]); A += unear[j]*samples[i].near_vects[j]*trans(samples[i].near_vects[j]);
for (unsigned long j = 0; j < ufar.size(); ++j) for (unsigned long j = 0; j < ufar.size(); ++j)
A += ufar[j]*samples[i].far[j]*trans(samples[i].far[j]); A += ufar[j]*samples[i].far_vects[j]*trans(samples[i].far_vects[j]);
} }
eigenvalue_decomposition<matrix<double,0,0,mem_manager_type> > ed(make_symmetric(A)); eigenvalue_decomposition<matrix<double,0,0,mem_manager_type> > ed(make_symmetric(A));
...@@ -120,17 +120,17 @@ namespace dlib ...@@ -120,17 +120,17 @@ namespace dlib
std::vector<double> ufar, unear; std::vector<double> ufar, unear;
for (unsigned long i = 0; i < samples.size(); ++i) for (unsigned long i = 0; i < samples.size(); ++i)
{ {
ufar.resize(samples[i].far.size()); ufar.resize(samples[i].far_vects.size());
unear.resize(samples[i].near.size()); unear.resize(samples[i].near_vects.size());
for (unsigned long j = 0; j < unear.size(); ++j) for (unsigned long j = 0; j < unear.size(); ++j)
unear[j] = sum(pointwise_multiply(Aminus, samples[i].near[j]*trans(samples[i].near[j]))); unear[j] = sum(pointwise_multiply(Aminus, samples[i].near_vects[j]*trans(samples[i].near_vects[j])));
for (unsigned long j = 0; j < ufar.size(); ++j) for (unsigned long j = 0; j < ufar.size(); ++j)
ufar[j] = sum(pointwise_multiply(Aminus, samples[i].far[j]*trans(samples[i].far[j]))); ufar[j] = sum(pointwise_multiply(Aminus, samples[i].far_vects[j]*trans(samples[i].far_vects[j])));
for (unsigned long j = 0; j < samples[i].near.size(); ++j) for (unsigned long j = 0; j < samples[i].near_vects.size(); ++j)
{ {
for (unsigned long k = 0; k < samples[i].far.size(); ++k) for (unsigned long k = 0; k < samples[i].far_vects.size(); ++k)
{ {
grad(idx++) = 1 + ufar[k]-unear[j]; grad(idx++) = 1 + ufar[k]-unear[j];
} }
...@@ -289,15 +289,6 @@ namespace dlib ...@@ -289,15 +289,6 @@ namespace dlib
void train ( void train (
const std::vector<frobmetric_training_sample<matrix_type> >& samples const std::vector<frobmetric_training_sample<matrix_type> >& samples
) )
/*!
requires
- samples.size() != 0
- All matrices inside samples (i.e. anchors and elements of near and far)
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
!*/
{ {
// make sure requires clause is not broken // make sure requires clause is not broken
DLIB_ASSERT(samples.size() > 0, DLIB_ASSERT(samples.size() > 0,
...@@ -306,24 +297,24 @@ namespace dlib ...@@ -306,24 +297,24 @@ namespace dlib
); );
#ifdef ENABLE_ASSERTS #ifdef ENABLE_ASSERTS
{ {
const long dims = samples[0].anchor.size(); const long dims = samples[0].anchor_vect.size();
DLIB_ASSERT(dims != 0, DLIB_ASSERT(dims != 0,
"\tvoid vector_normalizer_frobmetric::train()" "\tvoid vector_normalizer_frobmetric::train()"
<< "\n\t The dimension of the input vectors can't be zero." << "\n\t The dimension of the input vectors can't be zero."
); );
for (unsigned long i = 0; i < samples.size(); ++i) for (unsigned long i = 0; i < samples.size(); ++i)
{ {
DLIB_ASSERT(is_col_vector(samples[i].anchor), DLIB_ASSERT(is_col_vector(samples[i].anchor_vect),
"\tvoid vector_normalizer_frobmetric::train()" "\tvoid vector_normalizer_frobmetric::train()"
<< "\n\t Invalid inputs were given to this function." << "\n\t Invalid inputs were given to this function."
<< "\n\t i: " << i << "\n\t i: " << i
); );
DLIB_ASSERT(samples[i].anchor.size() == dims, DLIB_ASSERT(samples[i].anchor_vect.size() == dims,
"\tvoid vector_normalizer_frobmetric::train()" "\tvoid vector_normalizer_frobmetric::train()"
<< "\n\t Invalid inputs were given to this function." << "\n\t Invalid inputs were given to this function."
<< "\n\t i: " << i << "\n\t i: " << i
<< "\n\t dims: " << dims << "\n\t dims: " << dims
<< "\n\t samples[i].anchor.size(): " << samples[i].anchor.size() << "\n\t samples[i].anchor_vect.size(): " << samples[i].anchor_vect.size()
); );
DLIB_ASSERT(samples[i].num_triples() != 0, DLIB_ASSERT(samples[i].num_triples() != 0,
...@@ -331,38 +322,38 @@ namespace dlib ...@@ -331,38 +322,38 @@ namespace dlib
<< "\n\t It is illegal for a training sample to have no data in it" << "\n\t It is illegal for a training sample to have no data in it"
<< "\n\t i: " << i << "\n\t i: " << i
); );
for (unsigned long j = 0; j < samples[i].near.size(); ++j) for (unsigned long j = 0; j < samples[i].near_vects.size(); ++j)
{ {
DLIB_ASSERT(is_col_vector(samples[i].near[j]), DLIB_ASSERT(is_col_vector(samples[i].near_vects[j]),
"\tvoid vector_normalizer_frobmetric::train()" "\tvoid vector_normalizer_frobmetric::train()"
<< "\n\t Invalid inputs were given to this function." << "\n\t Invalid inputs were given to this function."
<< "\n\t i: " << i << "\n\t i: " << i
<< "\n\t j: " << j << "\n\t j: " << j
); );
DLIB_ASSERT(samples[i].near[j].size() == dims, DLIB_ASSERT(samples[i].near_vects[j].size() == dims,
"\tvoid vector_normalizer_frobmetric::train()" "\tvoid vector_normalizer_frobmetric::train()"
<< "\n\t Invalid inputs were given to this function." << "\n\t Invalid inputs were given to this function."
<< "\n\t i: " << i << "\n\t i: " << i
<< "\n\t j: " << j << "\n\t j: " << j
<< "\n\t dims: " << dims << "\n\t dims: " << dims
<< "\n\t samples[i].near[j].size(): " << samples[i].near[j].size() << "\n\t samples[i].near_vects[j].size(): " << samples[i].near_vects[j].size()
); );
} }
for (unsigned long j = 0; j < samples[i].far.size(); ++j) for (unsigned long j = 0; j < samples[i].far_vects.size(); ++j)
{ {
DLIB_ASSERT(is_col_vector(samples[i].far[j]), DLIB_ASSERT(is_col_vector(samples[i].far_vects[j]),
"\tvoid vector_normalizer_frobmetric::train()" "\tvoid vector_normalizer_frobmetric::train()"
<< "\n\t Invalid inputs were given to this function." << "\n\t Invalid inputs were given to this function."
<< "\n\t i: " << i << "\n\t i: " << i
<< "\n\t j: " << j << "\n\t j: " << j
); );
DLIB_ASSERT(samples[i].far[j].size() == dims, DLIB_ASSERT(samples[i].far_vects[j].size() == dims,
"\tvoid vector_normalizer_frobmetric::train()" "\tvoid vector_normalizer_frobmetric::train()"
<< "\n\t Invalid inputs were given to this function." << "\n\t Invalid inputs were given to this function."
<< "\n\t i: " << i << "\n\t i: " << i
<< "\n\t j: " << j << "\n\t j: " << j
<< "\n\t dims: " << dims << "\n\t dims: " << dims
<< "\n\t samples[i].far[j].size(): " << samples[i].far[j].size() << "\n\t samples[i].far_vects[j].size(): " << samples[i].far_vects[j].size()
); );
} }
} }
...@@ -373,7 +364,7 @@ namespace dlib ...@@ -373,7 +364,7 @@ namespace dlib
// compute the mean sample // compute the mean sample
m = 0; m = 0;
for (unsigned long i = 0; i < samples.size(); ++i) for (unsigned long i = 0; i < samples.size(); ++i)
m += samples[i].anchor; m += samples[i].anchor_vect;
m /= samples.size(); m /= samples.size();
DLIB_ASSERT(is_finite(m), "Some of the input vectors to vector_normalizer_frobmetric::train() have infinite or NaN values"); DLIB_ASSERT(is_finite(m), "Some of the input vectors to vector_normalizer_frobmetric::train() have infinite or NaN values");
...@@ -382,22 +373,22 @@ namespace dlib ...@@ -382,22 +373,22 @@ namespace dlib
// over the next few lines of code. // over the next few lines of code.
unsigned long num_triples = 0; unsigned long num_triples = 0;
for (unsigned long i = 0; i < samples.size(); ++i) for (unsigned long i = 0; i < samples.size(); ++i)
num_triples += samples[i].near.size()*samples[i].far.size(); num_triples += samples[i].near_vects.size()*samples[i].far_vects.size();
matrix<double,0,1,mem_manager_type> u(num_triples); matrix<double,0,1,mem_manager_type> u(num_triples);
u = 0; u = 0;
// precompute all the anchor to far/near pairs // precompute all the anchor_vect to far_vects/near_vects pairs
std::vector<compact_frobmetric_training_sample> data(samples.size()); std::vector<compact_frobmetric_training_sample> data(samples.size());
for (unsigned long i = 0; i < data.size(); ++i) for (unsigned long i = 0; i < data.size(); ++i)
{ {
data[i].far.reserve(samples[i].far.size()); data[i].far_vects.reserve(samples[i].far_vects.size());
data[i].near.reserve(samples[i].near.size()); data[i].near_vects.reserve(samples[i].near_vects.size());
for (unsigned long j = 0; j < samples[i].far.size(); ++j) for (unsigned long j = 0; j < samples[i].far_vects.size(); ++j)
data[i].far.push_back(samples[i].anchor - samples[i].far[j]); data[i].far_vects.push_back(samples[i].anchor_vect - samples[i].far_vects[j]);
for (unsigned long j = 0; j < samples[i].near.size(); ++j) for (unsigned long j = 0; j < samples[i].near_vects.size(); ++j)
data[i].near.push_back(samples[i].anchor - samples[i].near[j]); data[i].near_vects.push_back(samples[i].anchor_vect - samples[i].near_vects[j]);
} }
// Now run the main part of the algorithm // Now run the main part of the algorithm
......
...@@ -19,20 +19,20 @@ namespace dlib ...@@ -19,20 +19,20 @@ namespace dlib
WHAT THIS OBJECT REPRESENTS WHAT THIS OBJECT REPRESENTS
This object represents a training data sample for the This object represents a training data sample for the
vector_normalizer_frobmetric object. It defines a set of training triplets vector_normalizer_frobmetric object. It defines a set of training triplets
relative to a single anchor vector. That is, it specifies that the learned relative to a single anchor_vect vector. That is, it specifies that the
distance metric should satisfy num_triples() constraints which are, for all learned distance metric should satisfy num_triples() constraints which are,
valid i and j: for all valid i and j:
length(T*anchor-T*near[i]) + 1 < length(T*anchor - T*far[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 for some appropriate linear transformation T which will be learned by
vector_normalizer_frobmetric. vector_normalizer_frobmetric.
!*/ !*/
matrix_type anchor; matrix_type anchor_vect;
std::vector<matrix_type> near; std::vector<matrix_type> near_vects;
std::vector<matrix_type> far; std::vector<matrix_type> far_vects;
unsigned long num_triples ( unsigned long num_triples (
) const { return near.size() * far.size(); } ) const { return near_vects.size() * far_vects.size(); }
/*! /*!
ensures ensures
- returns the number of training triplets defined by this object. - returns the number of training triplets defined by this object.
...@@ -41,8 +41,8 @@ namespace dlib ...@@ -41,8 +41,8 @@ namespace dlib
void clear() void clear()
/*! /*!
ensures ensures
- #near.size() == 0 - #near_vects.size() == 0
- #far.size() == 0 - #far_vects.size() == 0
!*/ !*/
}; };
...@@ -73,13 +73,13 @@ namespace dlib ...@@ -73,13 +73,13 @@ namespace dlib
By Chunhua Shen, Junae Kim, Lei Wang, in CVPR 2011 By Chunhua Shen, Junae Kim, Lei Wang, in CVPR 2011
Therefore, this object is a tool that takes as input training triplets Therefore, this object is a tool that takes as input training triplets
(anchor, near, far) of vectors and attempts to learn a linear (anchor_vect, near, far) of vectors and attempts to learn a linear
transformation T such that: transformation T such that:
length(T*anchor-T*near) + 1 < length(T*anchor - T*far) length(T*anchor_vect-T*near) + 1 < length(T*anchor_vect - T*far)
That is, you give a bunch of anchor vectors and for each anchor vector you That is, you give a bunch of anchor_vect vectors and for each anchor_vect
specify some vectors which should be near to it and some that should be far you specify some vectors which should be near to it and some that should be
form it. This object then tries to find a transformation matrix that makes far form it. This object then tries to find a transformation matrix that
the "near" vectors close to their anchors while the "far" vectors are makes the "near" vectors close to their anchors while the "far" vectors are
farther away. farther away.
THREAD SAFETY THREAD SAFETY
...@@ -182,7 +182,7 @@ namespace dlib ...@@ -182,7 +182,7 @@ namespace dlib
/*! /*!
requires requires
- samples.size() != 0 - samples.size() != 0
- All matrices inside samples (i.e. anchors and elements of near and far) - All matrices inside samples (i.e. anchors and elements of near_vects and far_vects)
are column vectors with the same non-zero dimension. are column vectors with the same non-zero dimension.
- All the vectors in samples contain finite values. - All the vectors in samples contain finite values.
- All elements of samples contain data, specifically, for all valid i: - All elements of samples contain data, specifically, for all valid i:
...@@ -193,13 +193,13 @@ namespace dlib ...@@ -193,13 +193,13 @@ namespace dlib
according to the learned distance metric. In particular, we will have: according to the learned distance metric. In particular, we will have:
- #transform() == The linear transformation learned by the FrobMetric - #transform() == The linear transformation learned by the FrobMetric
learning procedure. learning procedure.
- #in_vector_size() == samples[0].anchor.size() - #in_vector_size() == samples[0].anchor_vect.size()
- You can call (*this)(x) to transform a vector according to the learned - You can call (*this)(x) to transform a vector according to the learned
distance metric. That is, it should generally be the case that: distance metric. That is, it should generally be the case that:
- length((*this)(anchor) - (*this)(near)) + 1 < length((*this)(anchor) - (*this)(far)) - length((*this)(anchor_vect) - (*this)(near)) + 1 < length((*this)(anchor_vect) - (*this)(far))
for the anchor, near, and far vectors in the training data. for the anchor_vect, near, and far vectors in the training data.
- #transformed_means() == the mean of the input anchor vectors after being - #transformed_means() == the mean of the input anchor_vect vectors
transformed by #transform() after being transformed by #transform()
!*/ !*/
long in_vector_size ( long in_vector_size (
...@@ -230,8 +230,8 @@ namespace dlib ...@@ -230,8 +230,8 @@ namespace dlib
- V.size() == in_vector_size() - V.size() == in_vector_size()
- V is a vector such that subtracting it from transformed vectors - V is a vector such that subtracting it from transformed vectors
results in them having an expected value of 0. Therefore, it is results in them having an expected value of 0. Therefore, it is
equal to transform() times the mean of the input anchor vectors given equal to transform() times the mean of the input anchor_vect vectors
to train(). given to train().
!*/ !*/
const matrix<scalar_type,0,0,mem_manager_type>& transform ( const matrix<scalar_type,0,0,mem_manager_type>& transform (
......
...@@ -378,7 +378,7 @@ namespace ...@@ -378,7 +378,7 @@ namespace
} }
// check the unbiased skewness and excess kurtosis of one million Gaussian // check the unbiased skewness and excess kurtosis of one million Gaussian
// draws are both near zero. // draws are both near_vects zero.
DLIB_TEST(abs(rs1.skewness()) < 0.1); DLIB_TEST(abs(rs1.skewness()) < 0.1);
DLIB_TEST(abs(rs1.ex_kurtosis()) < 0.1); DLIB_TEST(abs(rs1.ex_kurtosis()) < 0.1);
} }
...@@ -582,12 +582,12 @@ namespace ...@@ -582,12 +582,12 @@ namespace
running_stats<double> rs; running_stats<double> rs;
for (unsigned long i = 0; i < samples.size(); ++i) for (unsigned long i = 0; i < samples.size(); ++i)
{ {
for (unsigned long j = 0; j < samples[i].near.size(); ++j) for (unsigned long j = 0; j < samples[i].near_vects.size(); ++j)
{ {
const double d1 = length_squared(samples[i].anchor - samples[i].near[j]); const double d1 = length_squared(samples[i].anchor_vect - samples[i].near_vects[j]);
for (unsigned long k = 0; k < samples[i].far.size(); ++k) for (unsigned long k = 0; k < samples[i].far_vects.size(); ++k)
{ {
const double d2 = length_squared(samples[i].anchor - samples[i].far[k]); const double d2 = length_squared(samples[i].anchor_vect - samples[i].far_vects[k]);
rs.add(d2-d1); rs.add(d2-d1);
} }
} }
...@@ -620,17 +620,17 @@ namespace ...@@ -620,17 +620,17 @@ namespace
for (int i = 0; i < 50; ++i) for (int i = 0; i < 50; ++i)
{ {
samp.clear(); samp.clear();
samp.anchor = gaussian_randm(dims,1,k++); samp.anchor_vect = gaussian_randm(dims,1,k++);
if (samp.anchor(key) > 0) if (samp.anchor_vect(key) > 0)
samp.anchor(key) = rnd.get_random_double() + 5; samp.anchor_vect(key) = rnd.get_random_double() + 5;
else else
samp.anchor(key) = -(rnd.get_random_double() + 5); samp.anchor_vect(key) = -(rnd.get_random_double() + 5);
matrix<double,0,1> temp; matrix<double,0,1> temp;
for (int j = 0; j < 5; ++j) for (int j = 0; j < 5; ++j)
{ {
// Don't always put an equal number of near and far vectors into the // Don't always put an equal number of near_vects and far_vects vectors into the
// training samples. // training samples.
const int numa = rnd.get_random_32bit_number()%2 + 1; const int numa = rnd.get_random_32bit_number()%2 + 1;
const int numb = rnd.get_random_32bit_number()%2 + 1; const int numb = rnd.get_random_32bit_number()%2 + 1;
...@@ -639,16 +639,16 @@ namespace ...@@ -639,16 +639,16 @@ namespace
{ {
temp = gaussian_randm(dims,1,k++); temp(key) = 0.1; temp = gaussian_randm(dims,1,k++); temp(key) = 0.1;
//temp = gaussian_randm(dims,1,k++); temp(key) = std::abs(temp(key)); //temp = gaussian_randm(dims,1,k++); temp(key) = std::abs(temp(key));
if (samp.anchor(key) > 0) samp.near.push_back(temp); if (samp.anchor_vect(key) > 0) samp.near_vects.push_back(temp);
else samp.far.push_back(temp); else samp.far_vects.push_back(temp);
} }
for (int num = 0; num < numb; ++num) for (int num = 0; num < numb; ++num)
{ {
temp = gaussian_randm(dims,1,k++); temp(key) = -0.1; temp = gaussian_randm(dims,1,k++); temp(key) = -0.1;
//temp = gaussian_randm(dims,1,k++); temp(key) = -std::abs(temp(key)); //temp = gaussian_randm(dims,1,k++); temp(key) = -std::abs(temp(key));
if (samp.anchor(key) < 0) samp.near.push_back(temp); if (samp.anchor_vect(key) < 0) samp.near_vects.push_back(temp);
else samp.far.push_back(temp); else samp.far_vects.push_back(temp);
} }
} }
samples.push_back(samp); samples.push_back(samp);
...@@ -665,12 +665,12 @@ namespace ...@@ -665,12 +665,12 @@ namespace
for (unsigned long i = 0; i < samples.size(); ++i) for (unsigned long i = 0; i < samples.size(); ++i)
{ {
samples[i].anchor = normalizer(samples[i].anchor); samples[i].anchor_vect = normalizer(samples[i].anchor_vect);
total += samples[i].anchor; total += samples[i].anchor_vect;
for (unsigned long j = 0; j < samples[i].near.size(); ++j) for (unsigned long j = 0; j < samples[i].near_vects.size(); ++j)
samples[i].near[j] = normalizer(samples[i].near[j]); samples[i].near_vects[j] = normalizer(samples[i].near_vects[j]);
for (unsigned long j = 0; j < samples[i].far.size(); ++j) for (unsigned long j = 0; j < samples[i].far_vects.size(); ++j)
samples[i].far[j] = normalizer(samples[i].far[j]); samples[i].far_vects[j] = normalizer(samples[i].far_vects[j]);
} }
total /= samples.size(); total /= samples.size();
dlog << LINFO << "sample transformed means: "<< trans(total); dlog << LINFO << "sample transformed means: "<< trans(total);
......
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