非正定共分散行列を使用して正規分布乱数を生成します


15

サンプルのサンプル共分散行列を推定し、対称行列を取得しました。では、私が作成したい変量通常の分散RNをしかしそれゆえ、私はのコレスキー分解必要な。が正定でない場合はどうすればよいですか?CCnCC


1
この質問との違いは何ですかstackoverflow.com/questions/17295627/...は
-dickoa

1
正の半無限行列には複数の平方根があります(たとえば、stats.stackexchange.com / a / 71303/919の最後の説明を参照)。コレスキー分解によって生成されたものは必ずしも必要ではありません。ここに問題の核心があります。行列が特異な場合でも機能する平方根を計算する方法を見つけてください。@amoebaタイトルは、あなたの解釈が正しいことを示唆しています。
whuber

回答:


8

問題は、(おそらく)特異共分散行列持つ多変量正規分布からランダム変量を生成する方法に関するものです。この回答は共分散行列に対して機能する1つの方法を説明しています。精度をテストする実装を提供します。CR


共分散行列の代数分析

ので共分散行列であり、必ずしも対称と正半正定値です。背景情報を完成させるために、を目的の平均のベクトルにします。Cμ

ので対称で、その特異値分解(SVD)およびその固有値分解は、自動的にフォームを有することになりますC

C=VD2V

いくつかの直交行列と対角行列D 2に対して。一般に、D 2の対角要素は非負です(それらはすべて実数平方根を持っていることを意味します:対角行列Dを形成するために正のものを選択してください)。Cについての情報は、これらの対角要素の1つ以上がゼロであると述べていますが、それは後続の操作に影響を与えず、SVDの計算を妨げません。VD2D2DC

多変量ランダム値の生成

レッツ各コンポーネントはゼロ平均、単位分散を持っており、すべての共分散はゼロです::標準の多変量正規分布を持つその共分散行列がアイデンティティであるI。次に、ランダム変数Y = V D Xは共分散行列を持ちますXIY=VDX

Cov(Y)=E(YY)=E(VDXXDV)=VDE(XX)DV=VDIDV=VD2V=C.

その結果、ランダム変数は、平均μと共分散行列Cをもつ多変量正規分布になります。μ+YμC

計算とサンプルコード

次のRコードは、指定された次元とランクの共分散行列を生成し、SVD(またはコメントアウトされたコードで固有分解)で分析し、その分析を使用して指定された数の実現を生成します(平均ベクトル0) 、そしてそれらのデータの共分散行列を、数値的およびグラフィカルに目的の共分散行列と比較します。示されるように、それが生成し10 000の寸法実現Yがである100とのランクCがある50。出力はY010,000Y100C50

        rank           L2 
5.000000e+01 8.846689e-05 

つまり、データのランクもあり、データから推定される共分散行列は、Cの8 × 10 5の距離内にあり、これは近いです。より詳細なチェックとして、Cの係数がその推定の係数に対してプロットされます。それらはすべて、平等線の近くにあります。508×105CC

図

コードは前述の分析とまったく同じであるため、一目瞭然Rです(お気に入りのアプリケーション環境でエミュレートする可能性のある非ユーザーでも)。浮動小数点アルゴリズムを使用する場合、それは明らかに一つのことは、注意が必要なことである:のエントリ容易に不正確に起因する負の(しかし小さい)とすることができます。そのようなエントリは、D自体を見つけるために平方根を計算する前にゼロにする必要があります。D2D

n <- 100         # Dimension
rank <- 50
n.values <- 1e4  # Number of random vectors to generate
set.seed(17)
#
# Create an indefinite covariance matrix.
#
r <- min(rank, n)+1
X <- matrix(rnorm(r*n), r)
C <- cov(X)
#
# Analyze C preparatory to generating random values.
# `zapsmall` removes zeros that, due to floating point imprecision, might
# have been rendered as tiny negative values.
#
s <- svd(C)
V <- s$v
D <- sqrt(zapsmall(diag(s$d)))
# s <- eigen(C)
# V <- s$vectors
# D <- sqrt(zapsmall(diag(s$values)))
#
# Generate random values.
#
X <- (V %*% D) %*% matrix(rnorm(n*n.values), n)
#
# Verify their covariance has the desired rank and is close to `C`.
#
s <- svd(Sigma <- cov(t(X)))
(c(rank=sum(zapsmall(s$d) > 0), L2=sqrt(mean(Sigma - C)^2)))

plot(as.vector(C), as.vector(Sigma), col="#00000040",
     xlab="Intended Covariances",
     ylab="Estimated Covariances")
abline(c(0,1), col="Gray")

2
+1ですが、最初の文で「不定」と言うとき、正確にはどういう意味ですか?ウィキペディアで調べところ、正の半正定は不定ではない、つまり、不定はCが正と負の固有値を持っていることを意味します。それはあなたがそこに意味するものですか?
アメーバは、モニカーを復活させる

2
@amoebaはい、それはスリップでした。気づいてくれてありがとう。「不定」とは、マトリックスの署名に正と負の両方の符号があることを意味し、「半定」とは、署名に符号が1つしかないことを意味します。
whuber

6

解決方法A

  1. Cが対称でない場合は、対称化します。D < 0.5(C+CT)
  2. 必要なマージンmで正定にするのに十分な対称行列Cに倍数の単位行列を追加します。つまり、新しい行列の最小固有値が最小固有値= mになるようにします。具体的には、D < 、ここでIは単位行列です。Dには、目的の正定共分散行列が含まれます。D+(mmin(eigenvalue(D)))I

MATLABでは、コードは次のようになります。

D = 0.5 * (C + C');
D =  D + (m - min(eig(CD)) * eye(size(D));

解法B:凸SDP(半正定値計画)を定式化して解き、その差のフロベニウスノルムに従って、Dが正定で、最小固有値mを指定して、最も近い行列Dを見つける。

MATLABでCVXを使用すると、コードは次のようになります。

n = size(C,1);
cvx_begin
variable D(n,n)
minimize(norm(D-C,'fro'))
D -m *eye(n) == semidefinite(n)
cvx_end

解法の比較:解法Aは、初期行列の対称化とは別に、対角要素のみを一般的な量だけ調整(増加)し、非対角要素は変更しません。解法Bは、正定行列Dと元の行列Cの差の最小フロベニウスノルムの意味で、指定された最小固有値を持つ(元の行列に)最も近い正定行列を見つけます。 D-Cのすべての要素の平方差。非対角要素を含む。そのため、非対角要素を調整することにより、対角要素を増やす必要がある量を減らすことができ、対角要素を必ずしもすべて同じ量だけ増やす必要はありません。


2

あなたが推定しているモデルについて考えることから始めます。

共分散行列が正の半正定値ではない場合、変数に共線形性の問題があることを示している可能性があります。これは、モデルの問題を示しており、必ずしも数値的手法で解決する必要はありません。

数値的な理由で行列が半正定でない場合、ここで読むことができるいくつかの解決策があります


1
仮定は、モデルが線形混合モデルであることです。この場合、データの正しいモデルを見つけることは関係ありませんが、データは計算の例として示されています。現在、covarainceの推定として非正の半正定行列を取得する可能性があります。そこで、データがどこから来た正規分布母集団から共分散を把握したい場合、そこから何をすべきか。サンプルが正規分布していることは仮定です。
クラウス

1

1つの方法は、固有値分解から行列を計算することです。今、これらのプロセスの背後にある数学についてあまり知らないことを認めますが、私の研究から、このヘルプファイルを見るのは実りあるようです:

http://stat.ethz.ch/R-manual/R-patched/library/Matrix/html/chol.html

およびRの他の関連コマンド

また、Matrixパッケージの「nearPD」も確認してください。

申し訳ありませんが、これ以上のお手伝いはできませんでしたが、周りを検索することで正しい方向に進むことができれば幸いです。


こんにちは、リンクのthx。固有値分解に関係なく、この分解は助けになりません。なぜなら、そこから平方根行列の複雑な固有値を取得できるからです。
クラウス

1

RのMatrixパッケージのnearPD関数から結果を取得できます。これにより、実際の値のマトリックスが返されます。

library(Matrix)
A <- matrix(1, 3,3); A[1,3] <- A[3,1] <- 0
n.A <- nearPD(A, corr=T, do2eigen=FALSE)
n.A$mat

# 3 x 3 Matrix of class "dpoMatrix"
#           [,1]      [,2]      [,3]
# [1,] 1.0000000 0.7606899 0.1572981
# [2,] 0.7606899 1.0000000 0.7606899
# [3,] 0.1572981 0.7606899 1.0000000

R ..のユーザーにとって、これは私の答えのソリューションメソッドBの悪い「貧乏人」バージョン(コントロールが少ない)ではないかもしれません。
マークL.ストーン

これは最適ではありませんが、時にはうまくいくこともあります。
マイク博士
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.