【问题标题】:Is sparse tensor multiplication implemented in TensorFlow?TensorFlow 中是否实现了稀疏张量乘法?
【发布时间】:2016-03-05 22:48:42
【问题描述】:

稀疏张量与它们自身或与密集张量的乘法似乎在 TensorFlow 中不起作用。下面的例子

from __future__ import print_function
import tensorflow as tf

x = tf.constant([[1.0,2.0],
                 [3.0,4.0]])
y = tf.SparseTensor(indices=[[0,0],[1,1]], values=[1.0,1.0], shape=[2,2])
z = tf.matmul(x,y)

sess = tf.Session()
sess.run(tf.initialize_all_variables())
print(sess.run([x, y, z]))

失败并显示错误消息

TypeError: Input 'b' of 'MatMul' Op has type string that does not match type 
float32 of argument 'a'

两个张量都有 float32 类型的值,通过在没有乘法运算的情况下评估它们可以看出。 y 与自身相乘会返回类似的错误消息。 x 与自身相乘可以正常工作。

【问题讨论】:

    标签: sparse-matrix tensorflow


    【解决方案1】:

    tf.SparseTensor 的通用乘法目前未在 TensorFlow 中实现。但是,有 3 种部分解决方案,正确的选择将取决于您的数据的特征:

    • 如果您有tf.SparseTensor 和tf.Tensor,您可以使用tf.sparse_tensor_dense_matmul() 将它们相乘。如果其中一个张量在致密化时太大而无法放入内存,这比下一种方法更有效:文档有更多关于如何在这两种方法之间做出决定的指导。请注意,它接受 tf.SparseTensor 作为 first 参数,因此要解决您的确切问题,您需要使用 adjoint_a 和 adjoint_b 参数,并转置结果。

    • 如果您有两个稀疏张量并且需要将它们相乘,最简单(如果不是性能最高的话)的方法是将它们转换为稠密并使用tf.matmul:

      a = tf.SparseTensor(...)
      b = tf.SparseTensor(...)
      
      c = tf.matmul(tf.sparse_tensor_to_dense(a, 0.0),
                    tf.sparse_tensor_to_dense(b, 0.0),
                    a_is_sparse=True, b_is_sparse=True)
      

      请注意,可选的a_is_sparse 和b_is_sparse 参数意味着“a(或b)具有密集表示,但其大量条目为零”,这会触发使用不同的乘法算法。

    • 对于稀疏向量通过(可能大且分片)密集矩阵乘法的特殊情况,并且向量中的值为0或1,tf.nn.embedding_lookup运算符可能更多合适的。 This tutorial 讨论了何时可以使用嵌入以及如何更详细地调用运算符。

    • 对于稀疏 matrix 由(可能很大和分片的)密集矩阵的特殊情况,tf.nn.embedding_lookup_sparse() 可能是合适的。该函数接受一个或两个tf.SparseTensor 对象,sp_ids 表示非零值,可选的sp_weights 表示它们的值(否则默认为一个)。

    【讨论】:

    • 谢谢。这节省了我的时间。
    • 为什么tf.sparse_matmul没有被覆盖?有什么不同?
    • 如何对两个稀疏张量进行元素乘法?
    【解决方案2】:

    【讨论】:

      【解决方案3】:

      为了让答案更完整:

      tf.sparse_matmul(
          a,
          b,
          transpose_a=None,
          transpose_b=None,
          a_is_sparse=None,
          b_is_sparse=None,
          name=None
      )
      

      也存在:

      https://www.tensorflow.org/api_docs/python/tf/sparse_matmul

      【讨论】:

      • 我得到:TypeError: Expected binary or unicode string, got <tensorflow.python.framework.ops.SparseTensor object at 0x7f90873f4fd0>
      • pcejrowski !这是您的链接所写的内容““a”和“b”都必须是张量而不是稀疏张量”。不像你的建议 a_is_sparse=True 并不意味着矩阵是稀疏类型。它只是意味着矩阵 a 有许多零值,因此算法通过使用该先验信息快速计算它!
      【解决方案4】:

      好像

      tf.sparse_matmul(
          a,
          b,
          transpose_a=None,
          transpose_b=None,
          a_is_sparse=None,
          b_is_sparse=None,
          name=None
      )
      

      不适用于两个SparseTensors的乘法。

      a 和 b 是 Tensors 而不是 SparseTensors。我已经尝试过了,它不适用于SparseTensors。

      【讨论】:

        【解决方案5】:

        tf.sparse_matmul 用于将两个密集张量相乘而不是稀疏类型的数据结构。如果给定矩阵(或两个矩阵)具有许多零值,则该函数只是张量乘法的优化版本。同样,它不接受稀疏张量数据类型。它接受密集张量数据类型。如果值大多为零,它可能会加快您的计算。

        据我所知,没有两个稀疏类型张量乘法的实现。但只有一疏一密,即 tf.sparse_tensor_dense_matmul(x, y)!

        【讨论】:

          【解决方案6】:

          在 TF2.4.1 中,您可以使用 tensorflow.python.ops.linalg.sparse.sparse_csr_matrix_ops 中的方法乘以任意 SparseTensor(我认为最多 3 个维度)。

          应该使用类似下面的东西(通常你将稀疏张量转换为 CSR 表示)

          import tensorflow as tf
          from tensorflow.python.ops.linalg.sparse import sparse_csr_matrix_ops
          
          
          def tf_multiply(a: tf.SparseTensor, b: tf.SparseTensor):
              a_sm = sparse_csr_matrix_ops.sparse_tensor_to_csr_sparse_matrix(
                  a.indices, a.values, a.dense_shape
              )
          
              b_sm = sparse_csr_matrix_ops.sparse_tensor_to_csr_sparse_matrix(
                  b.indices, b.values, b.dense_shape
              )
          
              c_sm = sparse_csr_matrix_ops.sparse_matrix_sparse_mat_mul(
                  a=a_sm, b=b_sm, type=tf.float32
              )
          
              c = sparse_csr_matrix_ops.csr_sparse_matrix_to_sparse_tensor(
                  c_sm, tf.float32
              )
          
              return tf.SparseTensor(
                  c.indices, c.values, dense_shape=c.dense_shape
              )
          

          有一段时间我更喜欢 scipy 乘法(通过 py_function),因为 TF(2.3 和 2.4)中的这种乘法性能不如 scipy。我最近再次尝试,要么我在我的代码上进行了一些更改,要么在 2.4.1 中进行了一些修复,使得 TF 稀疏乘法在 CPU 和 GPU 中都比使用 scipy 更快。

          【讨论】:

          • 为什么会有self?
          • @LucaCappelletti 我将其作为类的方法来实现,但这里的演示不需要 self 。谢谢。
          • 完美运行(tf-2.6)
          • 是否还有一个基于 python.ops 的版本,它支持 3 级张量的稀疏密集乘法(具有批量维度),因为 tf.sparse.sparse_dense_matmul 不支持?跨度>
          猜你喜欢
          • 2018-07-19
          • 2017-12-03
          • 2017-05-02
          • 1970-01-01
          • 1970-01-01
          • 2017-02-11
          • 1970-01-01
          • 2012-01-03
          • 1970-01-01
          相关资源
          最近更新 更多