det матрицы возвращает 0 в matlab - PullRequest
5 голосов
/ 09 октября 2011

Мне дали очень большую матрицу (я не могу изменить значения матрицы), и мне нужно вычислить обратную матрицу (ковариации).

Иногда я получаю сообщение об ошибке:

 Matrix is close to singular or badly scaled.
     Results may be inaccurate

. В этих ситуациях я вижу, что значение det возвращает 0.

Перед вычислением обратного (ковариационной матрицы)Я хочу проверить значение det и выполнить что-то вроде этого

covarianceFea=cov(fea_class);
covdet=det(covarianceFea);
if(covdet ==0)
    covdet=covdet+.00001;
    %calculate the covariance using this new det
end 

Есть ли способ использовать новый det, а затем использовать его для вычисления инверсии ковариационной матрицы?

Ответы [ 3 ]

16 голосов
/ 09 октября 2011

Вздох.Вычисление детерминанта для определения сингулярности - это совершенно нелепая вещь.Особенно это касается большой матрицы.Извините, но это так.Зачем?Да, некоторые книги говорят вам сделать это.Может быть, даже ваш инструктор.

Аналитическая особенность - это одно.Но как насчет численного определения сингулярности?Если вы не используете символический инструмент, MATLAB использует арифметику с плавающей запятой.Это означает, что он хранит числа как числа с плавающей запятой и значения двойной точности.Эти числа не могут быть меньше по величине, чем

>> realmin
ans =
  2.2251e-308

(На самом деле, MATLAB немного ниже, чем в терминах денормализованных чисел, которые могут снизиться примерно до 1e-323.)Чтобы сохранить число меньше этого, MATLAB считает, что оно равно нулю.

>> A = 1e-323
A =
  9.8813e-324

>> A = 1e-324
A =
     0

Что происходит с большой матрицей?Например, является ли эта матрица единственной:

M = eye(1000);

Поскольку M - единичная матрица, она довольно явно неособа.Фактически, det предполагает, что это не единственное число.

>> det(M)
ans =
     1

Но, умножьте это на некоторую константу.Это делает это не единственное число?НЕТ !!!!!!!!!!!!!!!!!!!!!!!!Конечно, нет.Но все равно попробуйте.

>>     det(M*0.1)
ans =
     0

Хмм.Это странно.MATLAB говорит мне, что определитель равен нулю.Но мы знаем, что определителем является 1e-1000.О да.Черт возьми, 1e-1000 меньше, на значительную сумму, чем наименьшее число, которое я только что показал вам, что MATLAB может хранить как двойное число.Таким образом, определитель теряет значение, даже если он явно не равен нулю.Является ли матрица единственной?Конечно, нет.Но использование det терпит неудачу здесь?Конечно, будет, и это вполне ожидаемо.

Вместо этого используйте хороший инструмент для определения сингулярности.Используйте такой инструмент, как cond или rank.Например, можем ли мы обмануть ранг?

>> rank(M)
ans =
        1000

>> rank(M*.1)
ans =
        1000

Видим, что ранг знает, что это матрица полного ранга, независимо от того, масштабируем мы ее или нет.То же самое верно и для cond, вычисляющего число условия M.

>> cond(M)
ans =
     1

>> cond(M*.1)
ans =
     1

Добро пожаловать в мир арифметики с плавающей запятой.И, кстати, забудьте о det как о инструменте практически для любых вычислений, использующих арифметику с плавающей запятой.Это плохой выбор почти всегда.

5 голосов
/ 09 октября 2011

Woodchips дал вам очень хорошее объяснение того, почему вы не должны использовать определитель.Похоже, это распространенное заблуждение, и ваш вопрос очень связан с другим вопросом об инвертировании матриц: Есть ли быстрый способ инвертировать матрицу в Matlab? , когда ОП решил, что это так, как определитель его матрицыбыл 1, это было определенно обратимо!Вот фрагмент моего ответа

Вместо det(A)=1 номер условия вашей матрицы определяет, насколько точным или стабильным будет обратное.Обратите внимание, что det(A)=∏<sub>i=1:n</sub> λ<sub>i</sub>.Так что просто установка λ<sub>1</sub>=M, λ<sub>n</sub>=1/M и λ<sub>i≠1,n</sub>=1 даст вам det(A)=1.Тем не менее, как M → ∞, cond(A) = M<sup>2</sup> → ∞ и λ<sub>n</sub> → 0, что означает, что ваша матрица приближается к сингулярности, и при вычислении обратного значения будут большие числовые ошибки.следующий простой пример:

A = eye(10);
A([1 2]) = [1e15 1e-15];

%# calculate determinant
det(A)
ans =

     1

%# calculate condition number
cond(A)
ans =

   1.0000e+30
1 голос
/ 09 октября 2011

В таком случае вычисление обратного не очень хорошая идея. Если вам просто нужно это сделать, я бы предложил использовать это для увеличения точности отображения:

format long;

Другое предложение может состоять в том, чтобы попробовать использовать SVD матрицы и повозиться там с единичными значениями.

A = U∑V'
inv(A) = V*inv(∑)*U'

∑ - это диагональная матрица, в которой вы увидите одну из диагональных записей, близких к 0. Попробуйте поиграть с этим числом, если вы хотите какое-то приближение.

...