mirror of
https://gitcode.com/gh_mirrors/ope/OpenFace.git
synced 2026-05-16 20:28:00 +00:00
187 lines
6.8 KiB
C++
187 lines
6.8 KiB
C++
// Copyright (C) 2013 Davis E. King (davis@dlib.net)
|
|
// License: Boost Software License See LICENSE.txt for the full license.
|
|
#ifndef DLIB_CCA_hh_
|
|
#define DLIB_CCA_hh_
|
|
|
|
#include "cca_abstract.h"
|
|
#include "../algs.h"
|
|
#include "../matrix.h"
|
|
#include "../sparse_vector.h"
|
|
#include "random_subset_selector.h"
|
|
|
|
namespace dlib
|
|
{
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
template <
|
|
typename T
|
|
>
|
|
matrix<typename T::type,0,1> compute_correlations (
|
|
const matrix_exp<T>& L,
|
|
const matrix_exp<T>& R
|
|
)
|
|
{
|
|
DLIB_ASSERT( L.size() > 0 && R.size() > 0 && L.nr() == R.nr(),
|
|
"\t matrix compute_correlations()"
|
|
<< "\n\t Invalid inputs were given to this function."
|
|
<< "\n\t L.size(): " << L.size()
|
|
<< "\n\t R.size(): " << R.size()
|
|
<< "\n\t L.nr(): " << L.nr()
|
|
<< "\n\t R.nr(): " << R.nr()
|
|
);
|
|
|
|
typedef typename T::type type;
|
|
matrix<type> A, B, C;
|
|
A = diag(trans(R)*L);
|
|
B = sqrt(diag(trans(L)*L));
|
|
C = sqrt(diag(trans(R)*R));
|
|
A = pointwise_multiply(A , reciprocal(pointwise_multiply(B,C)));
|
|
return A;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
template <
|
|
typename matrix_type,
|
|
typename T
|
|
>
|
|
matrix<T,0,1> impl_cca (
|
|
const matrix_type& L,
|
|
const matrix_type& R,
|
|
matrix<T>& Ltrans,
|
|
matrix<T>& Rtrans,
|
|
unsigned long num_correlations,
|
|
unsigned long extra_rank,
|
|
unsigned long q,
|
|
unsigned long num_output_correlations,
|
|
double regularization
|
|
)
|
|
{
|
|
matrix<T> Ul, Vl;
|
|
matrix<T> Ur, Vr;
|
|
matrix<T> U, V;
|
|
matrix<T,0,1> Dr, Dl, D;
|
|
|
|
|
|
// Note that we add a few more singular vectors in because it helps improve the
|
|
// final results if we run this part with a little higher rank than the final SVD.
|
|
svd_fast(L, Ul, Dl, Vl, num_correlations+extra_rank, q);
|
|
svd_fast(R, Ur, Dr, Vr, num_correlations+extra_rank, q);
|
|
|
|
// Zero out singular values that are essentially zero so they don't cause numerical
|
|
// difficulties in the code below.
|
|
const double eps = std::numeric_limits<T>::epsilon()*std::max(max(Dr),max(Dl))*100;
|
|
Dl = round_zeros(Dl+regularization,eps);
|
|
Dr = round_zeros(Dr+regularization,eps);
|
|
|
|
// This matrix is really small so we can do a normal full SVD on it. Note that we
|
|
// also throw away the columns of Ul and Ur corresponding to zero singular values.
|
|
svd3(diagm(Dl>0)*tmp(trans(Ul)*Ur)*diagm(Dr>0), U, D, V);
|
|
|
|
// now throw away extra columns of the transformations. We do this in a way
|
|
// that keeps the directions that have the highest correlations.
|
|
matrix<T,0,1> temp = D;
|
|
rsort_columns(U, temp);
|
|
rsort_columns(V, D);
|
|
U = colm(U, range(0, num_output_correlations-1));
|
|
V = colm(V, range(0, num_output_correlations-1));
|
|
D = rowm(D, range(0, num_output_correlations-1));
|
|
|
|
Ltrans = Vl*inv(diagm(Dl))*U;
|
|
Rtrans = Vr*inv(diagm(Dr))*V;
|
|
|
|
// Note that the D matrix contains the correlation values for the transformed
|
|
// vectors. However, when the L and R matrices have rank higher than
|
|
// num_correlations+extra_rank then the values in D become only approximate.
|
|
return D;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
template <typename T>
|
|
matrix<T,0,1> cca (
|
|
const matrix<T>& L,
|
|
const matrix<T>& R,
|
|
matrix<T>& Ltrans,
|
|
matrix<T>& Rtrans,
|
|
unsigned long num_correlations,
|
|
unsigned long extra_rank = 5,
|
|
unsigned long q = 2,
|
|
double regularization = 0
|
|
)
|
|
{
|
|
DLIB_ASSERT( num_correlations > 0 && L.size() > 0 && R.size() > 0 && L.nr() == R.nr() &&
|
|
regularization >= 0,
|
|
"\t matrix cca()"
|
|
<< "\n\t Invalid inputs were given to this function."
|
|
<< "\n\t num_correlations: " << num_correlations
|
|
<< "\n\t regularization: " << regularization
|
|
<< "\n\t L.size(): " << L.size()
|
|
<< "\n\t R.size(): " << R.size()
|
|
<< "\n\t L.nr(): " << L.nr()
|
|
<< "\n\t R.nr(): " << R.nr()
|
|
);
|
|
|
|
using std::min;
|
|
const unsigned long n = min(num_correlations, (unsigned long)min(R.nr(),min(L.nc(), R.nc())));
|
|
return impl_cca(L,R,Ltrans, Rtrans, num_correlations, extra_rank, q, n, regularization);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
template <typename sparse_vector_type, typename T>
|
|
matrix<T,0,1> cca (
|
|
const std::vector<sparse_vector_type>& L,
|
|
const std::vector<sparse_vector_type>& R,
|
|
matrix<T>& Ltrans,
|
|
matrix<T>& Rtrans,
|
|
unsigned long num_correlations,
|
|
unsigned long extra_rank = 5,
|
|
unsigned long q = 2,
|
|
double regularization = 0
|
|
)
|
|
{
|
|
DLIB_ASSERT( num_correlations > 0 && L.size() == R.size() &&
|
|
max_index_plus_one(L) > 0 && max_index_plus_one(R) > 0 &&
|
|
regularization >= 0,
|
|
"\t matrix cca()"
|
|
<< "\n\t Invalid inputs were given to this function."
|
|
<< "\n\t num_correlations: " << num_correlations
|
|
<< "\n\t regularization: " << regularization
|
|
<< "\n\t L.size(): " << L.size()
|
|
<< "\n\t R.size(): " << R.size()
|
|
<< "\n\t max_index_plus_one(L): " << max_index_plus_one(L)
|
|
<< "\n\t max_index_plus_one(R): " << max_index_plus_one(R)
|
|
);
|
|
|
|
using std::min;
|
|
const unsigned long n = min(max_index_plus_one(L), max_index_plus_one(R));
|
|
const unsigned long num_output_correlations = min(num_correlations, std::min<unsigned long>(R.size(),n));
|
|
return impl_cca(L,R,Ltrans, Rtrans, num_correlations, extra_rank, q, num_output_correlations, regularization);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
template <typename sparse_vector_type, typename Rand_type, typename T>
|
|
matrix<T,0,1> cca (
|
|
const random_subset_selector<sparse_vector_type,Rand_type>& L,
|
|
const random_subset_selector<sparse_vector_type,Rand_type>& R,
|
|
matrix<T>& Ltrans,
|
|
matrix<T>& Rtrans,
|
|
unsigned long num_correlations,
|
|
unsigned long extra_rank = 5,
|
|
unsigned long q = 2
|
|
)
|
|
{
|
|
return cca(L.to_std_vector(), R.to_std_vector(), Ltrans, Rtrans, num_correlations, extra_rank, q);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
}
|
|
|
|
#endif // DLIB_CCA_hh_
|
|
|
|
|