5

A任意のサイズの行列を取得し、SVD で分解するプログラムを作成しようとしています。

A = U * S * V'

ここAで、 はユーザーが入力する行列、は の固有ベクトルで構成される直交行列、 は特異値の対角行列、 はのU固有ベクトルの直交行列です。A * A'SVA' * A

問題は、MATLAB 関数eigが時々間違った固有ベクトルを返すことです。

これは私のコードです:

function [U,S,V]=badsvd(A)
W=A*A';
[U,S]=eig(W);
max=0;
for i=1:size(W,1) %%sort
    for j=i:size(W,1)
        if(S(j,j)>max)
            max=S(j,j);
            temp_index=j;
        end
    end
    max=0;
    temp=S(temp_index,temp_index);
    S(temp_index,temp_index)=S(i,i);
    S(i,i)=temp;
    temp=U(:,temp_index);
    U(:,temp_index)=U(:,i);
    U(:,i)=temp;
end
W=A'*A;
[V,s]=eig(W);
max=0;
for i=1:size(W,1) %%sort
    for j=i:size(W,1)
        if(s(j,j)>max)
            max=s(j,j);
            temp_index=j;
        end
    end
    max=0;
    temp=s(temp_index,temp_index);
    s(temp_index,temp_index)=s(i,i);
    s(i,i)=temp;
    temp=V(:,temp_index);
    V(:,temp_index)=V(:,i);
    V(:,i)=temp;
end
s=sqrt(s);
end

私のコードは正しい行列を返し、「sほぼ」正しい行列も返します。ただし、一部の列は -1 で乗算されます。明らかに が固有ベクトルの場合は固有ベクトルでもありますが、符号が反転しているため (すべてではなく一部の列について)、 が得られません。UVt-tA = U * S * V'

これを修正する方法はありますか?

例: 行列の場合A=[1,2;3,4]、関数は次を返します。

U=[0.4046,-0.9145;0.9145,0.4046]

組み込みの MATLABsvd関数は次を返します。

u=[-0.4046,-0.9145;-0.9145,0.4046]
4

1 に答える 1