TensorFlow 中是否实现了稀疏张量乘法?
Is sparse tensor multiplication implemented in TensorFlow?
稀疏张量与自身或密集张量的乘法在 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 与自身相乘 returns 类似的错误信息。 x 与自身的乘法运算正常。
tf.SparseTensor
的通用乘法当前未在 TensorFlow 中实现。但是,一共有三个部分解决方案,选择合适的解决方案将取决于您的数据特征:
如果你有一个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
operator may be more appropriate. This tutorial 更详细地讨论了何时可以使用嵌入以及如何调用运算符。
对于稀疏 矩阵 由(可能很大且分片的)密集矩阵构成的特殊情况,tf.nn.embedding_lookup_sparse()
可能是合适的。此函数接受一个或两个 tf.SparseTensor
对象,其中 sp_ids
表示非零值,可选的 sp_weights
表示它们的值(否则默认为一个)。
最近,添加了 tf.sparse_tensor_dense_matmul(...)
,允许将稀疏矩阵乘以密集矩阵。
https://www.tensorflow.org/versions/r0.9/api_docs/python/sparse_ops.html#sparse_tensor_dense_matmul
为了让回答更完整:
tf.sparse_matmul(
a,
b,
transpose_a=None,
transpose_b=None,
a_is_sparse=None,
b_is_sparse=None,
name=None
)
也存在:
好像
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
.
tf.sparse_matmul 用于相乘两个稠密张量而非稀疏类型的数据结构。如果给定矩阵(或两个矩阵)有许多零值,则该函数只是张量乘法的优化版本。同样,它不接受稀疏张量数据类型。它接受密集张量数据类型。如果值大部分为零,它可能会加快您的计算速度。
据我所知,还没有两个稀疏类型张量乘法的实现。但只有一个稀疏一个密集,即 tf.sparse_tensor_dense_matmul(x, y) !
在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 更快。
稀疏张量与自身或密集张量的乘法在 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 与自身相乘 returns 类似的错误信息。 x 与自身的乘法运算正常。
tf.SparseTensor
的通用乘法当前未在 TensorFlow 中实现。但是,一共有三个部分解决方案,选择合适的解决方案将取决于您的数据特征:
如果你有一个
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
operator may be more appropriate. This tutorial 更详细地讨论了何时可以使用嵌入以及如何调用运算符。对于稀疏 矩阵 由(可能很大且分片的)密集矩阵构成的特殊情况,
tf.nn.embedding_lookup_sparse()
可能是合适的。此函数接受一个或两个tf.SparseTensor
对象,其中sp_ids
表示非零值,可选的sp_weights
表示它们的值(否则默认为一个)。
最近,添加了 tf.sparse_tensor_dense_matmul(...)
,允许将稀疏矩阵乘以密集矩阵。
https://www.tensorflow.org/versions/r0.9/api_docs/python/sparse_ops.html#sparse_tensor_dense_matmul
为了让回答更完整:
tf.sparse_matmul(
a,
b,
transpose_a=None,
transpose_b=None,
a_is_sparse=None,
b_is_sparse=None,
name=None
)
也存在:
好像
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
.
tf.sparse_matmul 用于相乘两个稠密张量而非稀疏类型的数据结构。如果给定矩阵(或两个矩阵)有许多零值,则该函数只是张量乘法的优化版本。同样,它不接受稀疏张量数据类型。它接受密集张量数据类型。如果值大部分为零,它可能会加快您的计算速度。
据我所知,还没有两个稀疏类型张量乘法的实现。但只有一个稀疏一个密集,即 tf.sparse_tensor_dense_matmul(x, y) !
在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 更快。