在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。你需要修复相应的张量才能使操作工作。