サンプルのサンプル共分散行列を推定し、対称行列を取得しました。では、私が作成したい変量通常の分散RNをしかしそれゆえ、私はのコレスキー分解必要な。が正定でない場合はどうすればよいですか?
サンプルのサンプル共分散行列を推定し、対称行列を取得しました。では、私が作成したい変量通常の分散RNをしかしそれゆえ、私はのコレスキー分解必要な。が正定でない場合はどうすればよいですか?
回答:
問題は、(おそらく)特異共分散行列持つ多変量正規分布からランダム変量を生成する方法に関するものです。この回答は、共分散行列に対して機能する1つの方法を説明しています。精度をテストする実装を提供します。R
ので共分散行列であり、必ずしも対称と正半正定値です。背景情報を完成させるために、を目的の平均のベクトルにします。
ので対称で、その特異値分解(SVD)およびその固有値分解は、自動的にフォームを有することになります
いくつかの直交行列と対角行列D 2に対して。一般に、D 2の対角要素は非負です(それらはすべて実数平方根を持っていることを意味します:対角行列Dを形成するために正のものを選択してください)。Cについての情報は、これらの対角要素の1つ以上がゼロであると述べていますが、それは後続の操作に影響を与えず、SVDの計算を妨げません。
レッツ各コンポーネントはゼロ平均、単位分散を持っており、すべての共分散はゼロです::標準の多変量正規分布を持つその共分散行列がアイデンティティであるI。次に、ランダム変数Y = V D Xは共分散行列を持ちます
その結果、ランダム変数は、平均μと共分散行列Cをもつ多変量正規分布になります。
次のR
コードは、指定された次元とランクの共分散行列を生成し、SVD(またはコメントアウトされたコードで固有分解)で分析し、その分析を使用して指定された数の実現を生成します(平均ベクトル0) 、そしてそれらのデータの共分散行列を、数値的およびグラフィカルに目的の共分散行列と比較します。示されるように、それが生成し10 、000の寸法実現Yがである100とのランクCがある50。出力は
rank L2
5.000000e+01 8.846689e-05
つまり、データのランクもあり、データから推定される共分散行列は、Cの8 × 10 − 5の距離内にあり、これは近いです。より詳細なチェックとして、Cの係数がその推定の係数に対してプロットされます。それらはすべて、平等線の近くにあります。
コードは前述の分析とまったく同じであるため、一目瞭然R
です(お気に入りのアプリケーション環境でエミュレートする可能性のある非ユーザーでも)。浮動小数点アルゴリズムを使用する場合、それは明らかに一つのことは、注意が必要なことである:のエントリ容易に不正確に起因する負の(しかし小さい)とすることができます。そのようなエントリは、D自体を見つけるために平方根を計算する前にゼロにする必要があります。
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")
解決方法A:
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のすべての要素の平方差。非対角要素を含む。そのため、非対角要素を調整することにより、対角要素を増やす必要がある量を減らすことができ、対角要素を必ずしもすべて同じ量だけ増やす必要はありません。
あなたが推定しているモデルについて考えることから始めます。
共分散行列が正の半正定値ではない場合、変数に共線形性の問題があることを示している可能性があります。これは、モデルの問題を示しており、必ずしも数値的手法で解決する必要はありません。
1つの方法は、固有値分解から行列を計算することです。今、これらのプロセスの背後にある数学についてあまり知らないことを認めますが、私の研究から、このヘルプファイルを見るのは実りあるようです:
http://stat.ethz.ch/R-manual/R-patched/library/Matrix/html/chol.html
およびRの他の関連コマンド
また、Matrixパッケージの「nearPD」も確認してください。
申し訳ありませんが、これ以上のお手伝いはできませんでしたが、周りを検索することで正しい方向に進むことができれば幸いです。
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