自定义pytorch损失函数使得训练过程中出现nan

问题:

BCE的定义:-ylogp - (1-y)log(1-p),而如果我们用下面这种方式写出来:

loss = - target * torch.log(pred) - (1-target) * torch.log(1-pred)

可能会出现损失函数nan和inf的情况。

我自定义一个加权的BCE损失的时候就出现这个问题,于是查找pytorch官方的BCE文档,发现这样一句话:
Our solution is thatBCELoss clamps its log function outputs to be greater than or equal to -100. This way, we can always have a finite loss value and a linear backward method.

大意:就是进行了截断,来防止log()计算的时候可能出现问题,因为对于一个很小的数x而言(刚开始训练,可能predict的值相当大或小),虽然理论上log(x)是能计算的,但是计算机有精度限制,所以没法实现这么理想的情况。所以会出现nan和inf的情况,这样导致梯度无法回传。

解决方法:

加入一个截断:

pred = torch.clamp(pred, min=1e-7, max=1-1e-7)
loss = - target * torch.log(pred) - (1-target) * torch.log(1-pred)

如果截断范围是[1e-8, 1-1e-8],nan和inf还是会出现,所以就用1e-7了,而且与原生的BCELoss效果基本一致,差异在1e-3以下的量级。

你可能感兴趣的:(深度学习,深度学习)