如何从粗糙张量中减去一个张量?
的例子:
import tensorflow as tf # TensorFlow 2.6
X = tf.ragged.constant([[[3, 1], [3]],
[[2], [3, 4]]], ragged_rank=2)
y = tf.constant([[1], [2]])
X-y
预期结果:
[[[2, 0], [1]],
[[1], [1, 2]]]
但是,它返回一个错误:
tensorflow.python.framework.errors_impl.InvalidArgumentError: Expected 'tf.Tensor(False, shape=(), dtype=bool)' to be true. Summarized data: b'Unable to broadcast: dimension size mismatch in dimension'
1
b'lengths='
2
b'dim_size='
2, 2
我知道我可以逐行执行:
result = []
if X.shape[0] is not None: # Placeholders have None everywhere -> range(None) raises an exception -> this condition
for row in range(X.shape[0]):
result.append(X[row] - y)
result = tf.stack(result)
然而,这只适用于等待模式-在图形模式下,我得到:
ValueError: No gradients provided for any variable
因为代码只会有条件地执行…
有效的方法是硬编码行数:
for row in range(2):
result.append(X[row] - y)
result = tf.stack(result)
但这不能很好地概括。
我也知道我可以写:
X - tf.expand_dims(y, axis=1)
但是返回的结果是&;转置&;y:
[[[2, 0], [2]],
[[0], [1, 2]]]
我还知道我还可以使用:
def subtract(x):
return x - y
tf.map_fn(subtract, X)
但是当在图形模式下使用结果时,我得到:
ValueError: Unable to broadcast: unknown rank
要达到预期效果,请尝试以下操作:
X - tf.expand_dims(y, axis=2)
注意,我们只在原来的y
上添加了tf.expand_dims()
,它仍然是tf.constant([[1], [2]])
得到了以下期望的结果(在TF 2.6版本上测试):
<tf.RaggedTensor [[[2, 0], [2]], [[0], [1, 2]]]>
import tensorflow as tf # TensorFlow 2.6
print("TensorFlow version:", tf. version )
X = tf.ragged.constant([[[3, 1], [3]],
[[2], [3, 4]]], ragged_rank=2)
y = tf.constant([[1], [2]])
print(X-tf.expand_dims(y, axis=2))
与输出:
<tf.RaggedTensor [[[2, 0], [2]], [[0], [1, 2]]]>
这对你有用吗?
x = tf.ragged.constant([[[3, 1], [3]],
[[2], [3, 4]]]) # shape(2,None,None)
x = tf.RaggedTensor.from_uniform_row_length(x.values, uniform_row_length=2) # shape(2,2,None)
x - y
输出
<tf.RaggedTensor [[[2, 0], [1]],
[[1], [1, 2]]]>
一种较好的方法是将x
构造为秩为1的张量
x = tf.ragged.constant([[3, 1], [3],
[2], [3, 4]], ragged_rank=1) # shape(4,None)
x = tf.RaggedTensor.from_uniform_row_length(x, uniform_row_length=2) # shape(2,2,None)
不幸的是,tf.RaggedTensor
s有点不稳定。
tldr;tf.RaggedTensor
和tf.Tensor
之间的操作并不总是如预期的那样。有时将tf.Tensor
转换为tf.RaggedTensor
也可以。
解决方案如下:X
可以保持原样,
X = tf.ragged.constant([[[3, 1], [3]],
[[2], [3, 4]]], ragged_rank=2)
形状(X.shape
)为[2, None, None]
的
解决方案接下来我们将y
转换为tf.RaggedTensor
,如下所示。
y = tf.ragged.constant(pylist=[[[1], [2]]], ragged_rank=1)
的形状(y.shape
)为[1, None, 1]
。,
X-y
给出
<tf.RaggedTensor [[[2, 0], [1]], [[1], [1, 2]]]>
警告
对于y
aragged_rank=2
将导致以下错误:
InvalidArgumentError: Expected 'tf.Tensor(False, shape=(), dtype=bool)' to be true. Summarized data: b'Unable to broadcast: dimension size mismatch in dimension'
2
b'lengths='
1, 1, 1, 1
b'dim_size='
2, 1, 1, 2
我不完全理解。避免这种情况的最佳方法是尽可能多地固定维度。随着张量的维数增加,这个会变得更复杂。为此,您可以使用RaggedTensor
结构,如from_uniform_row_length
(此处和此处有更多信息)