在TensorFlow 1.12中,你可以使用tf.math.unsorted_segment_sum来计算张量的各段最大值。
其中一个参数是:
segment_ids:一个张量。必须是以下类型之一:int32, int64。它的形状是data.shape的前缀。END } out_arg { name: “output” description: << END 与data的形状相同,只是前segment_ids.rank维度被替换为单一维度,其大小为num_segments。
问题1: 我不知道这意味着什么。我猜segment_ids
应该是[0,1,2,3,...]
,并且从0开始编号。
然后我尝试通过测试不同值的segment_ids
来验证我的假设:
print(sess.run(tf.unsorted_segment_max(tf.constant([0.1, 0.2, 0.3, 0.3, 0.4]), tf.constant([2, 0, 1, 1, 0]), 3)))#[0.4 0.3 0.1], 正确print(sess.run(tf.unsorted_segment_max(tf.constant([0.1, 0.2, 0.3, 0.3, 0.4]), tf.constant([3, 0, 1, 1, 0]), 3)))#[ 4.0000001e-01 3.0000001e-01 -3.4028235e+38], 编号2有效,但3无效print(sess.run(tf.unsorted_segment_max(tf.constant([0.1, 0.2, 0.3, 0.3, 0.4]), tf.constant([3, 0, 1, 1, 0]), 4)))#[ 4.0000001e-01 3.0000001e-01 -3.4028235e+38 1.0000000e-01], num_segments对最大值无效print(sess.run(tf.unsorted_segment_sum(tf.constant([0.1, 0.2, 0.3, 0.3, 0.4]), tf.constant([3, 0, 1, 1, 0]), 4)))#[0.6 0.6 0. 0.1], 而num_segments对求和有效。
从示例3和示例4中,我注意到tf.unsorted_segment_max()
中的segment_ids
有比tf.unsorted_segment_sum()
更多的限制,我认为它应该是从0开始的连续数字。示例3应该输出[0.4 0.3 0. 0.1]
从示例1和示例2中,我注意到示例1的结果是正确的,而示例2应该输出[0.4 0.3 0.]
,并且如果输入的segment_ids
无效,则不会有警告或错误发生。
问题2: 我如何检查我的segment_ids
是否符合要求?
问题3: 如果我的segment_ids
不符合要求,比如[3, 0, 1, 1, 0]
,我该怎么做才能使unsorted_segments_max
工作?
回答:
回答1: 对于一维情况,输出张量将具有由num_segments
指定的元素数量。每个元素i
将是操作(例如max
,sum
等)应用于data
中所有元素的结果,由位置j
表示,其中segment_ids[j] == i
。segment_ids
可以是任何数字,并不需要从0
开始。然而,输出将包含num_segments
个元素,如果对于任何输出元素i
都没有找到segment_ids[j] == i
,则使用特定默认值(每种操作的默认值不同)。对于高维张量,data
的前x
维度,由segment_ids
的秩指定,将被替换为包含各个段的单一维度。
你的示例
你似乎没有在tensorflow >= 1.12.0
上运行你的示例,因为第二个示例应该会引发异常:InvalidArgumentError (see above for traceback): segment_ids[0] = 3 is out of range [0, 3)
。它被忽略的事实可能是旧版本的行为(请检查)。
从tf.math.unsorted_segment_max
的文档中:
如果给定段ID
i
的最大值为空,则输出该特定数值类型的可能最小值,output[i] = numeric_limits<T>::lowest()
。
- 你指定了3个段,因此输出有3个元素。第一个元素,
i == 0
,对应位置j == [1, 4]
(如segment_ids
中指定),因此data[j] == [0.2, 0.4]
。取max(data[j])
得0.4
。类似地,对于下一段,i == 1
,我们有j == [2, 3]
和data[j] = [0.3, 0.3] => max(data[j]) = 0.3
。对于最后一段,i == 2
,只有单个元素在位置j == 0
,因此结果是0.1
。 - 现在你仍然指定了3个集群,因此输出将有3个元素。段ID
3
似乎被忽略,因为它不符合段的数量(不过在最新版本的tensorflow上应该会引发错误)。关于输出中的最后一个元素,它对应于段i == 2
,没有找到对应的segment_id
,因此结果是特定数值类型的可能最小值;这就是你观察到的:-3.4028235e+38
。 - 与2)类似,区别在于现在段ID
3
生效;这对应于输出的最后一个元素,因此是0.1
。倒数第二个元素,对应段ID 2,仍然没有匹配的ID,因此填充了默认值。 - 对于
tf.math.unsorted_segment_sum
,空段的默认值不同:如果给定段IDi
的和为空,则output[i] = 0
。因此段0
是项目0.2 + 0.4 == 0.6
的和,对于段1是0.3 + 0.3 == 0.6
,对于段2找不到对应的ID,因此默认值为0
,对于段3只有一个元素0.1
。
回答2: segment_ids
的标准是它“前缀”data
的形状,即segment_ids.shape == data.shape[:len(segment_ids.shape)]
,并且max(segment_ids) < num_segments
(在最新版本的tensorflow上)。相应的维度将被缩减为一个单一维度,包含由num_segments
指定的元素数量,而segments_ids
中的值指定输出中的相应段。
回答3: 如果segment_ids
参数不符合要求,将会引发InvalidArgumentError
。你需要修复相应的张量才能使操作工作。