我尝试计算 dtype
float32
的张量与 dtype uint8
的张量之间的损失。
由于损失函数执行自动类型提升,所以我一开始没有显式进行类型转换。
这是代码:
import torch
import torch.nn as nn
a = torch.randn(3, 3, dtype=torch.float32, requires_grad=True)
b = torch.randint(0, 256, (3, 3), dtype=torch.uint8)
loss = nn.MSELoss()(a, b)
print(loss.dtype)
loss.backward()
输出:
torch.float32
从我的角度来看,这意味着自动类型促销按预期工作。
但是,出现错误:
Traceback (most recent call last):
File "/root/.../test.py", line 8, in <module>
loss.backward()
File "/root/.../python3.8/site-packages/torch/_tensor.py", line 522, in backward
torch.autograd.backward(
File "/root/.../python3.8/site-packages/torch/autograd/__init__.py", line 266, in backward
Variable._execution_engine.run_backward( # Calls into the C++ engine to run the backward pass
RuntimeError: Found dtype Byte but expected Float
然后我改变了关于损失的台词:
# loss = nn.MSELoss()(a, b)
loss = nn.MSELoss()(a, b.to(torch.float32))
它有效。
但是为什么呢?
我还注意到,在'b'的定义中,我无法设置
requires_grad=True
,因为它会引发错误:
运行时错误:只有浮点和复杂数据类型的张量才需要梯度
我认为也许与我的主要问题有一些联系,所以我将其包含在这里。
那么,dtype uint8 的张量可以用于损失函数吗?稍后会调用
.backward()
?
答案是“有点”。整数张量可用于损失函数,例如用于分类结果的损失函数(有关示例,请参见here)。然而,它们不能用作要优化的参数。这是因为整数的导数没有明确定义。导数捕捉输入的无穷小变化对输出的影响。但无穷小的变化不适用于整数;最小可能的变化是 1(或 -1)。