【问题标题】:Alternative of numpy.linalg.pinv in tensorflowtensorflow 中 numpy.linalg.pinv 的替代方案
【发布时间】:2017-02-28 06:28:12
【问题描述】:

我正在寻找 tensorflow 中 numpy.linalg.pinv 的替代方案。 到目前为止,我发现 tensorflow 只有tf.matrix_inverse(input, adjoint=None, name=None),如果矩阵不可逆,则会引发错误。

【问题讨论】:

  • 如果矩阵不可逆,您也可以使用正则化。
  • @NikolasRieble,请举个例子
  • pinv() 是基于 SVD 的,Tensorflow 有 SVD 功能……我就不举例了:)

标签: python python-3.x numpy tensorflow


【解决方案1】:

TensorFlow 提供了一个 SVD 运算,因此您可以很容易地从中计算出伪逆:

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)))

【讨论】:

  • +1,这应该是公认的答案。但是,也许将b 设为可选?用户可能需要伪逆来计算 A+ * b 以外的其他目的?
  • 我认为,可以将最后两行替换为:s_inv = tf.diag(1. / s)。 return tf.matmul(v, tf.matmul(s_inv, u, transpose_b=True))
【解决方案2】:

遵循 numpy 的 pinv 实现的实现:

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 的提示!

【讨论】:

    【解决方案3】:

    我不知道 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

    然而,矩阵求逆在计算上是相当昂贵的,只有在必要时才应该这样做。更多信息请见:do not invert that matrix

    【讨论】:

    • 扩展你最后的评论,如果 OP 必须解决 A x = b 他们可以找到x x ← pinv(A)@b (OP 暗示的路线)或(按照您的建议)他们可以执行以下操作:b^ ← A.T@bA^ ← A.T@A 并使用例如解决LU分解,线性系统A^ x = b^
    • 永远不会调用except 块。对tf.matrix_inverse(input, adjoint=None, name=None) 的调用只是将相应的操作添加到图中。它不检查输入是否可逆,因为输入本身只是一个没有任何值的张量。你仍然会遇到InvalidArgumentError (see above for traceback): Input is not invertible.
    【解决方案4】:

    您可以将tensorflowtf.py_funcnumpypseudo-inverse 组合如下:

    return tf.py_func(np.linalg.pinv, [input], tf.float32)
    

    【讨论】:

      【解决方案5】:

      支持批处理以加快计算速度的另一种方法是将tf.diag 替换为tf.matrix_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)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-06-13
        • 1970-01-01
        • 1970-01-01
        • 2018-09-28
        • 2015-06-13
        • 2015-03-03
        • 2015-09-25
        • 2019-12-16
        相关资源
        最近更新 更多