mirror of
https://github.com/davisking/dlib.git
synced 2024-11-01 10:14:53 +08:00
Added dpca_matrix_of_size() to discriminant_pca. It allows the user
to easily get a transformation matrix of a particular size.
This commit is contained in:
parent
d974648669
commit
bf2edbecb1
@ -239,6 +239,25 @@ namespace dlib
|
||||
return dpca_mat;
|
||||
}
|
||||
|
||||
const general_matrix dpca_matrix_of_size (
|
||||
const long num_rows
|
||||
)
|
||||
{
|
||||
// make sure requires clause is not broken
|
||||
DLIB_ASSERT(0 < num_rows && num_rows <= in_vector_size(),
|
||||
"\t general_matrix discriminant_pca::dpca_matrix_of_size()"
|
||||
<< "\n\t Invalid inputs were given to this function"
|
||||
<< "\n\t num_rows: " << num_rows
|
||||
<< "\n\t in_vector_size(): " << in_vector_size()
|
||||
<< "\n\t this: " << this
|
||||
);
|
||||
|
||||
general_matrix dpca_mat;
|
||||
general_matrix eigenvalues;
|
||||
dpca_matrix_of_size(dpca_mat, eigenvalues, num_rows);
|
||||
return dpca_mat;
|
||||
}
|
||||
|
||||
void dpca_matrix (
|
||||
general_matrix& dpca_mat,
|
||||
general_matrix& eigenvalues,
|
||||
@ -254,53 +273,25 @@ namespace dlib
|
||||
<< "\n\t this: " << this
|
||||
);
|
||||
|
||||
general_matrix cov;
|
||||
|
||||
// now combine the three measures of variance into a single matrix by using the
|
||||
// within_weight and between_weight weights.
|
||||
cov = get_total_covariance_matrix();
|
||||
if (within_count != 0)
|
||||
cov -= within_weight*within_cov/within_count;
|
||||
if (between_count != 0)
|
||||
cov += between_weight*between_cov/between_count;
|
||||
|
||||
|
||||
eigenvalue_decomposition<general_matrix> eig(make_symmetric(cov));
|
||||
|
||||
eigenvalues = eig.get_real_eigenvalues();
|
||||
dpca_mat = eig.get_pseudo_v();
|
||||
|
||||
// sort the eigenvalues and eigenvectors so that the biggest eigenvalues come first
|
||||
rsort_columns(dpca_mat, eigenvalues);
|
||||
|
||||
// Some of the eigenvalues might be negative. So first lets zero those out
|
||||
// so they won't get considered.
|
||||
eigenvalues = pointwise_multiply(eigenvalues > 0, eigenvalues);
|
||||
// figure out how many eigenvectors we want in our dpca matrix
|
||||
const double thresh = sum(eigenvalues)*eps;
|
||||
long num_vectors = 0;
|
||||
double total = 0;
|
||||
for (long r = 0; r < eigenvalues.size() && total < thresh; ++r)
|
||||
{
|
||||
// Don't even think about looking at eigenvalues that are 0. If we go this
|
||||
// far then we have all we need.
|
||||
if (eigenvalues(r) == 0)
|
||||
break;
|
||||
|
||||
++num_vectors;
|
||||
total += eigenvalues(r);
|
||||
compute_dpca_matrix(dpca_mat, eigenvalues, eps, 0);
|
||||
}
|
||||
|
||||
if (num_vectors == 0)
|
||||
throw discriminant_pca_error("While performing discriminant_pca, all eigenvalues were negative or 0");
|
||||
|
||||
// So now we know we want to use num_vectors of the first eigenvectors. So
|
||||
// pull those out and discard the rest.
|
||||
dpca_mat = trans(colm(dpca_mat,range(0,num_vectors-1)));
|
||||
|
||||
// also clip off the eigenvalues we aren't using
|
||||
eigenvalues = rowm(eigenvalues, range(0,num_vectors-1));
|
||||
void dpca_matrix_of_size (
|
||||
general_matrix& dpca_mat,
|
||||
general_matrix& eigenvalues,
|
||||
const long num_rows
|
||||
)
|
||||
{
|
||||
// make sure requires clause is not broken
|
||||
DLIB_ASSERT(0 < num_rows && num_rows <= in_vector_size(),
|
||||
"\t general_matrix discriminant_pca::dpca_matrix_of_size()"
|
||||
<< "\n\t Invalid inputs were given to this function"
|
||||
<< "\n\t num_rows: " << num_rows
|
||||
<< "\n\t in_vector_size(): " << in_vector_size()
|
||||
<< "\n\t this: " << this
|
||||
);
|
||||
|
||||
compute_dpca_matrix(dpca_mat, eigenvalues, 1, num_rows);
|
||||
}
|
||||
|
||||
void swap (
|
||||
@ -419,6 +410,70 @@ namespace dlib
|
||||
|
||||
private:
|
||||
|
||||
void compute_dpca_matrix (
|
||||
general_matrix& dpca_mat,
|
||||
general_matrix& eigenvalues,
|
||||
const double eps,
|
||||
long num_rows
|
||||
) const
|
||||
{
|
||||
general_matrix cov;
|
||||
|
||||
// now combine the three measures of variance into a single matrix by using the
|
||||
// within_weight and between_weight weights.
|
||||
cov = get_total_covariance_matrix();
|
||||
if (within_count != 0)
|
||||
cov -= within_weight*within_cov/within_count;
|
||||
if (between_count != 0)
|
||||
cov += between_weight*between_cov/between_count;
|
||||
|
||||
|
||||
eigenvalue_decomposition<general_matrix> eig(make_symmetric(cov));
|
||||
|
||||
eigenvalues = eig.get_real_eigenvalues();
|
||||
dpca_mat = eig.get_pseudo_v();
|
||||
|
||||
// sort the eigenvalues and eigenvectors so that the biggest eigenvalues come first
|
||||
rsort_columns(dpca_mat, eigenvalues);
|
||||
|
||||
long num_vectors = 0;
|
||||
if (num_rows == 0)
|
||||
{
|
||||
// Some of the eigenvalues might be negative. So first lets zero those out
|
||||
// so they won't get considered.
|
||||
eigenvalues = pointwise_multiply(eigenvalues > 0, eigenvalues);
|
||||
// figure out how many eigenvectors we want in our dpca matrix
|
||||
const double thresh = sum(eigenvalues)*eps;
|
||||
double total = 0;
|
||||
for (long r = 0; r < eigenvalues.size() && total < thresh; ++r)
|
||||
{
|
||||
// Don't even think about looking at eigenvalues that are 0. If we go this
|
||||
// far then we have all we need.
|
||||
if (eigenvalues(r) == 0)
|
||||
break;
|
||||
|
||||
++num_vectors;
|
||||
total += eigenvalues(r);
|
||||
}
|
||||
|
||||
if (num_vectors == 0)
|
||||
throw discriminant_pca_error("While performing discriminant_pca, all eigenvalues were negative or 0");
|
||||
}
|
||||
else
|
||||
{
|
||||
num_vectors = num_rows;
|
||||
}
|
||||
|
||||
|
||||
// So now we know we want to use num_vectors of the first eigenvectors. So
|
||||
// pull those out and discard the rest.
|
||||
dpca_mat = trans(colm(dpca_mat,range(0,num_vectors-1)));
|
||||
|
||||
// also clip off the eigenvalues we aren't using
|
||||
eigenvalues = rowm(eigenvalues, range(0,num_vectors-1));
|
||||
|
||||
}
|
||||
|
||||
general_matrix get_total_covariance_matrix (
|
||||
) const
|
||||
/*!
|
||||
|
@ -240,6 +240,47 @@ namespace dlib
|
||||
that prevents this algorithm from working properly.
|
||||
!*/
|
||||
|
||||
const general_matrix dpca_matrix_of_size (
|
||||
const long num_rows
|
||||
);
|
||||
/*!
|
||||
requires
|
||||
- 0 < num_rows <= in_vector_size()
|
||||
ensures
|
||||
- computes and returns the matrix MAT given by dpca_matrix_of_size(MAT,eigen,num_rows).
|
||||
That is, this function returns the dpca_matrix computed by the function
|
||||
defined below.
|
||||
- Note that MAT is the desired linear transformation matrix. That is,
|
||||
multiplying a vector by MAT performs the desired linear dimensionality
|
||||
reduction to num_rows dimensions.
|
||||
!*/
|
||||
|
||||
void dpca_matrix_of_size (
|
||||
general_matrix& dpca_mat,
|
||||
general_matrix& eigenvalues,
|
||||
const long num_rows
|
||||
);
|
||||
/*!
|
||||
requires
|
||||
- 0 < num_rows <= in_vector_size()
|
||||
ensures
|
||||
- is_col_vector(#eigenvalues) == true
|
||||
- #dpca_mat.nr() == eigenvalues.size()
|
||||
- #dpca_mat.nr() == num_rows
|
||||
- #dpca_mat.nc() == in_vector_size()
|
||||
- rowm(#dpca_mat,i) represents the ith eigenvector of the S matrix described
|
||||
in the class description and its eigenvalue is given by eigenvalues(i).
|
||||
- The values in #eigenvalues might be positive or negative. Additionally, the
|
||||
eigenvalues are in sorted order with the largest eigenvalue stored at
|
||||
eigenvalues(0).
|
||||
- (#dpca_mat)*trans(#dpca_mat) == identity_matrix.
|
||||
(i.e. the rows of the dpca_matrix are all unit length vectors and are mutually
|
||||
orthogonal)
|
||||
- Note that #dpca_mat is the desired linear transformation matrix. That is,
|
||||
multiplying a vector by #dpca_mat performs the desired linear dimensionality
|
||||
reduction to num_rows dimensions.
|
||||
!*/
|
||||
|
||||
const discriminant_pca operator+ (
|
||||
const discriminant_pca& item
|
||||
) const;
|
||||
|
@ -80,6 +80,15 @@ namespace
|
||||
DLIB_TEST(last >= eig(i));
|
||||
}
|
||||
|
||||
{
|
||||
matrix<double> mat = dpca.dpca_matrix_of_size(4);
|
||||
DLIB_TEST(equal(mat*trans(mat), identity_matrix<double>(4)));
|
||||
}
|
||||
{
|
||||
matrix<double> mat = dpca.dpca_matrix_of_size(3);
|
||||
DLIB_TEST(equal(mat*trans(mat), identity_matrix<double>(3)));
|
||||
}
|
||||
|
||||
|
||||
dpca.set_within_class_weight(5);
|
||||
dpca.set_between_class_weight(6);
|
||||
|
Loading…
Reference in New Issue
Block a user