如何生成具有一些強相關性的大型全秩隨機相關矩陣?
我想生成一個隨機相關矩陣的大小使得存在一些中等強度的相關性:
- 平方實對稱矩陣大小,例如;
- 正定的,即所有特徵值都是實數和正數;
- 滿級;
- 所有對角線元素等於;
- 非對角元素應合理均勻分佈在. 確切的分佈無關緊要,但我想有一些適度大的數量(例如)的中等大值(例如,絕對值或更高)。基本上我想確保與所有非對角元素幾乎不成對角線.
有沒有簡單的方法來做到這一點?
目的是使用這樣的隨機矩陣來對一些使用相關(或協方差)矩陣的算法進行基準測試。
無效的方法
以下是一些我知道的生成隨機相關矩陣的方法,但在這裡對我不起作用:
- 生成隨機的大小,中心,標準化並形成相關矩陣. 如果,這通常會導致所有非對角相關. 如果,一些相關性會很強,但是不會滿級。
- 生成隨機正定矩陣通過以下方式之一:
- 生成隨機正方形並使對稱正定.
- 生成隨機正方形, 對稱, 並通過特徵分解使其為正定並將所有負特徵值設置為零:. 注意:這將導致秩虧矩陣。
- 生成隨機正交(例如通過生成隨機正方形並進行其 QR 分解,或通過 Gram-Schmidt 過程)和隨機對角線帶有所有積極的元素;形式.得到的矩陣可以很容易地歸一化以使所有的都在對角線上:, 在哪裡是與對角線相同的對角矩陣. 上面列出的所有三種生成方式造成非對角線元素關閉.
更新:舊線程
發布我的問題後,我在過去發現了兩個幾乎重複的內容:
不幸的是,這些線程中沒有一個包含令人滿意的答案(直到現在:)
其他答案想出了以各種方式解決我的問題的好技巧。然而,我發現了一種原則性的方法,我認為它的一大優勢是概念上非常清晰且易於調整。
在這個線程中:如何有效地生成隨機正半定相關矩陣?– 我描述並提供了用於生成隨機相關矩陣的兩種有效算法的代碼。兩者都來自Lewandowski、Kurowicka 和 Joe (2009) 的論文,@ssdecontrol 在上面的評論中提到(非常感謝!)。
請在此處查看我的答案以獲取大量數字、解釋和 matlab 代碼。所謂的“藤蔓”方法允許生成具有任何偏相關分佈的隨機相關矩陣,並可用於生成具有大非對角線值的相關矩陣。這是該線程的示例圖:
子圖之間唯一變化的是一個參數,它控制偏相關分佈集中在.
我也複製了我的代碼以在此處生成這些矩陣,以表明它不比此處建議的其他方法長。請參閱我的鏈接答案以獲得一些解釋。
betaparam
上圖的值為(並且維度d
是)。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
更新:特徵值
@psarka 詢問這些矩陣的特徵值。在下圖中,我繪製了與上述相同的六個相關矩陣的特徵值譜。請注意,它們逐漸減少;相比之下,@psarka 建議的方法通常會產生一個具有一個大特徵值的相關矩陣,但其餘部分非常一致。
更新。真正簡單的方法:幾個因素
類似於@ttnphns 在上面的評論中寫的和@GottfriedHelms 在他的回答中寫的,實現我的目標的一種非常簡單的方法是隨機生成幾個 () 因子載荷(隨機矩陣大小),形成協方差矩陣(當然不會是滿秩)並添加一個隨機對角矩陣有積極的元素滿級。可以將得到的協方差矩陣歸一化為相關矩陣(如我的問題中所述)。這非常簡單,並且可以解決問題。以下是一些示例相關矩陣:
唯一的缺點是生成的矩陣將具有大的特徵值,然後突然下降,與上面使用 vine 方法顯示的良好衰減相反。以下是對應的光譜:
這是代碼:
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)));