實Schur分解


    前面已經說過LU,Cholesky和QR分解,這次介紹的是實Schur分解。對這個分解的定義是任意一個矩陣A,可有如下形式的分解:

              U*A*U’ = B;其中B是擬上三角矩陣,擬上三角矩陣的定義是在矩陣的對角線上存在2x2大小的矩陣,而且矩陣U是正交矩陣,因為矩陣A的特征值和B的特征值相同。而且A的特征值出現在B的對角線上。計算特征值分解和SVD都依靠這個算法做最基本的處理,然后根據不同的任務有不同的處理。

計算schur分解的方法是是QR算法,這個算法的原理相當的簡單,可以用如下的偽代碼表示:

for i = 1 … 

  A(i-1)= QR

  A(i) = R*Q

end

這段代碼所做的變化類似於A(i) = R*Q = (Q’)*Q*R*Q = (Q’)*A(i-1)*Q;因此這段代碼的基本思想就是使用正交矩陣Q不停的對矩陣A做相似變化。在這樣的變化中將矩陣A的下半三角矩陣中的數全部消去。但是在實際中使用這樣的算法是不現實的,因為每一次QR分解都需要大量的計算,同時完全的矩陣相乘R*Q也需要大量的計算。對這種方法的改進是首先將矩陣A化為Hessenberg型,然后對Hessenbert計算QR分解,對應的code如下:

function [H, U] = zhess(A)

%for any matrix A, turn it into a upper hessenberg matrix by orthogonal 

%transformation

 

[m, n] = size(A);

 

if m ~= n

    error('support square matrix only')

end

 

H = A;

U = eye(n);

 

for k=1:n-2

    

    %compute the householder matrix

    [v, beta] = zhouse(H(k+1:end, k));

    temp_U = eye(n);

    

    temp_U(k+1:n,k+1:n) = eye(n-k) - beta*v*(v');

    

    H = temp_U*H;

    U = U * temp_U;

    

    %fprintf('after %d iteration\n', k);

    %disp(H);

end

 

這段代碼將矩陣A轉換成上hessenberg矩陣。

function [NH] = zhessqr(H)

% perform QR algorithm on upper hessenberg matrix

% firstly, we need to verity this is a hessberg matrix

 

 

[m, n] = size(H);

 

if m ~= n

    error('error, support square matrix only')

end

 

NH = H;

 

c = zeros(1, n-1);

s = zeros(1, n-1);

 

for k=1:n-1

    %compute gives rotation at first

    [c(k), s(k)] = zgivens(NH(k, k), NH(k+1, k));

    p = [c(k) s(k); -s(k) c(k)];

    NH(k:k+1, k:n) = (p')*NH(k:k+1, k:n);

    %fprintf('after %d iteration\n', k);

    %disp(NH);

end

 

for k=1:n-1

    p = [c(k) s(k); -s(k) c(k)];

    NH(1:k+1, k:k+1) = NH(1:k+1,k:k+1)*p;

end

 

這段代碼計算Hessenberg型矩陣A的一個QR step,在這里使用givens旋轉來獲得矩陣的QR分解提高了效率。

 

在QR算法中最主要的步驟就是QR step,首先做QR分解,然后R*Q,為了加快算法收斂的速度,使用了基於位移的QR算法,基本的偽代碼如下:

for i=1 ...

    A - a*I = QR

    R*Q + a*I = A

end

使用這個方法可以加快QR算法的收斂速度。在這個算法的基礎上有隱式雙位移算法,稱為Francis QR。首先給出顯式的雙位移算法:

 

for i=1:infinite

    H(0) - a1*I = Q(1)*R(1)

    H(1) = R(1)*Q(1) + a1*I

    H(1) - a2*I = Q(2)*R(2)

    H(2) = R(2)*Q(2) + a2*I

end

 

略加推倒可以獲得如下的公式:

>> H(2) = (Z’)*H*Z; M = Z*R; M = (H-a1*I)(H-a2*I);

Francis QR可以在不顯式的構造矩陣M的情況下,完成H2=Z’ * H * Z;

Francis QR算法可以使用依賴於隱式Q定理,對應的Matlab代碼如下:

function [H, U] = zfrancisqr(A)

%compute one of the step by implicitly shifted QR step

 

[m, n] = size(A);

 

if m ~= n

    error('support square matrix only')

end

 

m = n-1;

 

s = A(m, m) + A(n, n);

t = A(m, m)*A(n, n) - A(m, n)*A(n, m);

 

x = A(1,1)*A(1,1) + A(1,2)*A(2,1) - s*A(1,1) + t;

y = A(2,1)*(A(1,1) + A(2,2) - s);

z = A(2,1)*A(3,2);

 

for k=0:n-3

    

    [v, beta] = zhouse([x y z]');

    

    q = max([1 k]);

    

    %orthogonal transformation

    ot = (eye(3) - beta*v*(v'));

    

    A(k+1:k+3,q:n) = ot*A(k+1:k+3, q:n);

    

    r = min([k+4 n]);

    A(1:r, k+1:k+3) = A(1:r, k+1:k+3)*(ot');

    

    x = A(k+2, k+1);

    y = A(k+3, k+1);

    if k < n-3

        z = A(k+4, k+1);

    end

end

 

[v, beta] = zhouse([x y]');

ot = eye(2) - beta*v*(v');

A(n-1:n, n-2:n) = ot*A(n-1:n, n-2:n);

A(1:n, n-1:n) = A(1:n, n-1:n)*(ot');

 

H = A;

U = eye(n);

 

隱式Q定理的基本內容如下:對於矩陣A,存在兩個不同的相似變換Q’*A*Q = H, V’*A*V=G,H和G是上Hessenberg矩陣,如果Q和V的第一列相同,那么這兩個不同的相似變換就是等價的。因此Francis QR的第一步就是計算矩陣M的第一列,然后使用householder reflector將之變成e1,然后將變換后的矩陣轉換成上Hessenberg矩陣,這個時候就完成了一步Francis QR。這個方式之所以可以使用隱式Q定理是因為第一個householder reflector是針對M的第一列計算的,而且后來的householder reflector的第一列都是e1,因為最后計算出的變換矩陣的第一列和直接在M上計算QR分解是相同的。

這就是QR算法涉及的主要內容,事實上QR算法的研究很多,但是這里這是給出基本的,而且沒有給出完成的計算程序,是因為我現在還不能完全理解整個過程。下面對於Spectral Decomposition和Singular Value Decompositon介紹也要擱置一段時間,第一是因為兩個算法很復雜,需要一段時間來理解;第二個原因是因為現在沒有很強的需求去研究到這樣的細節。目前依靠LAPACK和Matlab足以解決我大部分的任務,慢慢來吧。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM