Come generare una grande matrice di correlazione casuale full-rank con alcune forti correlazioni presenti?


25

Vorrei generare una matrice di correlazione casuale di dimensioni tale che siano presenti alcune correlazioni moderatamente forti: n × nCn×n

  • matrice quadrata simmetrica reale di dimensione, ad es. ;n = 100n×nn=100
  • definito positivo, cioè con tutti gli autovalori reali e positivi;
  • rango pieno;
  • tutti gli elementi diagonali uguali a ;1
  • gli elementi fuori diagonale dovrebbero essere ragionevolmente distribuiti uniformemente su . La distribuzione esatta non ha importanza, ma vorrei avere una quantità moderatamente grande (ad es. ) di valori moderatamente grandi (ad es. Con un valore assoluto di o superiore). Fondamentalmente voglio fare in modo che è non quasi diagonale con tutti gli elementi fuori dalla diagonale .10 % 0,5 C0(1,1)10%0.5C0

C'è un modo semplice per farlo?

Lo scopo è quello di utilizzare tali matrici casuali per confrontare alcuni algoritmi che lavorano con matrici di correlazione (o covarianza).


Metodi che non funzionano

Ecco alcuni modi per generare matrici di correlazione casuali che conosco, ma che non funzionano per me qui:

  1. Generare casuale di dimensioni, centro, standardizzare e formare la matrice di correlazione . Se , ciò comporterà generalmente tutte le correlazioni off-diagonali intorno a . Se , alcune correlazioni saranno forti, ma non sarà al completo. s × n C = 1Xs×ns>n0snCC=1s1XXs>n0snC

  2. Generare una matrice definita positiva casuale in uno dei seguenti modi:B

    • Genera quadrato casuale e definisci simmetrico positivo .B = A AAB=AA

    • Genera un quadrato casuale , rendi simmetrico e rendilo definito positivo eseguendo la decomposizione eigen e azzerando tutti gli autovalori negativi: . NB: questo si tradurrà in una matrice carente di rango.E = A + AE = U S UB = UAE=A+AE=USUB=Umax{S,0}U

    • Genera un ortogonale casuale (ad esempio generando un quadrato casuale e facendo la sua decomposizione QR, o tramite il processo di Gram-Schmidt) e una diagonale casuale con tutti gli elementi positivi; form .A D B = Q D QQADB=QDQ

    La matrice ottenuta può essere facilmente normalizzata per avere tutti quelli sulla diagonale: , dove è la matrice diagonale con la stessa diagonale come . Tutti e tre i modi sopra elencati per generare comportano che con elementi non diagonali chiusi .C = D - 1 / 2 B D - 1 / 2 D = d i un gBC=D1/2BD1/2B B C 0D=diagBBBC0


Aggiornamento: discussioni precedenti

Dopo aver pubblicato la mia domanda, ho trovato due quasi duplicati in passato:

Sfortunatamente, nessuno di questi thread conteneva una risposta soddisfacente (fino ad ora :)


1
È possibile creare una matrice ortogonale casuale mediante i processi QR o Gram-Schmidt. Saranno "autovettori di PCA". Aggiungi scala alle sue colonne (trasformale in "caricamenti"). Ottieni la matrice di covarianza da questi caricamenti. Qualcosa del genere ...
ttnphns

1
Uhm, beh .. Immagina di voler creare una nXkmatrice di caricamento W, non completamente casuale ma quella che vogliamo ( WW'+diag(noise)definirà la matrice cov che cerchiamo. L'unico compito è correggere la W normalizzata a colonna (cioè il k "autovettori") per diventare ortogonali. Qualsiasi metodo per de-correlare variabili correlate (qui le variabili sono gli autovettori) probabilmente lo farà. (Questa è un'idea grezza.)
ttnphns

1
Ah, @whuber, ora capisco cosa intendi. Sì, hai ragione: se tutti gli elementi off-diagonali sono identici e uguali a , allora la matrice è davvero piena e definita positiva ... Questo ovviamente non è quello che avevo in mente: vorrei la distribuzione di elementi off-diagonali in ciascuna matrice da ragionevolmente "diffondere", non la distribuzione tra matrici ...ρ
Ameba dice Reinstate Monica,

3
Potresti voler esaminare la distribuzione LKJ
Shadowtalker,

2
@ttnphns: Penso di aver finalmente capito che avevi sempre ragione: quello che hai suggerito è il modo più semplice per raggiungere l'obiettivo. Ho aggiunto un aggiornamento alla mia risposta implementando essenzialmente ciò che hai scritto sopra.
ameba dice Ripristina Monica il

Risposte:


14

Altre risposte hanno fornito dei bei trucchi per risolvere il mio problema in vari modi. Tuttavia, ho trovato un approccio di principio che penso abbia un grande vantaggio di essere concettualmente molto chiaro e facile da adattare.

In questo thread: come generare in modo efficiente matrici di correlazione semidefinite positive casuali? - Ho descritto e fornito il codice per due algoritmi efficienti di generazione di matrici di correlazione casuali. Entrambi provengono da un articolo di Lewandowski, Kurowicka e Joe (2009), a cui @ssdecontrol faceva riferimento nei commenti sopra (grazie mille!).

Si prega di vedere la mia risposta lì per un sacco di cifre, spiegazioni e codice matlab. Il cosiddetto metodo "vine" consente di generare matrici di correlazione casuali con qualsiasi distribuzione di correlazioni parziali e può essere utilizzato per generare matrici di correlazione con grandi valori off-diagonali. Ecco la figura di esempio da quel thread:

Metodo della vite

L'unica cosa che cambia tra le sottotrame, è un parametro che controlla quanto la distribuzione delle correlazioni parziali sia concentrata attorno a .±1

Copio il mio codice per generare anche queste matrici qui, per mostrare che non è più lungo degli altri metodi suggeriti qui. Si prega di consultare la mia risposta collegata per alcune spiegazioni. I valori di betaparamper la figura sopra erano (e la dimensionalità era ). 10050,20,10,5,2,1d100

function S = vineBeta(d, betaparam)
    P = zeros(d);           %// storing partial correlations
    S = eye(d);

    for k = 1:d-1
        for i = k+1:d
            P(k,i) = betarnd(betaparam,betaparam); %// sampling from beta
            P(k,i) = (P(k,i)-0.5)*2;     %// linearly shifting to [-1, 1]
            p = P(k,i);
            for l = (k-1):-1:1 %// converting partial correlation to raw correlation
                p = p * sqrt((1-P(l,i)^2)*(1-P(l,k)^2)) + P(l,i)*P(l,k);
            end
            S(k,i) = p;
            S(i,k) = p;
        end
    end

    %// permuting the variables to make the distribution permutation-invariant
    permutation = randperm(d);
    S = S(permutation, permutation);
end

Aggiornamento: autovalori

@psarka chiede degli autovalori di queste matrici. Nella figura seguente tracciamo gli spettri autovalori delle stesse sei matrici di correlazione come sopra. Si noti che diminuiscono gradualmente; al contrario, il metodo suggerito da @psarka si traduce generalmente in una matrice di correlazione con un grande autovalore, ma il resto è piuttosto uniforme.

autovalori delle matrici sopra


Aggiornare. Metodo davvero semplice: diversi fattori

Simile a quello che @ttnphns ha scritto nei commenti sopra e @GottfriedHelms nella sua risposta, un modo molto semplice per raggiungere il mio obiettivo è generare casualmente diversi caricamenti di fattori ( ) (matrice casuale di dimensione) , forma la matrice di covarianza (che ovviamente non sarà di rango intero) e aggiungi una matrice diagonale casuale con elementi positivi per creare ranking completo. La matrice di covarianza risultante può essere normalizzata per diventare una matrice di correlazione (come descritto nella mia domanda). Questo è molto semplice e fa il trucco. Ecco alcuni esempi di matrici di correlazione perW k × n W WD B = W W + D k = 100 , 50 , 20 , 10 , 5 , 1k<nWk×nWWDB=WW+Dk=100,50,20,10,5,1 :

matrici di correlazione casuale da fattori casuali

L'unico aspetto negativo è che la matrice risultante avrà grandi autovalori e quindi un calo improvviso, al contrario di un bel decadimento mostrato sopra con il metodo della vite. Ecco gli spettri corrispondenti:k

eigenspectra di queste matrici

Ecco il codice:

d = 100;    %// number of dimensions
k = 5;      %// number of factors

W = randn(d,k);
S = W*W' + diag(rand(1,d));
S = diag(1./sqrt(diag(S))) * S * diag(1./sqrt(diag(S)));

+1. Tuttavia, ecco solo un promemoria per l'ultima sezione sul "metodo dei fattori". L'approccio rigorosamente corretto richiede che le colonne di Wsiano ortogonali (ovvero i coseni tra loro sono 0). La semplice generazione casuale Wnon lo fornisce. Se non sono ortogonali - cioè i fattori sono obliqui (chiama quindi Wcome W_) - il teorema dei fattori non è WW'ma W_CW_'con l' Cessere "correlazioni" (coseni) tra i fattori. Ora, C=Q'Qcon Qessendo la matrice di rotazione non ortogonale di rotazione W_=inv(Q)'W(e così W=W_Q'). Genera un po ' Q- una matrice con colonna ss = 1 e matrice ss = dimensione della matrice.
ttnphns,

... errore di battitura: no W_=inv(Q)'W, certo W_= W inv(Q)'.
ttnphns,

@ttnphns: Quello che stai dicendo è corretto, ma non penso che sia importante ai fini della generazione di matrici di correlazione casuali. Se generi modo casuale, quindi sì, le sue colonne non saranno esattamente ortogonali, ma (dopo la normalizzazione per ottenere tutti quelli sulla diagonale) sarà comunque una matrice di correlazione di rango completo con alcuni grandi valori off-diagonali, di cui si trattava la domanda. Ovviamente è molto facile ortografare in anticipo le colonne di , non ho visto perché questo sarebbe necessario in questo caso. W W + D OWWW+DW
ameba dice Ripristina Monica il

1
Traducendo questo in R: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)))
Scott Worland il

1
@Mihai, buon punto e i tuoi suggerimenti sono probabilmente i più semplici. Potresti anche fareS <- matrix(nearPD(S, corr = TRUE, keepDiag = TRUE)$mat@x,ncol(S),ncol(S))
Scott Worland l'

7

Una cosa semplice, ma forse funzionerà a fini di benchmark: ha preso il tuo 2. e iniettato alcune correlazioni nella matrice iniziale. La distribuzione è in qualche modo uniforme e cambiando puoi ottenere concentrazione vicino a 1 e -1 o vicino a 0.a

import numpy as np
from random import choice
import matplotlib.pyplot as plt

n = 100
a = 2

A = np.matrix([np.random.randn(n) + np.random.randn(1)*a for i in range(n)])
A = A*np.transpose(A)
D_half = np.diag(np.diag(A)**(-0.5))
C = D_half*A*D_half

vals = list(np.array(C.ravel())[0])
plt.hist(vals, range=(-1,1))
plt.show()
plt.imshow(C, interpolation=None)
plt.show()

La distribuzione in qualche modo uniforme I risultati di imshow


(+1) Grazie! Ho modificato la tua risposta per aggiungere lo schema di colorazione predefinito per Python e renderlo compatibile con Python2 :) Spero che vada bene. Ho anche cancellato i miei commenti sopra per rimuovere il disordine (puoi eliminare anche i tuoi). Ora sto cercando di capire la logica del tuo codice; hai davvero bisogno di crsarray? Che influenza ha ? La mia sensazione è che puoi semplicemente aggiungere un numero casuale da ad ogni riga, no? Ciò è simile all'utilizzo della matrice con campioni correlati (non caratteristiche) e quindi al calcolo della matrice di correlazione del campione, giusto? [ - a , a ] Xk[a,a]X
ameba dice di reintegrare Monica il

Sì, hai perfettamente ragione! (Oh ragazzo, era davvero sciocco: D). Ho cambiato la parte casuale in randn (1) * a e ora è molto meglio.
psarka,

Grazie! Ora devi solo rimuovere la tua menzione di sopra il codice. Nel frattempo, ho trovato una vecchia domanda che è quasi un duplicato e ho pubblicato una risposta lì, direttamente ispirata dalla tua qui: Come generare una matrice di correlazione casuale che ha approssimativamente distribuito voci fuori diagonale con una deviazione standard specifica? . Sembra funzionare bene! k
ameba dice di reintegrare Monica il

Freddo! Mi chiedo se tale procedura si traduca in una distribuzione nota. La sperimentazione di diversi e posso ottenere un bel paio di forme diverse. nan
psarka,

Uno svantaggio di questo metodo è che la matrice di correlazione risultante ha un grande autovalore, ma quelli rimanenti sono quasi uniformi. Quindi questa procedura non produce una matrice di correlazione "generale" ... Non che l'ho specificato nella mia domanda. Ma @ssdecontrol ha menzionato nei commenti sopra che apparentemente ci sono modi per campionare da tutte le matrici di correlazione; sembra interessante ma molto più complicato.
ameba dice di reintegrare Monica il

6

Hmm, dopo aver fatto un esempio nel mio linguaggio MatMate, vedo che esiste già una risposta Python, che potrebbe essere preferibile perché Python è ampiamente usato. Ma poiché avevi ancora delle domande, ti mostro il mio approccio usando il linguaggio Matmate-matrix, forse è più autocomprensivo.

Metodo 1
(utilizzando MatMate):

v=12         // 12 variables
f=3          // subset-correlation based on 3 common factors
vg = v / f   // variables per subsets

 // generate hidden factor-matrix
             // randomu(rows,cols ,lowbound, ubound) gives uniform random matrix 
             //    without explicite bounds the default is: randomu(rows,cols,0,100)
L = {   randomu(vg,f)     || randomu(vg,f)/100  || randomu(vg,f)/100 , _
        randomu(vg,f)/100 || randomu(vg,f)      || randomu(vg,f)/100 , _
        randomu(vg,f)/100 || randomu(vg,f)/100  || randomu(vg,f)     }

 // make sure there is itemspecific variance
 // by appending a diagonal-matrix with random positive entries
L = L || mkdiag(randomu(v,1,10,20)) 
  // make covariance and correlation matrix
cov = L *'   // L multiplied  with its transpose
cor = covtocorr(cov)
                   set ccdezweite=3 ccfeldweite=8
                   list cor
cor = 
   1.000,   0.321,   0.919,   0.489,   0.025,   0.019,   0.019,   0.030,   0.025,   0.017,   0.014,   0.014
   0.321,   1.000,   0.540,   0.923,   0.016,   0.015,   0.012,   0.030,   0.033,   0.016,   0.012,   0.015
   0.919,   0.540,   1.000,   0.679,   0.018,   0.014,   0.012,   0.029,   0.028,   0.014,   0.012,   0.012
   0.489,   0.923,   0.679,   1.000,   0.025,   0.022,   0.020,   0.040,   0.031,   0.014,   0.011,   0.014
   0.025,   0.016,   0.018,   0.025,   1.000,   0.815,   0.909,   0.758,   0.038,   0.012,   0.018,   0.014
   0.019,   0.015,   0.014,   0.022,   0.815,   1.000,   0.943,   0.884,   0.035,   0.012,   0.014,   0.012
   0.019,   0.012,   0.012,   0.020,   0.909,   0.943,   1.000,   0.831,   0.036,   0.013,   0.015,   0.010
   0.030,   0.030,   0.029,   0.040,   0.758,   0.884,   0.831,   1.000,   0.041,   0.017,   0.022,   0.020
   0.025,   0.033,   0.028,   0.031,   0.038,   0.035,   0.036,   0.041,   1.000,   0.831,   0.868,   0.780
   0.017,   0.016,   0.014,   0.014,   0.012,   0.012,   0.013,   0.017,   0.831,   1.000,   0.876,   0.848
   0.014,   0.012,   0.012,   0.011,   0.018,   0.014,   0.015,   0.022,   0.868,   0.876,   1.000,   0.904
   0.014,   0.015,   0.012,   0.014,   0.014,   0.012,   0.010,   0.020,   0.780,   0.848,   0.904,   1.000

Il problema qui potrebbe essere che definiamo blocchi di sottomatrici che hanno alte correlazioni all'interno con poca correlazione tra e questo non è programmaticamente ma dalle espressioni di concatenazione costanti. Forse questo approccio potrebbe essere modellato in modo più elegante in Python.


Metodo 2 (a)
Successivamente, esiste un approccio completamente diverso, in cui riempiamo l'eventuale covarianza rimanente di quantità casuali del 100 percento in una matrice di fattori di carico. Questo viene fatto in Pari / GP:

{L = matrix(8,8);  \\ generate an empty factor-loadings-matrix
for(r=1,8, 
   rv=1.0;    \\ remaining variance for variable is 1.0
   for(c=1,8,
        pv=if(c<8,random(100)/100.0,1.0); \\ define randomly part of remaining variance
        cv= pv * rv;  \\ compute current partial variance
        rv = rv - cv;     \\ compute the now remaining variance
        sg = (-1)^(random(100) % 2) ;  \\ also introduce randomly +- signs
        L[r,c] = sg*sqrt(cv) ;  \\ compute factor loading as signed sqrt of cv
       )
     );}

cor = L * L~

e la matrice di correlazione prodotta è

     1.000  -0.7111  -0.08648   -0.7806   0.8394  -0.7674   0.6812    0.2765
   -0.7111    1.000   0.06073    0.7485  -0.7550   0.8052  -0.8273   0.05863
  -0.08648  0.06073     1.000    0.5146  -0.1614   0.1459  -0.4760  -0.01800
   -0.7806   0.7485    0.5146     1.000  -0.8274   0.7644  -0.9373  -0.06388
    0.8394  -0.7550   -0.1614   -0.8274    1.000  -0.5823   0.8065   -0.1929
   -0.7674   0.8052    0.1459    0.7644  -0.5823    1.000  -0.7261   -0.4822
    0.6812  -0.8273   -0.4760   -0.9373   0.8065  -0.7261    1.000   -0.1526
    0.2765  0.05863  -0.01800  -0.06388  -0.1929  -0.4822  -0.1526     1.000

Forse questo genera una matrice di correlazione con i componenti principali dominanti a causa della regola di generazione cumulativa per la matrice di fattori di carico. Inoltre, potrebbe essere meglio assicurare la positività positiva rendendo l'ultima porzione della varianza un fattore unico. L'ho lasciato nel programma per mantenere l'attenzione sul principio generale.

Una matrice di correlazione 100x100 aveva le seguenti frequenze di correlazioni (arrotondate al 1 ° posto)

    e    f            e: entry(rounded) f: frequency
  -----------------------------------------------------
  -1.000, 108.000
  -0.900, 460.000
  -0.800, 582.000
  -0.700, 604.000
  -0.600, 548.000
  -0.500, 540.000
  -0.400, 506.000
  -0.300, 482.000
  -0.200, 488.000
  -0.100, 464.000
   0.000, 434.000
   0.100, 486.000
   0.200, 454.000
   0.300, 468.000
   0.400, 462.000
   0.500, 618.000
   0.600, 556.000
   0.700, 586.000
   0.800, 536.000
   0.900, 420.000
   1.000, 198.000

[aggiornare]. Hmm, la matrice 100x100 è mal condizionata; Pari / GP non è in grado di determinare correttamente gli autovalori con la funzione polroots (charpoly ()) anche con una precisione di 200 cifre. Ho fatto una rotazione Jacobi in forma pca sulla matrice loadings L e ho trovato autovalori per lo più estremamente piccoli, stampati in logaritmi alla base 10 (che danno all'incirca la posizione del punto decimale). Leggi da sinistra a destra e poi riga per riga:

log_10(eigenvalues):
   1.684,   1.444,   1.029,   0.818,   0.455,   0.241,   0.117,  -0.423,  -0.664,  -1.040
  -1.647,  -1.799,  -1.959,  -2.298,  -2.729,  -3.059,  -3.497,  -3.833,  -4.014,  -4.467
  -4.992,  -5.396,  -5.511,  -6.366,  -6.615,  -6.834,  -7.535,  -8.138,  -8.263,  -8.766
  -9.082,  -9.482,  -9.940, -10.167, -10.566, -11.110, -11.434, -11.788, -12.079, -12.722
 -13.122, -13.322, -13.444, -13.933, -14.390, -14.614, -15.070, -15.334, -15.904, -16.278
 -16.396, -16.708, -17.022, -17.746, -18.090, -18.358, -18.617, -18.903, -19.186, -19.476
 -19.661, -19.764, -20.342, -20.648, -20.805, -20.922, -21.394, -21.740, -21.991, -22.291
 -22.792, -23.184, -23.680, -24.100, -24.222, -24.631, -24.979, -25.161, -25.282, -26.211
 -27.181, -27.626, -27.861, -28.054, -28.266, -28.369, -29.074, -29.329, -29.539, -29.689
 -30.216, -30.784, -31.269, -31.760, -32.218, -32.446, -32.785, -33.003, -33.448, -34.318

[aggiornamento 2]
Metodo 2 (b)
Un miglioramento potrebbe essere quello di aumentare la varianza specifica degli elementi a un livello non marginale e ridurla a un numero ragionevolmente più piccolo di fattori comuni (ad esempio numero intero-quadrato del numero oggetto):

{  dimr = 100;
   dimc = sqrtint(dimr);        \\ 10 common factors
   L = matrix(dimr,dimr+dimc);  \\ loadings matrix 
                                \\     with dimr itemspecific and 
                                \\          dimc common factors
   for(r=1,dim, 
         vr=1.0;                \\ complete variance per item 
         vu=0.05+random(100)/1000.0;   \\ random variance +0.05
                                       \\ for itemspecific variance
         L[r,r]=sqrt(vu);              \\ itemspecific factor loading  
         vr=vr-vu;
         for(c=1,dimc,
                cv=if(c<dimc,random(100)/100,1.0)*vr;
                vr=vr-cv;
                L[r,dimr+c]=(-1)^(random(100) % 2)*sqrt(cv)
             )
        );}

   cov=L*L~
   cp=charpoly(cov)   \\ does not work even with 200 digits precision
   pr=polroots(cp)    \\ spurious negative and complex eigenvalues...

La struttura del risultato

in termini di distribuzione delle correlazioni:Immagine

rimane simile (anche la cattiva non decomposibilità di PariGP), ma gli autovalori, quando trovati dalla rotazione jacobi della matrice di caricamento, ora hanno una struttura migliore, per un esempio appena calcolato ho ottenuto gli autovalori come

log_10(eigenvalues):
   1.677,   1.326,   1.063,   0.754,   0.415,   0.116,  -0.262,  -0.516,  -0.587,  -0.783
  -0.835,  -0.844,  -0.851,  -0.854,  -0.858,  -0.862,  -0.862,  -0.868,  -0.872,  -0.873
  -0.878,  -0.882,  -0.884,  -0.890,  -0.895,  -0.896,  -0.896,  -0.898,  -0.902,  -0.904
  -0.904,  -0.909,  -0.911,  -0.914,  -0.920,  -0.923,  -0.925,  -0.927,  -0.931,  -0.935
  -0.939,  -0.939,  -0.943,  -0.948,  -0.951,  -0.955,  -0.956,  -0.960,  -0.967,  -0.969
  -0.973,  -0.981,  -0.986,  -0.989,  -0.997,  -1.003,  -1.005,  -1.011,  -1.014,  -1.019
  -1.022,  -1.024,  -1.031,  -1.038,  -1.040,  -1.048,  -1.051,  -1.061,  -1.064,  -1.068
  -1.070,  -1.074,  -1.092,  -1.092,  -1.108,  -1.113,  -1.120,  -1.134,  -1.139,  -1.147
  -1.150,  -1.155,  -1.158,  -1.166,  -1.171,  -1.175,  -1.184,  -1.184,  -1.192,  -1.196
  -1.200,  -1.220,  -1.237,  -1.245,  -1.252,  -1.262,  -1.269,  -1.282,  -1.287,  -1.290

Molte grazie! Molto interessante, ma mi ci vorrà un po 'di tempo per digerire ...
Ameba dice Reinstate Monica il

Devo ancora esaminare attentamente la tua risposta, ma nel frattempo ho letto un articolo sul campionamento di matrici di correlazione casuali e uno dei metodi da lì può essere usato per fare esattamente ciò di cui ho bisogno. Ho pubblicato una risposta qui, potresti essere interessato a dare un'occhiata! Si collega a una risposta molto più dettagliata che ho scritto in un altro thread.
ameba dice Ripristina Monica il

@amoeba: felice di aver trovato qualcosa che funziona bene per te! È una domanda interessante, tornerò più avanti su questo argomento, forse migliorerò / adatterò le procedure MatMate (e le trasformeremo in subroutine) in base al documento su cui hai lavorato.
Gottfried Helms

2

Domanda interessante (come sempre!). Come di trovare una serie di esempi di matrici che presentano le proprietà che desideri, e poi prendere convesso loro combinazioni, dal momento che se e sono definite positive, allora lo è . Come bonus, non sarà necessario il ridimensionamento delle diagonali, per la convessità dell'operazione. Regolando in modo che sia più concentrato su 0 e 1 rispetto a una distribuzione uniforme, è possibile concentrare i campioni sui bordi del politopo, o sull'interno. (È possibile utilizzare una distribuzione beta / Dirichlet per controllare la concentrazione rispetto all'uniformità).B λ A + ( 1 - λ ) B λABλA+(1λ)Bλ

Ad esempio, potresti lasciare che sia simmetrico ai componenti e sia toeplitz. Naturalmente, puoi sempre aggiungere un'altra classe e prendere tale che e e così via.B C λ A A + λ B B + λ C C λ = 1 λ 0ABCλAA+λBB+λCCλ=1λ0


AB

Ah, ma da un tale algoritmo e un'adeguata diversità nei "vertici" (ovvero matrici) che definiscono il tuo politopo di matrici di correlazione definite positive, puoi utilizzare il campionamento del rifiuto per ottenere qualsiasi distribuzione di autovalori, uniformità delle voci, ecc. che desideri. Tuttavia, non mi è chiaro quale sarebbe una buona base. Sembra una domanda per qualcuno che ha studiato l'algebra astratta più recentemente di me.
Andrew M

Ciao di nuovo, ho letto un articolo sul campionamento di matrici di correlazione casuali e uno dei metodi da lì può essere usato per fare esattamente ciò di cui ho bisogno. Ho pubblicato una risposta qui, potresti essere interessato a dare un'occhiata! Si collega a una risposta molto più dettagliata che ho scritto in un altro thread.
ameba dice Ripristina Monica il

2

R ha un pacchetto (clusterGeneration) che implementa il metodo in:

Esempio:

> (cormat10 = clusterGeneration::rcorrmatrix(10, alphad = 1/100000000000000))
        [,1]   [,2]    [,3]     [,4]     [,5]   [,6]   [,7]    [,8]     [,9]   [,10]
 [1,]  1.000  0.344 -0.1406 -0.65786 -0.19411  0.246  0.688 -0.6146  0.36971 -0.1052
 [2,]  0.344  1.000 -0.4256 -0.35512  0.15973  0.192  0.340 -0.4907 -0.30539 -0.6104
 [3,] -0.141 -0.426  1.0000  0.01775 -0.61507 -0.485 -0.273  0.3492 -0.30284  0.1647
 [4,] -0.658 -0.355  0.0178  1.00000  0.00528 -0.335 -0.124  0.5256 -0.00583 -0.0737
 [5,] -0.194  0.160 -0.6151  0.00528  1.00000  0.273 -0.350 -0.0785  0.08285  0.0985
 [6,]  0.246  0.192 -0.4847 -0.33531  0.27342  1.000  0.278 -0.2220 -0.11010  0.0720
 [7,]  0.688  0.340 -0.2734 -0.12363 -0.34972  0.278  1.000 -0.6409  0.40314 -0.2800
 [8,] -0.615 -0.491  0.3492  0.52557 -0.07852 -0.222 -0.641  1.0000 -0.50796  0.1461
 [9,]  0.370 -0.305 -0.3028 -0.00583  0.08285 -0.110  0.403 -0.5080  1.00000  0.3219
[10,] -0.105 -0.610  0.1647 -0.07373  0.09847  0.072 -0.280  0.1461  0.32185  1.0000
> cormat10[lower.tri(cormat10)] %>% psych::describe()
   vars  n  mean   sd median trimmed mad   min  max range skew kurtosis   se
X1    1 45 -0.07 0.35  -0.08   -0.07 0.4 -0.66 0.69  1.35 0.03       -1 0.05

Sfortunatamente, non sembra possibile simulare correlazioni che seguono una distribuzione uniforme con questo. Sembra che crei correlazioni più forti quando alphadè impostato su valori molto piccoli, ma anche a 1/100000000000000, l'intervallo di correlazioni salirà solo a circa 1,40.

Tuttavia, spero che questo possa essere di qualche utilità per qualcuno.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.