Primero proporcioné lo que ahora creo que es una respuesta subóptima; Por lo tanto, edité mi respuesta para comenzar con una mejor sugerencia.
Usando el método de la vid
En este hilo: ¿Cómo generar eficientemente matrices aleatorias de correlación semidefinida positiva? - Describí y proporcioné el código para dos algoritmos eficientes de generación de matrices de correlación aleatorias. Ambos provienen de un artículo de Lewandowski, Kurowicka y Joe (2009).
Vea mi respuesta allí para ver muchas figuras y códigos de matlab. Aquí solo me gustaría decir que el método vine permite generar matrices de correlación aleatorias con cualquier distribución de correlaciones parciales (observe la palabra "parcial") y puede usarse para generar matrices de correlación con grandes valores fuera de la diagonal. Aquí está la figura relevante de ese hilo:
±1
Creo que estas distribuciones son razonablemente "normales", y uno puede ver cómo aumenta gradualmente la desviación estándar. Debo agregar que el algoritmo es muy rápido. Ver hilo vinculado para los detalles.
Mi respuesta original
Una modificación directa de su método podría hacer el truco (dependiendo de qué tan cerca desea que la distribución sea normal). Esta respuesta se inspiró en los comentarios de @ cardinal anteriores y en la respuesta de @ psarka a mi propia pregunta ¿Cómo generar una matriz de correlación aleatoria grande de rango completo con algunas correlaciones fuertes presentes?
XX1000×100[−a/2,a/2]a=0,1,2,5a=0X⊤X1/1000−−−−√a>0aa=0,1,2,5
Todas estas matrices son, por supuesto, definitivas positivas. Aquí está el código matlab:
offsets = [0 1 2 5];
n = 1000;
p = 100;
rng(42) %// random seed
figure
for offset = 1:length(offsets)
X = randn(n,p);
for i=1:p
X(:,i) = X(:,i) + (rand-0.5) * offsets(offset);
end
C = 1/(n-1)*transpose(X)*X; %// covariance matrix (non-centred!)
%// convert to correlation
d = diag(C);
C = diag(1./sqrt(d))*C*diag(1./sqrt(d));
%// displaying C
subplot(length(offsets),3,(offset-1)*3+1)
imagesc(C, [-1 1])
%// histogram of the off-diagonal elements
subplot(length(offsets),3,(offset-1)*3+2)
offd = C(logical(ones(size(C))-eye(size(C))));
hist(offd)
xlim([-1 1])
%// QQ-plot to check the normality
subplot(length(offsets),3,(offset-1)*3+3)
qqplot(offd)
%// eigenvalues
eigv = eig(C);
display([num2str(min(eigv),2) ' ... ' num2str(max(eigv),2)])
end
La salida de este código (valores propios mínimos y máximos) es:
0.51 ... 1.7
0.44 ... 8.6
0.32 ... 22
0.1 ... 48