生成伪随机正定矩阵

时间:2012-09-07 17:00:50

标签: c++ matlab math matrix scipy

我想测试一下我用C ++编写的简单的Cholesky代码。所以我生成一个随机的低三角形L并乘以它的转置来生成A.

A = L * Lt;

但我的代码无法考虑因素A.所以我在Matlab中尝试了这个:

N=200; L=tril(rand(N, N)); A=L*L'; [lc,p]=chol(A,'lower'); p

这输出非零p,这意味着Matlab也没有考虑因子A.我猜测随机性会产生秩不足的矩阵。我是对的吗?

更新

我忘了提到以下Matlab代码似乎正如下面Malife所指出的那样:

N=200; L=rand(N, N); A=L*L'; [lc,p]=chol(A,'lower'); p

差异是L在第一个代码中是低三角形而不是第二个代码。为什么要这么重要?

在阅读A simple algorithm for generating positive-semidefinite matrices之后,我还尝试了以下scipy:

from scipy import random, linalg
A = random.rand(100, 100)
B = A*A.transpose()
linalg.cholesky(B)

但它出错了:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/dist-packages/scipy/linalg/decomp_cholesky.py", line 66, in cholesky
    c, lower = _cholesky(a, lower=lower, overwrite_a=overwrite_a, clean=True)
  File "/usr/lib/python2.7/dist-packages/scipy/linalg/decomp_cholesky.py", line 24, in _cholesky
    raise LinAlgError("%d-th leading minor not positive definite" % info)
numpy.linalg.linalg.LinAlgError: 2-th leading minor not positive definite

我不明白为什么scipy会发生这种情况。有什么想法吗?

谢谢,
Nilesh制作。

4 个答案:

答案 0 :(得分:6)

问题不在于胆怯分解。问题在于随机矩阵Lrand(N,N)的条件比tril(rand(N,N))好得多。要查看此内容,请将cond(rand(N,N))cond(tril(rand(N,N)))进行比较。我得到的是第一个1e3和第二个1e19,所以第二个矩阵的条件数要高得多,计算在数值上也不太稳定。 这将导致在病态情况下获得一些小的负特征值 - 看看使用eig()查看特征值,一些小的将是负的。

因此我建议使用rand(N,N)生成数值稳定的随机矩阵。

顺便说一句,如果你对发生这种情况的理论感兴趣,你可以看一下这篇论文:

http://epubs.siam.org/doi/abs/10.1137/S0895479896312869

答案 1 :(得分:1)

如前所述,三角矩阵的特征值位于对角线上。因此,通过做

L=tril(rand(n))

你确保eig(L)只产生正值。您可以通过向对角线添加足够大的正数来改善L * L'的条件数,例如

L=L+n*eye(n)

和L * L'为正定且条件良好:

> cond(L*L')

ans =

1.8400

答案 2 :(得分:0)

要在MATLAB中生成随机正定矩阵,您的代码应为:

N=200;
L=rand(N, N); 
A=L*transpose(L); 
[lc,p]=chol(A,'lower');
eig(A)
p

你确实应该让特征值大于零而p为零。

答案 3 :(得分:0)

你问下三角形的情况。让我们看看会发生什么,以及为什么会有问题。查看测试用例通常是件好事。

对于简单的5x5矩阵,

L = tril(rand(5))
L =
      0.72194            0            0            0            0
     0.027804      0.78422            0            0            0
      0.26607     0.097189      0.77554            0            0
      0.96157      0.71437      0.98738      0.66828            0
     0.024571     0.046486      0.94515      0.38009     0.087634

eig(L)
ans =
     0.087634
      0.66828
      0.77554
      0.78422
      0.72194

当然,三角矩阵的特征值只是对角元素。由于rand生成的元素总是在0和1之间,因此它们平均大约为1/2。也许看看L的行列式的分布会有所帮助。更好的是考虑log(det(L))的分布。由于行列式将仅仅是对角元素的乘积,因此对数是对角元素的对数的总和。 (是的,我知道行列式是一个很差的奇点度量,但是log(det(L))的分布很容易计算出来,而且我觉得懒得考虑条件数的分布。)

啊,但是均匀随机变量的负对数是一个指数变量,在这种情况下是一个指数变量,λ= 1.一组n个均匀随机数的对数来自区间(0,1)由中心极限定理将是高斯。该总和的平均值为-n。因此,由这种方案生成的下三角形n×n矩阵的行列式将是exp(-n)。当n为200时,MATLAB告诉我

exp(-200)
ans =
   1.3839e-87

因此,对于任何可观大小的矩阵,我们可以看到它的条件很差。更糟糕的是,当你形成产品L * L'时,它通常在数字上是单数的。相同的参数适用于条件数。因此,对于甚至20×20矩阵,可以看出这种下三角矩阵的条件数相当大。然后,当我们形成矩阵L * L'时,条件将按预期平方。

L = tril(rand(20));

cond(L)
ans =
   1.9066e+07

cond(L*L')
ans =
   3.6325e+14

看看完整矩阵有多好。

A = rand(20);

cond(A)
ans =
       253.74

cond(A*A')
ans =
        64384