我想测试一下我用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制作。
答案 0 :(得分:6)
问题不在于胆怯分解。问题在于随机矩阵L
。
rand(N,N)
的条件比tril(rand(N,N))
好得多。要查看此内容,请将cond(rand(N,N))
与cond(tril(rand(N,N)))
进行比较。我得到的是第一个1e3
和第二个1e19
,所以第二个矩阵的条件数要高得多,计算在数值上也不太稳定。
这将导致在病态情况下获得一些小的负特征值 - 看看使用eig()
查看特征值,一些小的将是负的。
因此我建议使用rand(N,N)
生成数值稳定的随机矩阵。
答案 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