一次pytorch中出现的nan问题

博客讲述了在PyTorch中遇到loss变为nan的问题,经过排查发现是由于负数开方操作导致。文章指出,数学上虽然负数的某些次方有实数解,但在Python和PyTorch中会得到虚数或nan。通过举例说明了(-27)**(1/3)的结果,并提出解决方案:在开方前确保数值为正或者对负数进行特殊处理。建议在计算时要避免负数开方,以免出现nan错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

nan排查

最近调试代码时,发现一个loss全部变为nan。网上主流的解释大多千篇一律,比如

1.学习率太高。

2.loss函数

3.对于回归问题,可能出现了除0 的计算,加一个很小的余项可能可以解决

4.数据本身,是否存在Nan,可以用numpy.any(numpy.isnan(x))检查一下input和target
...

我这儿问题可以确定,是由于数学运算造成的nan。最后具体定位到,是由于一个池化操作造成的。在pycharm中单步调试,使用如下表达式判断x中是否有nan,因为nan!=nan结果是True,而其他任何实数!=实数本身结果均为False

torch.sum(x!=x)
torch.sum(x[:1000] != x[:1000])  # 依次这样二分法查找第一次出现nan的那个位置

最后发现是对负数开方将会产生nan,如下

p = 3.
 x_i = (torch.mean(x_i**p, dim=-1) + 1e-12)**(1/p) # 如果x_i中有负数,那么开方之后,对应位置就会为nan

解释

主流的计算器,编程语言均是不支持负数的开方的,即便是数学上成立,计算器还是会给出虚数解, 对于pytorch来说,就成了nan。比如:

>>>(-27)**(1/3)
(1.5000000000000004+2.598076211353316j)

-27的1/3次是存在实数解的,但是计算结果还是一个虚数解。所以以后要开方的话,一定要对负数特别处理,比如把负号拿出来:

>>>-(1)**(1/3)
-1.0
>>>-(27)**(1/3)
-3.0

这篇博文也提到了python中这个问题,实际上一般的计算器也是这样的。

您可以使用PyTorch实现性别识别。首先,您需要准备一个包含男性和女性图像的数据集。然后,您可以使用PyTorch构建一个卷积神经网络(CNN)模型,并使用该数据集对其进行训练。在训练完成后,您可以使用该模型对新的图像进行性别识别。 以下是一个简单的PyTorch CNN模型示例: ```python import torch.nn as nn import torch.nn.functional as F class GenderClassifier(nn.Module): def __init__(self): super(GenderClassifier, self).__init__() self.conv1 = nn.Conv2d(3, 16, 3, padding=1) self.conv2 = nn.Conv2d(16, 32, 3, padding=1) self.conv3 = nn.Conv2d(32, 64, 3, padding=1) self.pool = nn.MaxPool2d(2, 2) self.fc1 = nn.Linear(64 * 8 * 8, 512) self.fc2 = nn.Linear(512, 2) def forward(self, x): x = self.pool(F.relu(self.conv1(x))) x = self.pool(F.relu(self.conv2(x))) x = self.pool(F.relu(self.conv3(x))) x = x.view(-1, 64 * 8 * 8) x = F.relu(self.fc1(x)) x = self.fc2(x) return x ``` 在训练模型之前,您需要定义损失函数和优化器。对于二分类问题,您可以使用二元交叉熵损失函数,并使用随机梯度下降(SGD)优化器进行优化。 ```python import torch.optim as optim criterion = nn.CrossEntropyLoss() optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9) ``` 接下来,您可以使用数据集对模型进行训练。以下是一个简单的训练循环示例: ```python for epoch in range(10): # 训练10个epoch running_loss = 0.0 for i, data in enumerate(trainloader, 0): inputs, labels = data optimizer.zero_grad() outputs = net(inputs) loss = criterion(outputs, labels) loss.backward() optimizer.step() running_loss += loss.item() if i % 2000 == 1999: # 每2000个batch打印一次loss print('[%d, %5d] loss: %.3f' % (epoch + 1, i + 1, running_loss / 2000)) running_loss = 0.0 ``` 在训练完成后,您可以使用测试集对模型进行评估。以下是一个简单的评估循环示例: ```python correct = 0 total = 0 with torch.no_grad(): for data in testloader: images, labels = data outputs = net(images) _, predicted = torch.max(outputs.data, 1) total += labels.size(0) correct += (predicted == labels).sum().item() print('Accuracy of the network on the test images: %d %%' % ( 100 * correct / total)) ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值