确保协方差矩阵正定



我的神经网络的输出作为协方差矩阵的条目。然而,输出和条目之间的一对一对应导致非正定协方差矩阵。

因此,我读到https://www.quora.com/When-carrying-out-the-EM-algorithm-how-do-I-ensure-that-the-covariance-matrix-is-positive-definite-at-all-times-avoiding-rounding-issues和https://en.wikipedia.org/wiki/Cholesky_decomposition,更具体地说,"当A有实数项时,L也有实数项,分解可以写成A = LL^T"。

现在我的输出对应于L矩阵的项然后我通过乘以它的转置来生成协方差矩阵。

然而,有时我仍然有一个错误的非正定矩阵。这怎么可能呢?

我发现了一个产生错误的矩阵,参见

print L.shape
print Sigma.shape
S = Sigma[1,18,:,:] # The matrix that gives the error
L_ = L[1,18,:,:]
print L_
S = np.dot(L_,np.transpose(L_))
print S
chol = np.linalg.cholesky(S)

给出如下输出:

(3, 20, 2, 2)
(3, 20, 2, 2)
[[ -1.69684255e+00   0.00000000e+00]
 [ -1.50235415e+00   1.73807144e-04]]
[[ 2.87927461  2.54925847]
 [ 2.54925847  2.25706792]]
.....
LinAlgError: Matrix is not positive definite

然而,这段复制值的代码工作得很好(但可能不是完全相同的值,因为不是所有的小数都打印出来)

B = np.array([[-1.69684255e+00, 0.00000000e+00], [-1.50235415e+00, 1.73807144e-04]])
A = np.dot(B,B.T)
chol_A = np.linalg.cholesky(A)

问题是:

  • 使用Sigma = LL'的方法是否正确(与'转置')?
  • 如果是,为什么我得到一个错误?这是由于舍入问题吗?
编辑:我还计算了特征值
print np.linalg.eigvalsh(S)
[ -7.89378944432428397703915834426880e-08
   5.13634252548217773437500000000000e+00]

对于第二种情况

print np.linalg.eigvalsh(A)
[  1.69341869415973178547574207186699e-08
   5.13634263409323210680668125860393e+00]

所以在第一种情况下有一个轻微的负特征值,它声明了非正确定性。但是如何解决这个问题呢?

这看起来像是一个数值问题,但通常情况下,LL'并不总是正定的(如果L是可逆的,则会是正定的)。例如,取L为矩阵,其中每列为[1 0 0 0…](或者更极端——取L为任意维数的零矩阵),L'将不会是PD。一般我建议使用

S = LL' + eps I

解决了这两个问题(对于小eps),并且是一个"正则化"协方差估计。你甚至可以选择"最优"

利用Ledoit-Wolf估计器求eps的(在某些假设下)值。

我怀疑L*L'的计算在第一种情况下是用浮点数完成的,在第二种情况下是用双精度完成的。我试过把你的L作为一个浮点矩阵,计算L*L '并找到它的特征值,我得到的值和你在第一种情况下做的一样,但是如果我把L转换成双精度矩阵,计算L*L'并找到特征值,我得到的值和你在第二种情况下做的一样。

这是有道理的,因为在L*L'[1,1]的计算中,与-1.50235415e+00的平方相比,1.73807144e-04的平方在浮点数中可以忽略不计。

如果我是对的,解决方案是在任何计算之前将L转换为双精度矩阵

相关内容

  • 没有找到相关文章

最新更新