Matlab Eig иногда возвращает перевернутые знаки

Я пытаюсь написать программу, которая получает матрицу A любого размера, а SVD разлагает ее:

A=USV'

Где A - матрица, которую вводит пользователь, U - ортогональная матрица, составляющая собственные векторы AA', S - диагональная матрица сингулярных значений, и V - ортогональная матрица собственных векторов A'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, а также "почти" правильные матрицы U и V. но некоторые столбцы умножаются на -1. очевидно, что если t является собственным вектором, то также -t является собственным вектором, но с инвертированными знаками (для некоторых столбцов не для всех) я не получаю A=USV'.

Есть ли способ это исправить?

пример: для матрицы A=[1,2;3,4] моя функция возвращает:

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

и встроенный Matlab svd функция возвращает:

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

1 ответ

Решение

Обратите внимание, что собственные векторы не являются уникальными. Умножение на любую константу, в том числе -1 (который просто меняет знак), дает другой действительный собственный вектор. Это ясно, учитывая определение собственного вектора:

A·v = λ·v

MATLAB выбирает нормализацию собственных векторов, чтобы иметь норму 1,0, знак произвольный:

За eig(A)собственные векторы масштабируются так, чтобы норма каждого составляла 1,0. За eig(A,B), eig(A,'nobalance'), а также eig(A,B,flag)собственные векторы не нормированы

Теперь, как вы знаете, СВД и собственное разложение взаимосвязаны. Ниже приведен код для проверки этого факта. Обратите внимание, что svd а также eig вернуть результаты в другом порядке (один отсортирован от высокого к низкому, другой в обратном порядке):

% some random matrix
A = rand(5);

% singular value decomposition
[U,S,V] = svd(A);

% eigenvectors of A'*A are the same as the right-singular vectors
[V2,D2] = eig(A'*A);
[D2,ord] = sort(diag(D2), 'descend');
S2 = diag(sqrt(D2));
V2 = V2(:,ord);

% eigenvectors of A*A' are the same as the left-singular vectors
[U2,D2] = eig(A*A');
[D2,ord] = sort(diag(D2), 'descend');
S3 = diag(sqrt(D2));
U2 = U2(:,ord);

% check results
A
U*S*V'
U2*S2*V2'

Я получаю очень похожие результаты (игнорируя незначительные ошибки с плавающей точкой):

>> norm(A - U*S*V')
ans =
   7.5771e-16
>> norm(A - U2*S2*V2')
ans =
   3.2841e-14

РЕДАКТИРОВАТЬ:

Чтобы получить согласованные результаты, обычно принимают соглашение, согласно которому первый элемент в каждом собственном векторе должен иметь определенный знак. Таким образом, если вы получите собственный вектор, который не следует этому правилу, вы умножаете его на -1 перевернуть знак...

Другие вопросы по тегам