Artykuł Generowanie losowych macierzy korelacji na podstawie metody winorośli i rozszerzonej cebuli autorstwa Lewandowskiego, Kurowickiej i Joe (LKJ), 2009, zapewnia ujednolicone traktowanie i opis dwóch skutecznych metod generowania macierzy losowej korelacji. Obie metody pozwalają na generowanie macierzy z jednolitego rozkładu w ściśle określonym sensie zdefiniowanym poniżej, są łatwe do wdrożenia, szybkie i mają dodatkową zaletę polegającą na zabawnych nazwach.
Prawdziwa macierz symetryczna o rozmiarze z elementami na przekątnej ma unikalne elementy poza przekątną, więc można ją sparametryzować jako punkt w . Każdy punkt w tej przestrzeni odpowiada macierzy symetrycznej, ale nie wszystkie z nich są dodatnio określone (ponieważ muszą to być macierze korelacji). Macierze korelacji tworzą zatem podzbiór (właściwie połączony wypukły podzbiór), i obie metody mogą generować punkty z jednolitego rozkładu w tym podzbiorze.d×dd(d−1)/2Rd(d−1)/2Rd(d−1)/2
Przedstawię własną implementację MATLAB dla każdej metody i zilustruję je .d=100
Metoda cebuli
Metoda cebulowa pochodzi z innego artykułu (nr 3 w LKJ) i zawdzięcza swoją nazwę faktowi, że macierze korelacji są generowane zaczynając od macierzy i rosnąc ją kolumna po kolumnie i rząd po rzędzie. Wynikowy rozkład jest jednolity. Naprawdę nie rozumiem matematyki za tą metodą (i tak wolę drugą metodę), ale oto wynik:1×1
Tu i poniżej tytuł każdej podploty pokazuje najmniejsze i największe wartości własne oraz wyznacznik (iloczyn wszystkich wartości własnych). Oto kod:
%// ONION METHOD to generate random correlation matrices distributed randomly
function S = onion(d)
S = 1;
for k = 2:d
y = betarnd((k-1)/2, (d-k)/2); %// sampling from beta distribution
r = sqrt(y);
theta = randn(k-1,1);
theta = theta/norm(theta);
w = r*theta;
[U,E] = eig(S);
R = U*E.^(1/2)*U'; %// R is a square root of S
q = R*w;
S = [S q; q' 1]; %// increasing the matrix size
end
end
Metoda rozszerzonej cebuli
LKJ nieznacznie zmodyfikuje tę metodę, aby móc próbkować macierze korelacji z rozkładu proporcjonalnego do . Im większa , tym większa będzie wyznacznik, co oznacza, że generowane macierze korelacji będą coraz bardziej zbliżały się do matrycy tożsamości. Wartość odpowiada rozkładowi jednorodnemu. Na poniższym rysunku macierze są generowane z .C[detC]η−1ηη=1η=1,10,100,1000,10000,100000
Z jakiegoś powodu, aby uzyskać wyznacznik tego samego rzędu wielkości co w metodzie z wanilią, muszę a nie (jak twierdzi LKJ). Nie jestem pewien, gdzie jest błąd.η=0η=1
%// EXTENDED ONION METHOD to generate random correlation matrices
%// distributed ~ det(S)^eta [or maybe det(S)^(eta-1), not sure]
function S = extendedOnion(d, eta)
beta = eta + (d-2)/2;
u = betarnd(beta, beta);
r12 = 2*u - 1;
S = [1 r12; r12 1];
for k = 3:d
beta = beta - 1/2;
y = betarnd((k-1)/2, beta);
r = sqrt(y);
theta = randn(k-1,1);
theta = theta/norm(theta);
w = r*theta;
[U,E] = eig(S);
R = U*E.^(1/2)*U';
q = R*w;
S = [S q; q' 1];
end
end
Metoda winorośli
Metoda Vine została pierwotnie zasugerowana przez Joe (J w LKJ) i ulepszona przez LKJ. Bardziej mi się podoba, ponieważ jest koncepcyjnie łatwiejszy, a także łatwiejszy do modyfikacji. Chodzi o to, aby wygenerować częściowe korelacje (są one niezależne i mogą mieć dowolne wartości z bez żadnych ograniczeń), a następnie przekształcić je w surowe korelacje za pomocą wzoru rekurencyjnego. Wygodnie jest zorganizować obliczenia w określonej kolejności, a ten wykres jest znany jako „winorośl”. Co ważne, jeśli próbkuje się korelacje częściowe z poszczególnych rozkładów beta (różnych dla różnych komórek w macierzy), wówczas uzyskana macierz będzie rozkładana równomiernie. Tutaj ponownie LKJ wprowadza dodatkowy parametr aby pobrać próbkę z rozkładu proporcjonalnego dod(d−1)/2[−1,1]η[detC]η−1 . Wynik jest identyczny z rozszerzoną cebulą:
%// VINE METHOD to generate random correlation matrices
%// distributed ~ det(S)^eta [or maybe det(S)^(eta-1), not sure]
function S = vine(d, eta)
beta = eta + (d-1)/2;
P = zeros(d); %// storing partial correlations
S = eye(d);
for k = 1:d-1
beta = beta - 1/2;
for i = k+1:d
P(k,i) = betarnd(beta,beta); %// 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
end
Metoda winorośli z ręcznym próbkowaniem korelacji cząstkowych
Jak widać powyżej, równomierny rozkład daje prawie diagonalne macierze korelacji. Ale można łatwo zmodyfikować metodę winorośli, aby uzyskać silniejsze korelacje (nie jest to opisane w pracy LKJ, ale jest proste): w tym celu należy próbkować korelacje częściowe z rozkładu skoncentrowanego wokół . Poniżej próbuję je z rozkładu beta (przeskalowanego z na ) za pomocą . Im mniejsze parametry rozkładu beta, tym bardziej jest ono skoncentrowane w pobliżu krawędzi.±1[0,1][−1,1]α=β=50,20,10,5,2,1
Zauważ, że w tym przypadku nie ma gwarancji, że rozkład będzie niezmienny w permutacji, więc dodatkowo generuję losowo wiersze i kolumny po wygenerowaniu.
%// VINE METHOD to generate random correlation matrices
%// with all partial correlations distributed ~ beta(betaparam,betaparam)
%// rescaled to [-1, 1]
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
Oto, jak histogramy elementów nie przekątnych wyglądają dla powyższych matryc (wariancja rozkładu monotonicznie wzrasta):
Aktualizacja: przy użyciu losowych czynników
Jedna bardzo prosta metoda generowania macierzy losowych korelacji z pewnymi silnymi korelacjami została zastosowana w odpowiedzi przez @shabbychef i chciałbym to również zilustrować tutaj. Chodzi o to, aby losowo wygenerować kilka ( ) ładunków czynnikowych (losowa macierz wielkości), utworzyć macierz kowariancji (który oczywiście nie będzie pełnej rangi ) i dodaj do niej losową macierz ukośną z dodatnimi elementami, aby pełna ranga. Otrzymaną macierz kowariancji można znormalizować, aby stała się macierzą korelacji, pozwalającW k x d W W ⊤ D B = W W ⊤ + D C = E - 1 / 2 B E - 1 / 2 PL B K = 100 , 50 , 20 , 10 , 5 , 1k<dWk×dWW⊤DB=WW⊤+DC=E−1/2BE−1/2Gdzie jest macierzą diagonalną o tej samej przekątnej, co . To jest bardzo proste i załatwia sprawę. Oto kilka przykładowych macierzy korelacji dla :EBk=100,50,20,10,5,1
I kod:
%// FACTOR method
function S = factor(d,k)
W = randn(d,k);
S = W*W' + diag(rand(1,d));
S = diag(1./sqrt(diag(S))) * S * diag(1./sqrt(diag(S)));
end
Oto kod opakowania używany do generowania liczb:
d = 100; %// size of the correlation matrix
figure('Position', [100 100 1100 600])
for repetition = 1:6
S = onion(d);
%// etas = [1 10 100 1000 1e+4 1e+5];
%// S = extendedOnion(d, etas(repetition));
%// S = vine(d, etas(repetition));
%// betaparams = [50 20 10 5 2 1];
%// S = vineBeta(d, betaparams(repetition));
subplot(2,3,repetition)
%// use this to plot colormaps of S
imagesc(S, [-1 1])
axis square
title(['Eigs: ' num2str(min(eig(S)),2) '...' num2str(max(eig(S)),2) ', det=' num2str(det(S),2)])
%// use this to plot histograms of the off-diagonal elements
%// offd = S(logical(ones(size(S))-eye(size(S))));
%// hist(offd)
%// xlim([-1 1])
end