Python tensorflow中numpy.linalg.pinv的替代方案
我正在寻找tensorflow中numpy.linalg.pinv的替代品。Python tensorflow中numpy.linalg.pinv的替代方案,python,python-3.x,numpy,tensorflow,Python,Python 3.x,Numpy,Tensorflow,我正在寻找tensorflow中numpy.linalg.pinv的替代品。 到目前为止,我发现tensorflow只有tf.matrix_inverse(输入,伴随=None,name=None),如果矩阵不可逆,它就会抛出一个错误 我不知道tensorflow中的numpy.linalg.pinv替代方案,但正则化是矩阵不可逆时的替代方案。例如: try: result = tf.matrix_inverse(input, adjoint=None, name=None) exce
到目前为止,我发现tensorflow只有
tf.matrix_inverse(输入,伴随=None,name=None)
,如果矩阵不可逆,它就会抛出一个错误 我不知道tensorflow中的numpy.linalg.pinv替代方案,但正则化是矩阵不可逆时的替代方案。例如:
try:
result = tf.matrix_inverse(input, adjoint=None, name=None)
except:
input += np.identity((input.shape))* c
result = tf.matrix_inverse(input, adjoint=None, name=None)
式中,c为常数,应非常小,如c=0.000001
然而,矩阵求逆在计算上相当昂贵,只有在必要时才能进行。有关更多信息,请参见:您可以将tensorflow
与numpy
组合,如下所示:
return tf.py_func(np.linalg.pinv, [input], tf.float32)
TensorFlow提供了一个SVD op,因此您可以很容易地从中计算伪逆:
def pinv(A, b, reltol=1e-6):
# Compute the SVD of the input matrix A
s, u, v = tf.svd(A)
# Invert s, clear entries lower than reltol*s[0].
atol = tf.reduce_max(s) * reltol
s = tf.boolean_mask(s, s > atol)
s_inv = tf.diag(tf.concat([1. / s, tf.zeros([tf.size(b) - tf.size(s)])], 0))
# Compute v * s_inv * u_t * b from the left to avoid forming large intermediate matrices.
return tf.matmul(v, tf.matmul(s_inv, tf.matmul(u, tf.reshape(b, [-1, 1]), transpose_a=True)))
numpy实现之后的实现:
def pinv(a, rcond=1e-15):
s, u, v = tf.svd(a)
# Ignore singular values close to zero to prevent numerical overflow
limit = rcond * tf.reduce_max(s)
non_zero = tf.greater(s, limit)
reciprocal = tf.where(non_zero, tf.reciprocal(s), tf.zeros(s.shape))
lhs = tf.matmul(v, tf.matrix_diag(reciprocal))
return tf.matmul(lhs, u, transpose_b=True)
这支持伪逆的单次和批量计算:
# Pseudo-inverse of one (4, 3) matrix, has shape (3, 4)
pinv(tf.random_normal((4, 3)))
# Pseudo-inverses of two (4, 3) matrices, has shape (2, 3, 4)
pinv(tf.random_normal((2, 4, 3)))
谢谢@Andy Tsai的提示 支持批处理以提高计算速度的另一种方法是将
tf.diag
替换为tf.matrix\u diag
。大概是这样的:
def pinv(a, rcond=1e-15):
s, u, v = tf.svd(a)
# Ignore singular values close to zero to prevent numerical overflow
limit = rcond * tf.reduce_max(s)
non_zero = tf.greater(s, limit)
reciprocal = tf.where(non_zero, tf.reciprocal(s), tf.zeros(s.shape))
lhs = tf.matmul(v, tf.matrix_diag(reciprocal))
return tf.matmul(lhs, u, transpose_b=True)
如果矩阵不可逆,您也可以使用正则化。@NikolasRieble,请提供一个示例
pinv()
基于SVD,Tensorflow有一个SVD函数。。。我不打算提供一个例子:)扩展你的最后一句话,如果OP必须解决ax=b
,他们可以在x方面找到x
← pinv(A)@b
(OP暗示的路线)或(按照您的建议)他们可以做如下操作:b^← A.T@b
,A^← A.T@A
并使用LU分解等方法求解线性系统A^x=b^
将永远不会调用除块之外的。调用tf.matrix\u inverse(输入,伴随=None,name=None)
只是将相应的操作添加到图形中。它不会检查输入是否可逆,因为输入本身只是一个没有任何值的张量。您仍然会遇到InvalidArgumentError(回溯见上文):输入不可逆。
+1,这应该是可接受的答案。但是,是否可以将b
设置为可选?除了计算A+*b之外,用户可能还需要伪逆函数。我认为,可以用s_inv=tf.diag(1./s)替换最后两行。返回tf.matmul(v,tf.matmul(s_inv,u,transpose_b=True))