Я использую 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
+1! небольшое улучшение: лучше использовать 'ws = warning ('error', ...)', а затем в конце 'warning (ws);'. Таким образом, состояние предупреждения сбрасывается до того, что было до операции, а не заставляло его «на». –
Изменен мой ответ! спасибо – Dohyun
Спасибо, это хорошая идея. Но я не предпочитаю шаблон 'try ... catch ... ', поскольку это может значительно замедлить вычисление, если оно вставлено в циклы с большим количеством итераций. Я обновил собственное решение для моего вопроса. Я думаю, что это более прямолинейно. – Elkan