2017-01-06 13 views
2

Я использую MATLAB для вычисления условной ковариации и значения с использованием модели смеси Гаусса, которая всегда относится к Schur complement. В Wiki предлагается, что если матрица C является сингулярной, то для вычисления дополнения Шура можно использовать обобщенный инверсный C.Как определить матрицу с точностью до рабочей точности в Matlab

В MATLAB, pinv для этой цели. Поскольку моя матрица очень большая (более 1000 столбцов) и приведет к ковариационной матрице с размером > 1000*1000, для вычисления может быть намного быстрее использовать eig вместо svd. Однако это может потерять замечательную точность, поскольку он обрезает собственные векторы, соответствующие малым собственным значениям с заданным порогом.

Другим способом является использование функции rmdivide для вычисления BC^(-1) как B/C, так как обратная матрица может рассматриваться как проблема наименьшего квадрата. В моей проблеме это может получить гораздо более высокую точность и работать намного быстрее, чем при использовании B*pinv(C). Кроме того, rmdivide может иметь дело с некоторой сингулярной матрицей, поэтому этот метод является предпочтительным. Но в некоторых случаях может возникнуть предупреждение Matrix is singular to working precision, результатом которого является NaNs, если используется rmdivide. Итак, есть ли способ определить, когда возникнет это предупреждение, поэтому я могу вместо этого использовать pinv?

Update

В дополнение к @ ответ Dohyun, в то, что я сейчас делаю, чтобы проверить полученные результаты, основываясь на том факте, что NaN можно получить в результатах, если матрица вырождена.

warning('off','MATLAB:singularMatrix') 
x = b/C; % in my codes, vector is obtained, I think matrix can also be checked in this way 
if isnan(sum(x)) 
    x = b*pinv(C); 
end 

ответ

3

Если матрица C является «обычно» неособо и mrdvide гораздо быстрее, чем pinv, то вы можете попробовать mrdivide, а затем поймать предупреждение, чтобы переключиться на pinv.

Однако в MATLAB мы не можем уловить предупреждение, используя try. К счастью, есть undocumented solution, чтобы поймать предупреждение.

Основная идея превратить warning в error для конкретного предупреждения ID (в вашем случае, MATLAB:singularMatrix) вы будете иметь, а затем использовать try и catch.

myWarn = warning('error','MATLAB:singularMatrix'); % turn singular matrix warning to error 
try 
    u = mrdivide(B,C); 
catch 
    u = B*pinv(C); 
end 
warning(myWarn); % return to warning 
+2

+1! небольшое улучшение: лучше использовать 'ws = warning ('error', ...)', а затем в конце 'warning (ws);'. Таким образом, состояние предупреждения сбрасывается до того, что было до операции, а не заставляло его «на». –

+0

Изменен мой ответ! спасибо – Dohyun

+0

Спасибо, это хорошая идея. Но я не предпочитаю шаблон 'try ... catch ... ', поскольку это может значительно замедлить вычисление, если оно вставлено в циклы с большим количеством итераций. Я обновил собственное решение для моего вопроса. Я думаю, что это более прямолинейно. – Elkan

 Смежные вопросы

  • Нет связанных вопросов^_^