Commit b51d1148 authored by Davis King's avatar Davis King

Made the svd_fast() code a little more readable and memory efficient.

Also added the orthogonalize() function.
parent 246a60c2
...@@ -816,6 +816,22 @@ convergence: ...@@ -816,6 +816,22 @@ convergence:
#endif #endif
} }
// ----------------------------------------------------------------------------------------
template <
typename T,
long NR,
long NC,
typename MM,
typename L
>
void orthogonalize (
matrix<T,NR,NC,MM,L>& m
)
{
qr_decomposition<matrix<T,NR,NC,MM,L> >(m).get_q(m);
}
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
...@@ -845,23 +861,21 @@ convergence: ...@@ -845,23 +861,21 @@ convergence:
!*/ !*/
{ {
DLIB_ASSERT(A.nr() >= (long)l, "Invalid inputs were given to this function."); DLIB_ASSERT(A.nr() >= (long)l, "Invalid inputs were given to this function.");
matrix<T> G = matrix_cast<T>(gaussian_randm(A.nc(), l)); Q = A*matrix_cast<T>(gaussian_randm(A.nc(), l));
matrix<T> Y = A*G;
Q = qr_decomposition<matrix<T> >(Y).get_q(); orthogonalize(Q);
// Do some extra iterations of the power method to make sure we get Q into the // Do some extra iterations of the power method to make sure we get Q into the
// span of the most important singular vectors of A. // span of the most important singular vectors of A.
if (q != 0) if (q != 0)
{ {
matrix<T> Z;
for (unsigned long itr = 0; itr < q; ++itr) for (unsigned long itr = 0; itr < q; ++itr)
{ {
Z = trans(A)*Q; Q = trans(A)*Q;
Z = qr_decomposition<matrix<T> >(Z).get_q(); orthogonalize(Q);
Y = A*Z; Q = A*Q;
Q = qr_decomposition<matrix<T> >(Y).get_q(); orthogonalize(Q);
} }
} }
} }
...@@ -928,27 +942,27 @@ convergence: ...@@ -928,27 +942,27 @@ convergence:
!*/ !*/
{ {
DLIB_ASSERT(A.size() >= l, "Invalid inputs were given to this function."); DLIB_ASSERT(A.size() >= l, "Invalid inputs were given to this function.");
matrix<T> Y(A.size(), l); Q.set_size(A.size(), l);
// Compute Y = A*gaussian_randm() // Compute Q = A*gaussian_randm()
for (long r = 0; r < Y.nr(); ++r) for (long r = 0; r < Q.nr(); ++r)
{ {
for (long c = 0; c < Y.nc(); ++c) for (long c = 0; c < Q.nc(); ++c)
{ {
Y(r,c) = dot(A[r], gaussian_randm(std::numeric_limits<long>::max(), 1, c)); Q(r,c) = dot(A[r], gaussian_randm(std::numeric_limits<long>::max(), 1, c));
} }
} }
Q = qr_decomposition<matrix<T> >(Y).get_q(); orthogonalize(Q);
// Do some extra iterations of the power method to make sure we get Q into the // Do some extra iterations of the power method to make sure we get Q into the
// span of the most important singular vectors of A. // span of the most important singular vectors of A.
if (q != 0) if (q != 0)
{ {
const unsigned long n = max_index_plus_one(A); const unsigned long n = max_index_plus_one(A);
matrix<T> Z(n, l);
for (unsigned long itr = 0; itr < q; ++itr) for (unsigned long itr = 0; itr < q; ++itr)
{ {
matrix<T> Z(n, l);
// Compute Z = trans(A)*Q // Compute Z = trans(A)*Q
Z = 0; Z = 0;
for (unsigned long m = 0; m < A.size(); ++m) for (unsigned long m = 0; m < A.size(); ++m)
...@@ -966,18 +980,21 @@ convergence: ...@@ -966,18 +980,21 @@ convergence:
} }
} }
Z = qr_decomposition<matrix<T> >(Z).get_q(); Q.set_size(0,0); // free RAM
orthogonalize(Z);
// Compute Y = A*Z // Compute Q = A*Z
for (long r = 0; r < Y.nr(); ++r) Q.set_size(A.size(), l);
for (long r = 0; r < Q.nr(); ++r)
{ {
for (long c = 0; c < Y.nc(); ++c) for (long c = 0; c < Q.nc(); ++c)
{ {
Y(r,c) = dot(A[r], colm(Z,c)); Q(r,c) = dot(A[r], colm(Z,c));
} }
} }
Q = qr_decomposition<matrix<T> >(Y).get_q(); Z.set_size(0,0); // free RAM
orthogonalize(Q);
} }
} }
} }
......
...@@ -235,6 +235,30 @@ namespace dlib ...@@ -235,6 +235,30 @@ namespace dlib
Therefore, it is very fast and suitable for use with very large matrices. Therefore, it is very fast and suitable for use with very large matrices.
!*/ !*/
// ----------------------------------------------------------------------------------------
template <
typename T,
long NR,
long NC,
typename MM,
typename L
>
void orthogonalize (
matrix<T,NR,NC,MM,L>& m
);
/*!
requires
- m.nr() >= m.nc()
- m.size() > 0
ensures
- #m == an orthogonal matrix with the same dimensions as m. In particular,
the columns of #m have the same span as the columns of m.
- trans(#m)*#m == identity matrix
- This function is just shorthand for performing the QR decomposition of m
and then storing the Q factor into #m.
!*/
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
const matrix real_eigenvalues ( const matrix real_eigenvalues (
......
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