[英]Generate multivariate normal r.v.'s with rank-deficient covariance via Pivoted Cholesky Factorization
I'm just beating my head against the wall trying to get a Cholesky decomposition to work in order to simulate correlated price movements. 我只是在碰壁,试图使Cholesky分解起作用,以便模拟相关的价格变动。
I use the following code: 我使用以下代码:
cormat <- as.matrix(read.csv("http://pastebin.com/raw/qGbkfiyA"))
cormat <- cormat[,2:ncol(cormat)]
rownames(cormat) <- colnames(cormat)
cormat <- apply(cormat,c(1,2),FUN = function(x) as.numeric(x))
chol(cormat)
#Error in chol.default(cormat) :
# the leading minor of order 8 is not positive definite
cholmat <- chol(cormat, pivot=TRUE)
#Warning message:
# In chol.default(cormat, pivot = TRUE) :
# the matrix is either rank-deficient or indefinite
rands <- array(rnorm(ncol(cholmat)), dim = c(10000,ncol(cholmat)))
V <- t(t(cholmat) %*% t(rands))
#Check for similarity
cor(V) - cormat ## Not all zeros!
#Check the standard deviations
apply(V,2,sd) ## Not all ones!
I'm not really sure how to properly use the pivot = TRUE
statement to generate my correlated movements. 我不太确定如何正确使用
pivot = TRUE
语句来生成我的相关运动。 The results look totally bogus. 结果看起来完全是假的。
Even if I have a simple matrix and I try out "pivot" then I get bogus results... 即使我有一个简单的矩阵,并且尝试“枢轴”操作,我也会得到虚假结果...
cormat <- matrix(c(1,.95,.90,.95,1,.93,.90,.93,1), ncol=3)
cholmat <- chol(cormat)
# No Error
cholmat2 <- chol(cormat, pivot=TRUE)
# No warning... pivot changes column order
rands <- array(rnorm(ncol(cholmat)), dim = c(10000,ncol(cholmat)))
V <- t(t(cholmat2) %*% t(rands))
#Check for similarity
cor(V) - cormat ## Not all zeros!
#Check the standard deviations
apply(V,2,sd) ## Not all ones!
There are two errors with your code: 您的代码有两个错误:
You did not use pivoting index to revert the pivoting done to the Cholesky factor. 您没有使用数据透视索引将数据透视还原为Cholesky因素。 Note, pivoted Cholesky factorization for a semi-positive definite matrix
A
is doing: 注意,半正定矩阵
A
枢轴Cholesky分解正在执行:
P'AP = R'R
where P
is a column pivoting matrix, and R
is an upper triangular matrix. 其中
P
是列枢轴矩阵, R
是上三角矩阵。 To recover A
from R
, we need apply the inverse of P
(ie, P'
): 为了从
R
恢复A
,我们需要应用P
的倒数(即P'
):
A = PR'RP' = (RP')'(RP')
Multivariate normal with covariance matrix A
, is generated by: 带有协方差矩阵
A
多元正态是通过以下方式生成的:
XRP'
where X
is multivariate normal with zero mean and identity covariance. 其中
X
是具有零均值和恒等协方差的多元法线。
Your generation of X
您的
X
世代
X <- array(rnorm(ncol(R)), dim = c(10000,ncol(R)))
is wrong. 是错的。 First, it should not be
ncol(R)
but nrow(R)
, ie, the rank of X
, denoted by r
. 首先,它不应该是
ncol(R)
但nrow(R)
即,秩X
,记为r
Second, you are recycling rnorm(ncol(R))
along columns, and the resulting matrix is not random at all. 其次,您将沿着列回收
rnorm(ncol(R))
,并且所得矩阵根本不是随机的。 Therefore, cor(X)
is never close to an identity matrix. 因此,
cor(X)
永远不会接近单位矩阵。 The correct code is: 正确的代码是:
X <- matrix(rnorm(10000 * r), 10000, r)
As a model implementation of the above theory, consider your toy example: 作为上述理论的模型实现,请考虑您的玩具示例:
A <- matrix(c(1,.95,.90,.95,1,.93,.90,.93,1), ncol=3)
We compute the upper triangular factor (suppressing possible rank-deficient warnings) and extract inverse pivoting index and rank: 我们计算较高的三角因子(抑制可能的等级不足警告),并提取反向枢轴索引和等级:
R <- suppressWarnings(chol(A, pivot = TRUE))
piv <- order(attr(R, "pivot")) ## reverse pivoting index
r <- attr(R, "rank") ## numerical rank
Then we generate X
. 然后我们生成
X
For better result we centre X
so that column means are 0. 为了获得更好的结果,我们将
X
居中,以使列均值为0。
X <- matrix(rnorm(10000 * r), 10000, r)
## for best effect, we centre `X`
X <- sweep(X, 2L, colMeans(X), "-")
Then we generate target multivariate normal: 然后我们生成目标多元正态:
## compute `V = RP'`
V <- R[1:r, piv]
## compute `Y = X %*% V`
Y <- X %*% V
We can verify that Y
has target covariance A
: 我们可以验证
Y
具有目标协方差A
:
cor(Y)
# [,1] [,2] [,3]
#[1,] 1.0000000 0.9509181 0.9009645
#[2,] 0.9509181 1.0000000 0.9299037
#[3,] 0.9009645 0.9299037 1.0000000
A
# [,1] [,2] [,3]
#[1,] 1.00 0.95 0.90
#[2,] 0.95 1.00 0.93
#[3,] 0.90 0.93 1.00
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.