"Halko, N., Martinsson, PG, Shkolnisky, Y., & Tygert, M. (2010)"에 제시된대로 Randomized SVD를 구현했습니다. 대규모 데이터 세트의 주요 구성 요소 분석 알고리즘 Arxiv preprint arXiv : 1007.5510, 0526. 2011 년 4 월 1 일에 http://arxiv.org/abs/1007.5510 에서 검색 됨 . " 잘린 SVD를 얻으려면 MATLAB의 svd 변형보다 훨씬 빠르게 작동합니다. 여기에서 얻을 수 있습니다 :
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
테스트하려면 동일한 폴더에 이미지를 만드십시오 (큰 매트릭스와 마찬가지로 매트릭스를 직접 만들 수 있습니다)
% 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)')
크기가 635 * 483 인 이미지를 바탕 화면에서 실행하면
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
보다시피, 값이 낮 으면 k
Matlab SVD를 사용하는 것보다 10 배 이상 빠릅니다. 그런데 테스트 기능을 위해 다음과 같은 간단한 기능이 필요할 수 있습니다.
function e = compute_error(A, B)
% COMPUTE_ERROR Compute relative error between two arrays
e = norm(A(:)-B(:)) / norm(A(:));
end
SVD를 사용하여 구현하는 것이 간단하기 때문에 PCA 방법을 추가하지 않았습니다. 이 링크 를 확인하여 관계를 확인할 수 있습니다 .