有没有人思考过这么一个问题:
label = torch.Tensor([0, 2, 1]).long()
fc_out = torch.Tensor([
[245, 13., 3.34],
[45., 43., 37.],
[1.22, 35.05, 1.23]
])
def cross_entropy_loss(out, label):
# convert out to softmax probability
out = out.numpy().tolist()
out = np.array([np.exp(i)/np.sum(np.exp(i)) for i in out])
print(out)
loss = torch.nn.CrossEntropyLoss()
# lv = loss(fc_out, label)
lv = cross_entropy_loss(fc_out, label)
print(lv)
我们尝试用np来编写一个CrossEntropy, 实现和pytorch一样的输出. 但是, 遇到一个问题.
其中那行代码:
out = out.numpy().tolist()
如果改为:
out = out.numpy()
则结果不一样. 结果差异如下:
[[1.00000000e+000 1.75258947e-101 1.11788072e-105]
[8.80536902e-001 1.19167711e-001 2.95387223e-004]
[2.03150559e-015 1.00000000e+000 2.05192254e-015]]
a.py:23: RuntimeWarning: overflow encountered in exp
out = np.array([np.exp(i)/np.sum(np.exp(i)) for i in out])
a.py:23: RuntimeWarning: invalid value encountered in true_divide
out = np.array([np.exp(i)/np.sum(np.exp(i)) for i in out])
[[ nan 0.0000000e+00 0.0000000e+00]
[8.8053685e-01 1.1916771e-01 2.9538720e-04]
[2.0315054e-15 1.0000000e+00 2.0519225e-15]]
这不是一个经常会遇到的问题, 但是在实际之中你确实应该思考差异的缘由.
将to_list()
去掉之后, 结果会出现溢出. 这个十分的不对劲.
发生这个现象的根本原因是: list和np里面默认的精度是不一样的. numpy里面是float, list是动态的. float无法表征10-501这么小的数, 因此会溢出.