【问题标题】:Why does Tensorflow cast int32/int32 to float64 and how to stop it?为什么 Tensorflow 将 int32/int32 转换为 float64 以及如何阻止它?
【发布时间】:2019-06-05 09:26:07
【问题描述】:

我将一个 int32 类型的张量除以一个 int32 类型的张量,结果是 float64。我找不到关于为什么会发生这种情况的答案,或者 Tensorflow 如何做到这一点背后是否有隐含的规则。我没有为任何张量明确定义 dtype,但我已经检查了所有张量,并且在除法之后它们都没有 64 位类型。

我尝试过使用不同的除法公式,例如 tf.divide,都给出了相同的结果。

我的代码如下:

a_cdf = a / tf.size(a)

具有 tf.int32 类型的存在。

我想要得到的是 float32 的结果,所以我可以在没有显式转换的情况下编写我的函数。

【问题讨论】:

  • 我正在尝试复制您的问题,但我收到了TypeError: x and y must have the same dtype, got tf.float32 != tf.int32。你能发布一个我们可以处理的独立示例吗?
  • 你在使用 Eager 模式吗?
  • 这很尴尬,都是int32类型。我编辑了这个问题。我没有使用 Eager 模式,但我使用的是 tf nightly 1.14,如果这会改变的话。

标签: tensorflow implicit-conversion


【解决方案1】:

这是设计使然。 TensorFlow中的“真”除法(即实除法)使用_TRUEDIV_TABLE指定每种类型的转换规则,目前为:

# Conversion table for __truediv__.  None entries mean no conversion required.
_TRUEDIV_TABLE = {
    dtypes.uint8: dtypes.float32,
    dtypes.int8: dtypes.float32,
    dtypes.uint16: dtypes.float32,
    dtypes.int16: dtypes.float32,
    dtypes.int32: dtypes.float64,
    dtypes.int64: dtypes.float64,
    dtypes.bfloat16: None,
    dtypes.float16: None,
    dtypes.float32: None,
    dtypes.float64: None,
    dtypes.complex64: None,
    dtypes.complex128: None,
}

这意味着int32 张量将被转换为float64。如果您想获得 float32 作为输出,请使用较小的 int 类型或将您的输入转换为 float32

这样做的理由是另一回事。如果我不得不猜测,一方面我会说如果您使用 8 位或 16 位整数,您可能会担心内存,因此较小的结果类型是有意义的。而且,你可以给出以下论点:

import numpy as np

# Compute smallest positive divisions with 16 and 32 bits
smallest_16bit_fraction = 1 / ((1 << 16) - 1)
smallest_32bit_fraction = 1 / (-(1 << 31))  # 31 bits because int32 is signed
# Compute one plus the smallest fractions with 32 and 64 bit floats
print(np.float32(1) + np.float32(smallest_16bit_fraction))
# 1.0000153
print(np.float64(1) + np.float64(smallest_16bit_fraction))
# 1.0000152590218967
print(np.float32(1) + np.float32(smallest_32bit_fraction))
# 1.0
print(np.float64(1) + np.float64(smallest_32bit_fraction))
# 0.9999999995343387

因此,您可能会认为,作为两个整数值的除法,您可能希望将结果与整数混合,但正如您所见,对于 32 位整数,存在 32 位浮点数会下溢的情况。

但同样,这只是猜测,更像是一种思考练习。

【讨论】:

  • 感谢您的详细回复!这可能完全是另一个问题,但是转换结果是否会使 TFs 自分化更糟?
  • @Olfway Mmh,好吧,我不明白为什么/如何铸造会影响自微分(精度除外),但无论如何,微分只针对实际值定义。如果您的计算中有整数,则梯度不会通过它们传播。
  • 我不知道!在计算中使用它之前转换整数会改变吗?
  • @Olfway 这完全取决于您要计算的梯度。如果您有一个整数类型的tf.Variable,您将无法使用优化器对其进行更新,因为无法为它计算梯度。如果你有一个浮点变量v 和一个整数值i 并且你计算v * tf.cast(i, tf.float32),那么梯度会反向传播到v(只是不要反向传播超过i)。
  • @Olfway 嗯,到底是什么信息?我不确定是否有任何文档明确表示您无法计算整数的梯度,我想这只是隐含的假设,因为梯度的概念不能真正应用于整数。您可以深入研究梯度注册表以查看哪些操作具有梯度,但这并不能说明全部情况,因为它取决于 dtype。所以通常最简单的事情就是做这个操作,看看tf.gradients是否变成None
猜你喜欢
  • 1970-01-01
  • 2011-03-02
  • 1970-01-01
  • 1970-01-01
  • 2011-03-01
  • 2011-08-27
  • 1970-01-01
  • 2023-02-07
相关资源
最近更新 更多