我们有一个未知长度为N的Tensor,包含一些int32值。 我们如何生成另一个包含连接在一起的N个范围的Tensor,每个范围在0和原始张量的int32值之间?
例如,如果我们有[4, 4, 5, 3, 1]
,则输出Tensor应该看起来像[0 1 2 3 0 1 2 3 0 1 2 3 4 0 1 2 0]
。
感谢您的任何建议。
答案 0 :(得分:2)
您可以通过使用tf.RaggedTensor
使其包含张量作为输入来工作,该# Or any other N length tensor
tf_counts = tf.convert_to_tensor([4, 4, 5, 3, 1])
tf.print(tf_counts)
# [4 4 5 3 1]
# Create a ragged tensor, each row is a sequence of length tf_counts[i]
tf_ragged = tf.ragged.range(tf_counts)
tf.print(tf_ragged)
# <tf.RaggedTensor [[0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3, 4], [0, 1, 2], [0]]>
# Read values
tf.print(tf_ragged.flat_values, summarize=-1)
# [0 1 2 3 0 1 2 3 0 1 2 3 4 0 1 2 0]
可以包含长度不均匀的尺寸。
tf_ragged
对于这种二维情况,参差不齐的张量[[0, 1, 2, 3],
[0, 1, 2, 3],
[0, 1, 2, 3, 4],
[0, 1, 2],
[0]]
是长度可变的行的“矩阵”:
starts
在tf.ragged.range上查看有关如何在每行上创建序列的更多选项:limits
包括下限,deltas
表示排他上限,dtype
表示增量。每个序列可能会有所不同。
还请注意,tf_counts
张量的var students = {
"name":"John", "semester":30
"name":"Anna", "semester":12
}
Wanted output:
var students {
"name":"John", "semester":30,8
"name":"Anna", "semester":12,4
}
会传播到最终值。
答案 1 :(得分:0)
如果您想将所有内容都作为张量流对象,请使用tf.range()
和tf.concat()
。
In [88]: vals = [4, 4, 5, 3, 1]
In [89]: tf_range = [tf.range(0, limit=item, dtype=tf.int32) for item in vals]
# concat all `tf_range` objects into a single tensor
In [90]: concatenated_tensor = tf.concat(tf_range, 0)
In [91]: concatenated_tensor.eval()
Out[91]: array([0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 0], dtype=int32)
还有其他方法可以做到这一点。在这里,我假设您需要一个constant tensor,但是一旦拥有完整范围列表,就可以构造任何张量。
首先,我们使用 list comprehension 构建完整范围列表,从中创建一个平面列表,然后构造一个张量。
In [78]: from itertools import chain
In [79]: vals = [4, 4, 5, 3, 1]
In [80]: range_list = list(chain(*[range(item) for item in vals]))
In [81]: range_list
Out[81]: [0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 0]
In [82]: const_tensor = tf.constant(range_list, dtype=tf.int32)
In [83]: const_tensor.eval()
Out[83]: array([0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 0], dtype=int32)
另一方面,我们也可以使用tf.range()
但是当你eval
时它会返回一个数组。因此,您必须从数组中构造列表,然后从中生成一个平面列表,最后构建张量,如下例所示。
list_of_arr = [tf.range(0, limit=item, dtype=tf.int32).eval() for item in vals]
range_list = list(chain(*[arr.tolist() for arr in list_of_arr]))
# output
[0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 0]
const_tensor = tf.constant(range_list, dtype=tf.int32)
const_tensor.eval()
#output tensor as numpy array
array([0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 0], dtype=int32)