Tornando a raiz quadrada da matriz de covariância positiva-definida (Matlab)

9

Motivação : estou escrevendo um estimador de estado no MATLAB (o filtro Kalman sem cheiro), que exige a atualização da raiz quadrada (triangular superior) de uma matriz de covariância a cada iteração (ou seja, para uma matriz de covariância , é verdade que ). Para que eu possa executar os cálculos necessários, preciso fazer uma Atualização e Downdate Rank-1 de Cholesky usando a função do MATLAB .P P = S S TSPP=SSTcholupdate

Problema : Infelizmente, durante o curso das iterações, essa matriz às vezes pode perder uma definição positiva. O downdate de Cholesky falha em matrizes não PD.S

Minha pergunta é : existem formas simples e confiáveis ​​no MATLAB de tornar positivo-definido?S

( ou, mais geralmente, existe uma boa maneira de tornar positiva qualquer matriz covariância positivaX ) ?


Notas :

  • S é classificação completa
  • Eu tentei a abordagem eigendecomposition (que não funcionou). Isso basicamente envolveu encontrar , definir todos os elementos negativos de e reconstruir um novo que são matrizes apenas com elementos positivos. V , D = 1 × 10 - 8 S = V D V T V , D S=VDVTV,D=1×108S=VDVTV,D
  • Estou ciente da abordagem de Higham (que é implementada em R as nearpd), mas parece projetar apenas a matriz PSD mais próxima. Eu preciso de uma matriz PD para a atualização Cholesky.
Gilead
fonte
Acho que talvez você queira , onde é a covariância e é o fator de Cholesky. S PS=PPSP
shabbychef
Na verdade, eu quero que (a raiz quadrada ou, neste caso, o fator Cholesky) seja definido positivamente. Eu esclareci a pergunta; obrigado! S
Gileade
Eu estou tendo o mesmo problema. Tentei a função sqrtm (x), mas funcionou apenas para algumas iterações. Você encontrou a solução?
Tentei vários métodos, mas acabei usando o truque padrão (não rigoroso) de perturbar as diagonais, ou seja, , onde é uma constante suficientemente grande para tornar positivo definitivo. Talvez haja abordagens melhores, mas essa foi rápida e fácil. k SS+kIkS
Gilead
Um pouco tarde, mas girar é uma estratégia útil para numericamente instável.
probabilityislogic

Respostas:

4

Aqui está o código que eu usei no passado (usando a abordagem SVD). Sei que você disse que já tentou, mas sempre funcionou para mim, então pensei em publicá-lo para ver se era útil.

function [sigma] = validateCovMatrix(sig)

% [sigma] = validateCovMatrix(sig)
%
% -- INPUT --
% sig:      sample covariance matrix
%
% -- OUTPUT --
% sigma:    positive-definite covariance matrix
%

EPS = 10^-6;
ZERO = 10^-10;

sigma = sig;
[r err] = cholcov(sigma, 0);

if (err ~= 0)
    % the covariance matrix is not positive definite!
    [v d] = eig(sigma);

    % set any of the eigenvalues that are <= 0 to some small positive value
    for n = 1:size(d,1)
        if (d(n, n) <= ZERO)
            d(n, n) = EPS;
        end
    end
    % recompose the covariance matrix, now it should be positive definite.
    sigma = v*d*v';

    [r err] = cholcov(sigma, 0);
    if (err ~= 0)
        disp('ERROR!');
    end
end
usuario
fonte
Obrigado pelo seu esforço - infelizmente, não funcionou. (Eu estava fazendo algo muito semelhante no meu programa de 3 linhas:) [V,D] = eig(A); D(D <= 1e-10) = 1e-6; Apd = V*A*V';. Essa abordagem é semelhante à de Rebonato e Jackel, e parece falhar em casos patológicos como o meu.
Gilead
Isso é ruim. Eu estaria interessado em uma matriz de exemplo que você descobriu que faz com que isso (e outros métodos que você tentou) falhe se você tiver tempo para postar uma. Este é um problema tão agravante para continuar correndo, espero que você encontre uma solução.
Nick
2

em Matlab:

help cholupdate

eu recebo

CHOLUPDATE Rank 1 update to Cholesky factorization.
    If R = CHOL(A) is the original Cholesky factorization of A, then
    R1 = CHOLUPDATE(R,X) returns the upper triangular Cholesky factor of A + X*X',
    where X is a column vector of appropriate length.  CHOLUPDATE uses only the
    diagonal and upper triangle of R.  The lower triangle of R is ignored.

    R1 = CHOLUPDATE(R,X,'+') is the same as R1 = CHOLUPDATE(R,X).

    R1 = CHOLUPDATE(R,X,'-') returns the Cholesky factor of A - X*X'.  An error
    message reports when R is not a valid Cholesky factor or when the downdated
    matrix is not positive definite and so does not have a Cholesky factorization.

    [R1,p] = CHOLUPDATE(R,X,'-') will not return an error message.  If p is 0
    then R1 is the Cholesky factor of A - X*X'.  If p is greater than 0, then
    R1 is the Cholesky factor of the original A.  If p is 1 then CHOLUPDATE failed
    because the downdated matrix is not positive definite.  If p is 2, CHOLUPDATE
    failed because the upper triangle of R was not a valid Cholesky factor.

    CHOLUPDATE works only for full matrices.

    See also chol.
shabbychef
fonte
Estou usando, cholupdatemas minha pergunta é sobre como tornar R(neste caso) positivo definitivo. Eu tenho um caso em que meu Ré não-pd e cholupdate(R,X,'-')(um downdate) falha.
Gileade
1
todos os algoritmos on-line deste formulário (atualização e downdate) sofrem de problemas de precisão como este. Eu tive problemas semelhantes em 1d, resultando em estimativas de variação negativas. Minha sugestão seria manter um buffer circular dos últimos k vetores observados e, quando cholupdatefalhar, recalcular a covariância com base nesse buffer circular e reduzir o custo. Se você possui memória e pode suportar o tempo ocasional de acerto quando isso acontece, não encontrará um método melhor em termos de precisão e facilidade de implementação.
21711 shabbychef
Obrigado, é algo para se pensar. Infelizmente, minha matriz de covariância passa por tantas transformações que não está claro em que ponto eu tenho uma recomputação do buffer circular. No entanto, se tudo mais falhar, devo ser capaz de usar a última matriz de covariância de PD conhecida - com a esperança de que não produza um viés nas minhas estimativas.
Gilead
2

Uma maneira alternativa de calcular a fatoração de Cholesky é fixando os elementos diagonais de S em 1 e, em seguida, introduzindo uma matriz diagonal D, com elementos positivos.

Isso evita a necessidade de criar raízes quadradas ao realizar os cálculos, o que pode causar problemas ao lidar com números "pequenos" (ou seja, números pequenos o suficiente para que o arredondamento que ocorre devido a operações de ponto flutuante seja importante). A página da wikipedia tem a aparência desse algoritmo ajustado.

Então, em vez de você obtém com P = R D R T S = R D 1P=SSTP=RDRTS=RD12

Espero que isto ajude!

probabilityislogic
fonte
1
Obrigado, essa é uma técnica que eu poderia usar potencialmente. Parece que foi implementado aqui: infohost.nmt.edu/~borchers/ldlt.html
Gilead
1

Efetivamente, a fatoração de Cholesky pode falhar quando sua matriz não é "realmente" positivamente definida. Aparecem dois casos, ou você tem um valor de eingen negativo ou seu menor valor de eingen é positivo, mas próximo de zero. O segundo caso deve teoricamente dar uma solução, mas numericamente difícil. Se tiver apenas intuitivo, adicione uma pequena constante à diagonal da minha matriz para resolver o problema. Mas esse caminho não é rigoroso porque modifica um pouco a solução. Se você precisar calcular uma solução de alta precisão, tente algumas pesquisas sobre a fatoração de Cholesky modificada.

ctNGUYEN
fonte
0

Se você tentar estimar com P não positivo positivo, está solicitando problemas e algoritmos de desafio, evite esta situação. Se o seu problema for numérico: P é definitivo positivo, mas o autovalor numérico é muito pequeno - tente uma nova ameaça para os seus estados. Espero que o conselho não seja tarde demais Atenciosamente, Zeev

Zeev Berman
fonte