В статье « Генерация матриц случайной корреляции на основе лоз и расширенного метода лука», выполненной Левандовски, Куровицкой и Джо (LKJ), 2009 г., представлены единый подход и описание двух эффективных методов генерации матриц случайной корреляции. Оба метода позволяют генерировать матрицы из равномерного распределения в определенном точном смысле, определенном ниже, просты в реализации, быстры и имеют дополнительное преимущество, заключающееся в забавных именах.
Вещественная симметричная матрица размера с единицами на диагонали имеет уникальных недиагональных элемента и поэтому может быть параметризована как точка в . Каждая точка в этом пространстве соответствует симметричной матрице, но не все они являются положительно определенными (как это должно быть для корреляционных матриц). Поэтому корреляционные матрицы образуют подмножество (фактически связное выпуклое подмножество), и оба метода могут генерировать точки из равномерного распределения по этому подмножеству.d ( d - 1 ) / 2 R d ( d - 1 ) / 2 R d ( d - 1 ) / 2d× дd( д- 1 ) / 2рd( д- 1 ) / 2рd( д- 1 ) / 2
Я предоставлю свою собственную реализацию MATLAB каждого метода и проиллюстрирую их с .d= 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 немного изменил этот метод, чтобы иметь возможность выбирать корреляционные матрицы из распределения, пропорционального . Чем больше значение , тем больше будет определитель, означающий, что сгенерированные корреляционные матрицы будут все больше приближаться к единичной матрице. Значение соответствует равномерному распределению. На рисунке ниже матрицы генерируются с . [ д е тС η η = 1 η = 1 , 10 , 100 , 1000 , 10[ Д е тC ]η- 1ηη= 1η= 1 , 10 , 100 , 1000 , 10000 , 100000
По какой-то причине, чтобы получить определитель того же порядка, что и в методе с ванильным луком, мне нужно поставить а не (как утверждает LKJ). Не уверен, где ошибка.η = 1η= 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. Мне это нравится больше, потому что это концептуально проще, а также легче модифицировать. Идея состоит в том, чтобы сгенерировать частичных корреляции (они независимы и могут иметь любые значения из без каких-либо ограничений), а затем преобразовать их в необработанные корреляции с помощью рекурсивной формулы. Удобно организовать вычисления в определенном порядке, и этот график известен как «лоза». Важно отметить, что если частичные корреляции выбираются из конкретных бета-распределений (различающихся для разных ячеек в матрице), то полученная матрица будет распределена равномерно. Здесь снова LKJ вводит дополнительный параметр для выборки из распределения, пропорционального[ - 1 , 1 ] η [ d e td( д- 1 ) / 2[ - 1 , 1 ]η[ Д е т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
Винный метод с ручной выборкой частичных корреляций
Как видно выше, равномерное распределение приводит к почти диагональным корреляционным матрицам. Но можно легко изменить метод виноградной лозы, чтобы иметь более сильные корреляции (это не описано в статье LKJ, но просто): для этого следует выбрать частичные корреляции из распределения, сосредоточенного около . Ниже я приведу выборку их из бета-распределения (масштабируется с до ) с помощью . Чем меньше параметры бета-распределения, тем больше оно сосредоточено вблизи краев.[ 0 , 1 ] [ - 1 , 1 ] α = β = 50 , 20 , 10 , 5 , 2 , 1± 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
Вот как выглядят гистограммы недиагональных элементов для вышеприведенных матриц (дисперсия распределения монотонно увеличивается):
Обновление: с использованием случайных факторов
к < дWk × dW W⊤DС = Е - 1 / 2 Б Е - 1 / 2 Е В к = 100 , 50 , 20 , 10 , 5 , 1B = W W⊤+ DC = E- 1 / 2B E- 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