Gostaria de gerar uma matriz de correlação aleatório de n x n de tamanho de tal modo que existem algumas correlações moderadamente fortes presente:
- matriz quadrada de reais simétrico de tamanho, por exemplo, com n = 100 ;
- positivo-definido, ou seja, com todos os autovalores reais e positivos;
- classificação completa;
- todos os elementos diagonais são iguais a ;
- elementos fora da diagonal devem ser razoavelmente distribuídos uniformemente em . A distribuição exata não importa, mas eu gostaria de ter uma quantidade moderadamente grande (por exemplo, 10 % ) de valores moderadamente grandes (por exemplo, com valor absoluto de 0,5 ou superior). Basicamente eu quero ter certeza de que C é não quase diagonal com todos os elementos fora da diagonal ≈ 0 .
Existe uma maneira simples de fazer isso?
O objetivo é usar essas matrizes aleatórias para comparar alguns algoritmos que trabalham com matrizes de correlação (ou covariância).
Métodos que não funcionam
Aqui estão algumas maneiras de gerar matrizes de correlação aleatória que eu conheço, mas que não funcionam para mim aqui:
Gere aleatório de tamanho s × n , centralize, padronize e forme a matriz de correlação C = 1. Ses>n, isso geralmente resultará em todas as correlações fora da diagonal em torno de0. Ses«n, algumas correlações será forte, masCnão será posto completo.
Gere a matriz definida positiva aleatória de uma das seguintes maneiras:
Gere o quadrado aleatório e faça B positivo definido simétrico B = A A positive .
Gere o quadrado aleatório , torne simétrico E = A + A ⊤ e torne-o positivo definitivo, realizando a decomposição do Eigen E = U S U ⊤ e definindo todos os autovalores negativos para zero: B = U . NB: isso resultará em uma matriz deficiente na classificação.
Gere ortogonal aleatório (por exemplo, gerando quadrado aleatório A e fazendo sua decomposição QR, ou via processo de Gram-Schmidt) e diagonal D aleatória com todos os elementos positivos; forma B = Q D Q ⊤ .
Obteve matriz pode ser facilmente normalizada ter todos aqueles na diagonal: C = D - 1 / 2 B D - 1 / 2 , onde D = d i um g é a matriz diagonal com o mesmo diagonal como B . Todas as três maneiras listadas acima para gerar B resultam em C com elementos fora da diagonal perto de 0 .
Atualização: Tópicos mais antigos
Depois de postar minha pergunta, encontrei duas quase duplicatas no passado:
- Como gerar uma matriz de correlação aleatória que tem aproximadamente entradas normalmente fora da diagonal distribuídas com determinado desvio padrão?
- Como gerar eficientemente matrizes de correlação aleatória positiva-semidefinida?
Infelizmente, nenhum desses tópicos continha uma resposta satisfatória (até agora :)
fonte
nXk
matriz de carregamento W, não totalmente aleatória, mas a que queremos (elaWW'+diag(noise)
definirá a matriz cov que procuramos. A única tarefa é corrigir o W normalizado pela coluna (ou seja, k "eigenvectors") para se tornar ortogonal Qualquer método para de-correlato variáveis correlacionadas (aqui variáveis são os autovetores) provavelmente irá fazer (Esta uma idéia crua)...Respostas:
Outras respostas surgiram com bons truques para resolver meu problema de várias maneiras. No entanto, encontrei uma abordagem baseada em princípios que acredito ter uma grande vantagem de ser conceitualmente muito clara e fácil de ajustar.
Nesta discussão: Como gerar eficientemente matrizes de correlação aleatória positiva-semidefinida? - Descrevi e forneci o código para dois algoritmos eficientes de geração de matrizes de correlação aleatória. Ambos vêm de um artigo de Lewandowski, Kurowicka e Joe (2009), ao qual o @ssdecontrol se refere nos comentários acima (muito obrigado!).
Por favor, veja minha resposta lá para muitas figuras, explicações e código do matlab. O chamado método "vine" permite gerar matrizes de correlação aleatórias com qualquer distribuição de correlações parciais e pode ser usado para gerar matrizes de correlação com grandes valores fora da diagonal. Aqui está a figura de exemplo desse segmento:
A única coisa que muda entre as subparcelas é um parâmetro que controla quanto a distribuição das correlações parciais se concentra em torno de .± 1
Copio meu código para gerar essas matrizes aqui também, para mostrar que não é mais longo que os outros métodos sugeridos aqui. Por favor, veja minha resposta vinculada para algumas explicações. Os valores de50 , 20 , 10 , 5 , 2 , 1 100
betaparam
para a figura acima foram (e a dimensionalidadefoi 100 ).d
Atualização: autovalores
@psarka pergunta sobre os autovalores dessas matrizes. Na figura abaixo, planto os espectros de autovalor das mesmas seis matrizes de correlação acima. Observe que eles diminuem gradualmente; por outro lado, o método sugerido por @psarka geralmente resulta em uma matriz de correlação com um grande autovalor, mas o restante é bastante uniforme.
Atualizar. Método realmente simples: vários fatores
Semelhante ao que @ttnphns escreveu nos comentários acima e @GottfriedHelms em sua resposta, uma maneira muito simples de alcançar meu objetivo é gerar aleatoriamente várias cargas de fator ( )k < n (matriz aleatória detamanho k × n ), formar o matriz de covariância W W ⊤ (que obviamente não será a classificação completa) e adicione a ela umamatriz diagonal aleatóriaW k × n W W⊤ com os elementos positivos para fazer B = W W ⊤ + DD B = W W⊤+ D classificação completa. A matriz de covariância resultante pode ser normalizada para se tornar uma matriz de correlação (conforme descrito na minha pergunta). Isso é muito simples e faz o truque. Aqui estão alguns exemplos de matrizes de correlação para :k = 100 , 50 , 20 , 10 , 5 , 1
A única desvantagem é que a matriz resultante terá valores próprios grandes e, em seguida, uma queda repentina, em oposição a uma boa decadência mostrada acima com o método vine. Aqui estão os espectros correspondentes:k
Aqui está o código:
fonte
W
são ortogonais (isto é, cossenos entre elas são 0). Simplesmente gerar aleatoriamente,W
claro, não fornece isso. Se eles não são ortogonais - ou seja, são factores oblíqua (chamada entãoW
comoW_
) - factor de teorema não éWW'
masW_CW_'
comC
sendo "correlações" (co-senos) entre factores. Agora,C=Q'Q
comQ
sendo a matriz de rotação não ortogonal de rotaçãoW_=inv(Q)'W
(e assimW=W_Q'
). Gere um poucoQ
- uma matriz com a coluna ss = 1 e matriz ss = tamanho da matriz.W_=inv(Q)'W
, é claroW_= W inv(Q)'
.W = replicate(k, rnorm(d)); S = W%*%t(W) + diag(rnorm(d),nrow=d); S = diag(1/sqrt(diag(S)))%*%S%*%diag(1/sqrt(diag(S)))
S <- matrix(nearPD(S, corr = TRUE, keepDiag = TRUE)$mat@x,ncol(S),ncol(S))
fonte
crs
Hmm, depois de fazer um exemplo na minha linguagem MatMate, vejo que já existe uma resposta em python, que pode ser preferível porque o python é amplamente usado. Mas como você ainda tinha perguntas, mostro a minha abordagem usando a linguagem Matmate-matrix, talvez seja mais auto-comentada.
Método 1
(usando o MatMate):
O problema aqui pode ser que definimos blocos de submatrizes que possuem altas correlações com pouca correlação entre e isso não é programaticamente, mas pelas constantes expressões de concatenação. Talvez essa abordagem possa ser modelada de forma mais elegante em python.
Método 2 (a)
Depois disso, existe uma abordagem completamente diferente, na qual preenchemos a possível covariância restante por quantidades aleatórias de 100% em uma matriz de cargas fatoriais. Isso é feito no Pari / GP:
e a matriz de correlação produzida é
Possivelmente, isso gera uma matriz de correlação com componentes principais dominantes devido à regra de geração cumulativa para a matriz de cargas fatoriais. Também pode ser melhor garantir uma definição positiva, tornando a última parte da variação um fator único. Deixei no programa para manter o foco no princípio geral.
Uma matriz de correlação 100x100 tinha as seguintes frequências de correlações (arredondadas para 1 dec)
[atualizar]. Hmm, a matriz 100x100 está mal condicionada; Pari / GP não pode determinar os valores próprios corretamente com as polroots (charpoly ()) - função mesmo com precisão de 200 dígitos. Fiz uma rotação de Jacobi para formar pca na matriz de loadings L e encontro principalmente autovalores extremamente pequenos, imprimi-os em logaritmos na base 10 (que fornecem aproximadamente a posição do ponto decimal). Leia da esquerda para a direita e depois linha por linha:
[atualização 2]
Método 2 (b)
Uma melhoria pode ser aumentar a variação específica de itens para algum nível não marginal e reduzir para um número razoavelmente menor de fatores comuns (por exemplo, número inteiro inteiro do número de item):
A estrutura do resultado
em termos de distribuição de correlações:
permanece semelhante (também a descompossibilidade desagradável do PariGP), mas os valores próprios, quando encontrados pela rotação jacobi da matriz de loadings, agora têm uma estrutura melhor.
fonte
Pergunta interessante (como sempre!). Que tal encontrar um conjunto de matrizes de exemplo que exibam as propriedades que você deseja e, em seguida, fazer combinações convexas, pois seUMA e B são definitivos positivos, então também λ A + ( 1 - λ ) B . Como bônus, não será necessário redimensionar as diagonais pela convexidade da operação. Ajustando oλ para estar mais concentrado em 0 e 1 em relação à distribuição uniforme, você pode concentrar as amostras nas bordas do politopo ou no interior. (Você pode usar uma distribuição beta / Dirichlet para controlar a concentração versus uniformidade).
Por exemplo, você pode deixarUMA ser simétrico por componentes e B seja toeplitz. Claro, você sempre pode adicionar outra classeC , e pegue λUMAA + λBB + λCC de tal modo que ∑ λ = 1 e λ ≥ 0 , e assim por diante.
fonte
R possui um pacote (clusterGeneration) que implementa o método em:
Exemplo:
Infelizmente, não parece possível simular correlações que seguem uma distribuição uniforme-ish com isso. Parece fazer correlações mais fortes quando
alphad
é definido com valores muito pequenos, mas mesmo assim1/100000000000000
, o intervalo de correlações seria de apenas 1,40.No entanto, espero que isso possa ser útil para alguém.
fonte