numpy 使用np.基于打印或进一步(不相关)计算的倒数变化的函数输出[重复]

ecbunoof  于 2023-11-18  发布在  其他
关注(0)|答案(1)|浏览(93)

此问题在此处已有答案

numpy.reciprocal returns different values when called repeatedly [duplicate](1个答案)
13天前关门了。
在计算SVD时,我遇到了与np.reciprocal有关的奇怪行为。在某些条件下(即在不相关的变量上执行额外的步骤或打印变量),由于某种原因,输出会发生变化。
下面是代码的简化版本。

import numpy as np
from numpy.linalg import eig
from math import sqrt

def ComputeSVD(A):
    m, n = A.shape
    eigenvalues, eigenvectors = eig(A.T @ A)

    Sigma = np.zeros((m,n))
    np.fill_diagonal(Sigma, np.sqrt(eigenvalues))
    print(Sigma)

    U = np.zeros((m,m))
    for i in range(len(eigenvalues)):
         U[:,i] =  A @ (eigenvectors[:,i]) 

    return Sigma

def PseudoInverse(A):
    S = ComputeSVD(A)
    S_inv = np.reciprocal(S, where= (S != 0))
    return S_inv

A = np.array([[1.0, 1.0, 1.0], [1.0, 2.0, 3.0], [1.0, 4.0, 9.0]])
print(PseudoInverse(A))

字符串
对于非对角线条目,输出不正确:

[[10.64956309  0.          0.        ]
 [ 0.          1.2507034   0.        ]
 [ 0.          0.          0.15015641]]
[[ 0.09390057 -0.74904542  0.64830637]
 [-0.34457359  0.79955008 -0.73997748]
 [-0.92878374  0.32438956  6.65972239]]


但是,当删除与U相关的计算部件时,

import numpy as np
from numpy.linalg import eig
from math import sqrt

def ComputeSVD(A):
    m, n = A.shape
    eigenvalues, eigenvectors = eig(A.T @ A)

    Sigma = np.zeros((m,n))
    np.fill_diagonal(Sigma, np.sqrt(eigenvalues))
    print(Sigma)

    return (Sigma) 

def PseudoInverse(A): #same as before

A = np.array([[1.0, 1.0, 1.0], [1.0, 2.0, 3.0], [1.0, 4.0, 9.0]])
print(PseudoInverse(A))


现在输出是正确的:

[[10.64956309  0.          0.        ]
 [ 0.          1.2507034   0.        ]
 [ 0.          0.          0.15015641]]
[[0.09390057 0.         0.        ]
 [0.         0.79955008 0.        ]
 [0.         0.         6.65972239]]


更奇怪的是,当我们离开与U相关的部分时,但是在我们反转非零条目之前,我们打印(S),这个问题再次得到纠正。

import numpy as np
from numpy.linalg import eig
from math import sqrt

def ComputeSVD(A): #Same as first time

def PseudoInverse(A):
    S = ComputeSVD(A)
    print(S)
    S_inv = np.reciprocal(S, where= (S != 0))
    return S_inv

A = np.array([[1.0, 1.0, 1.0], [1.0, 2.0, 3.0], [1.0, 4.0, 9.0]])
print(PseudoInverse(A))


现在再次生成正确的输出。(参见第二个输出)

xpcnnkqh

xpcnnkqh1#

线

S_inv = np.reciprocal(S, where=(S != 0))

字符串
创建一个未初始化的数组,并将条件S != 0True的条目填充为S的相应元素的倒数。所有其他元素保持不变,因此它们可能是零,但也可能具有一些随机值。为了解决这个问题,使用out参数初始化一个数组,其中将存储结果:

S_inv = np.reciprocal(S, where=(S != 0), out=np.zeros_like(S))

相关问题