Uso a decomposição de Cholesky para simular variáveis aleatórias correlacionadas, dada uma matriz de correlação. A questão é que o resultado nunca reproduz a estrutura de correlação conforme é fornecida. Aqui está um pequeno exemplo em Python para ilustrar a situação.
import numpy as np
n_obs = 10000
means = [1, 2, 3]
sds = [1, 2, 3] # standard deviations
# generating random independent variables
observations = np.vstack([np.random.normal(loc=mean, scale=sd, size=n_obs)
for mean, sd in zip(means, sds)]) # observations, a row per variable
cor_matrix = np.array([[1.0, 0.6, 0.9],
[0.6, 1.0, 0.5],
[0.9, 0.5, 1.0]])
L = np.linalg.cholesky(cor_matrix)
print(np.corrcoef(L.dot(observations)))
Isso imprime:
[[ 1. 0.34450587 0.57515737]
[ 0.34450587 1. 0.1488504 ]
[ 0.57515737 0.1488504 1. ]]
Como você pode ver, a matriz de correlação estimada post-hoc difere drasticamente da matriz anterior. Existe um erro no meu código ou existe alguma alternativa ao uso da decomposição de Cholesky?
Editar
Peço perdão por essa bagunça. Não achei que houvesse um erro no código e / ou na maneira como a decomposição de Cholesky era aplicada devido a algum mal-entendido do material que eu havia estudado antes. Na verdade, eu tinha certeza de que o método em si não era para ser preciso e eu estava bem com isso até a situação que me levou a postar essa pergunta. Obrigado por apontar o equívoco que eu tive. Editei o título para refletir melhor a situação real, como proposto por @Silverfish.
fonte
Respostas:
A abordagem baseada na decomposição de Cholesky deve funcionar, é descrita aqui e é mostrada na resposta de Mark L. Stone postada quase ao mesmo tempo que esta resposta.
Exemplo em
R
(desculpe, eu não estou usando o mesmo software que você usou na pergunta):Você também pode estar interessado neste post e neste post .
fonte
As pessoas provavelmente encontrarão seu erro muito mais rápido se você explicar o que fez com palavras e álgebra em vez de código (ou pelo menos escrevê-lo usando pseudocódigo).
Você parece estar fazendo o equivalente a isso (embora possivelmente transposto):
O que você deve fazer é o seguinte:
Há muitas explicações sobre esse algoritmo no local. por exemplo
Como gerar números aleatórios correlacionados (médias, variações e grau de correlação)?
Posso usar o método de Cholesky para gerar variáveis aleatórias correlacionadas com determinada média?
Este discute-o diretamente em termos da matriz de covariância desejada e também fornece um algoritmo para obter uma covariância de amostra desejada :
Gerando dados com uma determinada matriz de covariância de amostra
fonte
Não há nada de errado com a fatoração de Cholesky. Há um erro no seu código. Veja a edição abaixo.
Aqui estão o código e os resultados do MATLAB, primeiro para n_obs = 10000 como você possui, depois para n_obs = 1e8. Por simplicidade, como não afeta os resultados, não me preocupo com os meios, ou seja, os faço zeros. Observe que o chol do MATLAB produz um fator Cholesky triangular superior R da matriz M, de modo que R '* R = M. numpy.linalg.cholesky produz um fator Cholesky triangular inferior, sendo necessário um ajuste em relação ao meu código; mas acredito que seu código é bom nesse sentido.
Edit: Encontrei seu erro. Você aplicou incorretamente o desvio padrão. Isso é o equivalente ao que você fez, o que está errado.
fonte
O CV não é sobre código, mas fiquei intrigado ao ver como isso ficaria depois de todas as boas respostas, e especificamente da contribuição de Mark L. Stone. A resposta real à pergunta é fornecida em sua postagem (credite sua postagem em caso de dúvida). Estou movendo essas informações anexadas aqui para facilitar a recuperação desta postagem no futuro. Sem descartar nenhuma das outras excelentes respostas, após a resposta de Mark, isso encerra o problema, corrigindo a postagem no OP.
Fonte
EM PITÃO:
EM R]:
fonte
Como outros já mostraram: obras cholesky. Aqui, um trecho de código muito curto e muito próximo ao pseudocódigo: uma peça de código no MatMate:
fonte