Документ , що генерує випадкові кореляційні матриці на основі лоз та методу розширеного лука, зроблені Левандовським, Куровіккою та Джо (LKJ), 2009, забезпечує уніфіковану обробку та експозицію двох ефективних методів генерації випадкових кореляційних матриць. Обидва способи дозволяють генерувати матриці з рівномірного розподілу в певному точному значенні, визначеному нижче, прості у здійсненні, швидкі та мають додаткову перевагу від забавних імен.
Справжня симетрична матриця розміром з діагоналлю має d ( d - 1 ) / 2 унікальних позадіагональних елементів і тому може бути параметризована як точка в R d ( d - 1 ) / 2 . Кожна точка в цьому просторі відповідає симетричній матриці, але не всі вони є позитивно визначеними (як мають бути кореляційні матриці). Отже, кореляційні матриці утворюють підмножину R d ( d - 1 ) / 2г× дг( д- 1 ) / 2Rг( д- 1 ) / 2Rг( д- 1 ) / 2 (фактично підключений опуклий підмножина), і обидва способи можуть генерувати точки з рівномірного розподілу по цій підмножині.
Я забезпечу власну реалізацію кожного методу MATLAB і проілюструю їх .г= 100
Цибульний метод
Метод цибулі походить з іншого паперу (посилання №3 в LKJ) і належить його назві тому, що генеруються кореляційні матриці, починаючи з матриці і збільшуючи її стовпцем за стовпцем та рядком за рядком. Результат розподілу рівномірний. Я не дуже розумію математику за методом (і все одно віддаю перевагу другому методу), але ось результат:1 × 1
Тут і нижче в заголовку кожного субплота відображаються найменші та найбільші власні значення, а також визначальний (добуток усіх власних значень). Ось код:
%// 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
Розширений метод цибулі
LKJ трохи модифікують цей метод, щоб мати можливість вибірки кореляційних матриць з розподілу, пропорційного [ d e tС . Чим більший η , тим більшим буде визначник, тобто генеровані кореляційні матриці все більше і більше наближаються до матриці ідентичності. Значення η = 1 відповідає рівномірному розподілу. На малюнку нижче матриці формуються з η = 1 , 10 , 100 , 1000 , 10[ д е тC ]η- 1ηη= 1 .η= 1 , 10 , 100 , 1000 , 10000 , 100000
Чомусь для отримання визначника того ж порядку величини, що і у методі цибулі ванілі, мені потрібно поставити а не η = 1 (як стверджує LKJ). Не впевнений, де помилка.η= 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
Виноградний метод
Спочатку метод лози був запропонований Джо (J в LKJ) і вдосконалений LKJ. Мені це подобається більше, тому що це концептуально простіше, а також простіше змінювати. Ідея полягає у створенні часткових кореляцій (вони незалежні і можуть мати будь-які значення з [ - 1 , 1 ]г( д- 1 ) / 2[ - 1 , 1 ]без будь-яких обмежень), а потім перетворити їх у необроблені кореляції за допомогою рекурсивної формули. Зручно організувати обчислення в певному порядку, і цей графік відомий як "лоза". Важливо, якщо часткові кореляції відібрані з конкретних бета-розподілів (різних для різних клітин у матриці), то отримана матриця розподілиться рівномірно. Тут знову ж таки LKJ вводить додатковий параметр для вибірки з розподілу, пропорційного [ d e tη . Результат ідентичний розширеній цибулі:[ д е тC ]η- 1
%// 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
Виноградний метод з ручним відбором часткових кореляцій
± 1[ 0 , 1 ][ - 1 , 1 ]α = β= 50 , 20 , 10 , 5 , 2 , 1. Чим менші параметри бета-розподілу, тим більше він сконцентрований біля країв.
Зауважте, що в цьому випадку розподіл не гарантується, що перестановка буде інваріантною, тому я додатково випадково перестановлюю рядки та стовпці після генерації.
%// 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
Ось як шукають гістограми позадіагональних елементів для матриць вище (дисперсія розподілу монотонно зростає):
Оновлення: використання випадкових факторів
k < dWk × dШ Ш⊤DB = W W⊤+ DC = E- 1 / 2Б Е- 1 / 2ЕБk = 100 , 50 , 20 , 10 , 5 , 1
І код:
%// 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
Ось обгортковий код, який використовується для створення фігур:
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