Implementé la SVD aleatoria como se indica en "Halko, N., Martinsson, PG, Shkolnisky, Y., y Tygert, M. (2010). Un algoritmo para el análisis de componentes principales de grandes conjuntos de datos. Arxiv preprint arXiv: 1007.5510, 0526. Recuperado el 1 de abril de 2011, de http://arxiv.org/abs/1007.5510 ". Si desea obtener SVD truncado, realmente funciona mucho más rápido que las variaciones de svd en MATLAB. Puedes obtenerlo aqui:
function [U,S,V] = fsvd(A, k, i, usePowerMethod)
% FSVD Fast Singular Value Decomposition
%
% [U,S,V] = FSVD(A,k,i,usePowerMethod) computes the truncated singular
% value decomposition of the input matrix A upto rank k using i levels of
% Krylov method as given in [1], p. 3.
%
% If usePowerMethod is given as true, then only exponent i is used (i.e.
% as power method). See [2] p.9, Randomized PCA algorithm for details.
%
% [1] Halko, N., Martinsson, P. G., Shkolnisky, Y., & Tygert, M. (2010).
% An algorithm for the principal component analysis of large data sets.
% Arxiv preprint arXiv:1007.5510, 0526. Retrieved April 1, 2011, from
% http://arxiv.org/abs/1007.5510.
%
% [2] Halko, N., Martinsson, P. G., & Tropp, J. A. (2009). Finding
% structure with randomness: Probabilistic algorithms for constructing
% approximate matrix decompositions. Arxiv preprint arXiv:0909.4061.
% Retrieved April 1, 2011, from http://arxiv.org/abs/0909.4061.
%
% See also SVD.
%
% Copyright 2011 Ismail Ari, http://ismailari.com.
if nargin < 3
i = 1;
end
% Take (conjugate) transpose if necessary. It makes H smaller thus
% leading the computations to be faster
if size(A,1) < size(A,2)
A = A';
isTransposed = true;
else
isTransposed = false;
end
n = size(A,2);
l = k + 2;
% Form a real n×l matrix G whose entries are iid Gaussian r.v.s of zero
% mean and unit variance
G = randn(n,l);
if nargin >= 4 && usePowerMethod
% Use only the given exponent
H = A*G;
for j = 2:i+1
H = A * (A'*H);
end
else
% Compute the m×l matrices H^{(0)}, ..., H^{(i)}
% Note that this is done implicitly in each iteration below.
H = cell(1,i+1);
H{1} = A*G;
for j = 2:i+1
H{j} = A * (A'*H{j-1});
end
% Form the m×((i+1)l) matrix H
H = cell2mat(H);
end
% Using the pivoted QR-decomposiion, form a real m×((i+1)l) matrix Q
% whose columns are orthonormal, s.t. there exists a real
% ((i+1)l)×((i+1)l) matrix R for which H = QR.
% XXX: Buradaki column pivoting ile yapılmayan hali.
[Q,~] = qr(H,0);
% Compute the n×((i+1)l) product matrix T = A^T Q
T = A'*Q;
% Form an SVD of T
[Vt, St, W] = svd(T,'econ');
% Compute the m×((i+1)l) product matrix
Ut = Q*W;
% Retrieve the leftmost m×k block U of Ut, the leftmost n×k block V of
% Vt, and the leftmost uppermost k×k block S of St. The product U S V^T
% then approxiamtes A.
if isTransposed
V = Ut(:,1:k);
U = Vt(:,1:k);
else
U = Ut(:,1:k);
V = Vt(:,1:k);
end
S = St(1:k,1:k);
end
Para probarlo, simplemente cree una imagen en la misma carpeta (como una matriz grande, puede crear la matriz usted mismo)
% Example code for fast SVD.
clc, clear
%% TRY ME
k = 10; % # dims
i = 2; % # power
COMPUTE_SVD0 = true; % Comment out if you do not want to spend time with builtin SVD.
% A is the m×n matrix we want to decompose
A = im2double(rgb2gray(imread('test_image.jpg')))';
%% DO NOT MODIFY
if COMPUTE_SVD0
tic
% Compute SVD of A directly
[U0, S0, V0] = svd(A,'econ');
A0 = U0(:,1:k) * S0(1:k,1:k) * V0(:,1:k)';
toc
display(['SVD Error: ' num2str(compute_error(A,A0))])
clear U0 S0 V0
end
% FSVD without power method
tic
[U1, S1, V1] = fsvd(A, k, i);
toc
A1 = U1 * S1 * V1';
display(['FSVD HYBRID Error: ' num2str(compute_error(A,A1))])
clear U1 S1 V1
% FSVD with power method
tic
[U2, S2, V2] = fsvd(A, k, i, true);
toc
A2 = U2 * S2 * V2';
display(['FSVD POWER Error: ' num2str(compute_error(A,A2))])
clear U2 S2 V2
subplot(2,2,1), imshow(A'), title('A (orig)')
if COMPUTE_SVD0, subplot(2,2,2), imshow(A0'), title('A0 (svd)'), end
subplot(2,2,3), imshow(A1'), title('A1 (fsvd hybrid)')
subplot(2,2,4), imshow(A2'), title('A2 (fsvd power)')

Cuando lo ejecuto en mi escritorio para obtener una imagen de tamaño 635 * 483, obtengo
Elapsed time is 0.110510 seconds.
SVD Error: 0.19132
Elapsed time is 0.017286 seconds.
FSVD HYBRID Error: 0.19142
Elapsed time is 0.006496 seconds.
FSVD POWER Error: 0.19206
Como puede ver, para valores bajos de k, es más de 10 veces más rápido que usar Matlab SVD. Por cierto, es posible que necesite la siguiente función simple para la función de prueba:
function e = compute_error(A, B)
% COMPUTE_ERROR Compute relative error between two arrays
e = norm(A(:)-B(:)) / norm(A(:));
end
No agregué el método PCA ya que es fácil de implementar usando SVD. Puede consultar este enlace para ver su relación.