PyTorch训练孪生网络时loss.backward()报TypeError错误求助
PyTorch孪生网络训练中loss.backward()触发TypeError问题
错误信息
Traceback (most recent call last): File "/home/xxx/PyProject/image_similarity/Grad_CAM_Siamese/01.Train_Siamese_model.py", line 250, in <module> loss.backward() File "/home/xxx/anaconda3/envs/pytorch_siamese/lib/python3.8/site-packages/torch/_tensor.py", line 487, in backward torch.autograd.backward( File "/home/xxx/anaconda3/envs/pytorch_siamese/lib/python3.8/site-packages/torch/autograd/__init__.py", line 200, in backward Variable._execution_engine.run_backward( # Calls into the C++ engine to run the backward pass TypeError: 'NoneType' object is not callable
相关代码片段
训练循环代码(错误发生行)
for epoch in range(params['hyperparameters']['epochs']): torch.cuda.empty_cache() model.train() loop = tqdm(train_dl, leave=True, ncols=120) metrics = {'losses': []} for step, (img1, img2, img3) in enumerate(loop): img1, img2, img3 = img1.to(device), img2.to(device), img3.to(device) optimizer.zero_grad() loss = model(img1, img2, img3) # 此处尝试获取loss相关信息 loss.backward() # Line250 torch.nn.utils.clip_grad_norm_(parameters=model.parameters(), max_norm=params['hyperparameters']['max_norm']) optimizer.step()
loss相关信息(backward调用前)
tensor(1.0018, device='cuda:3', grad_fn=<MeanBackward0>) # loss值 Loss type: <class 'torch.Tensor'> # loss类型 torch.float32 # loss数据类型
loss计算逻辑
模型内定义损失函数并计算:
self.loss_fnc = TripletLoss(margin=1.0) loss = self.loss_fnc(embeddings_anchor, embeddings_positive, embeddings_negative)
TripletLoss类实现
class TripletLoss(torch.nn.Module): def __init__(self, margin=1.0): super(TripletLoss, self).__init__() self.margin = margin def forward(self, anchor, positive, negative): distance_positive = F.pairwise_distance(anchor, positive) distance_negative = F.pairwise_distance(anchor, negative) losses = torch.mean(F.relu(distance_positive - distance_negative + self.margin)) return losses
环境信息
- Python版本:3.8.17
- PyTorch版本:pytorch2.0.0,torchvision0.15.0,torchaudio==2.0.0,pytorch-cuda=11.7
- CUDA版本:11.7(nvcc -V验证)
- 训练设备:GPU
问题排查与解决方法
针对这个TypeError: 'NoneType' object is not callable错误,结合你的代码和环境,可按以下方向排查:
1. 检查模型中的inplace操作
inplace操作会直接修改张量内存,破坏反向传播的计算图。排查模型所有层:
- 若使用了
F.relu(inplace=True)、torch.nn.ReLU(inplace=True)或其他带inplace=True的操作,改为inplace=False。 - 检查是否有手动修改张量的操作(比如
x += y这种inplace赋值),替换为x = x + y。
2. 验证模型参数与设备一致性
确认模型所有参数都已正确移动到GPU:
- 在初始化模型后,执行
model = model.to(device),确保所有层的参数都在cuda:3上(和loss的设备一致)。 - 检查数据加载时,是否所有输入张量都正确转移到指定设备。
3. 检查PyTorch版本兼容性
PyTorch 2.0.0存在部分已知的反向传播bug,可尝试:
- 降级到PyTorch 1.13.1(兼容CUDA11.7):
pip install torch==1.13.1+cu117 torchvision==0.14.1+cu117 torchaudio==0.13.1 --extra-index-url https://download.pytorch.org/whl/cu117 - 或升级到PyTorch 2.0.1及以上版本,修复已知问题。
4. 确认优化器绑定的参数正确
检查优化器初始化代码,确保传入的是model.parameters(),没有传入无关参数或未注册的张量:
optimizer = torch.optim.Adam(model.parameters(), lr=params['hyperparameters']['lr'])
5. 排查计算图是否被意外中断
虽然loss有grad_fn,但仍需确认模型前向传播中没有意外断开计算图:
- 检查是否在模型前向传播中使用了
detach()或torch.no_grad()(除非是刻意冻结部分层)。 - 确认TripletLoss中的所有张量操作都在计算图内,没有手动脱离梯度追踪。
6. 重置PyTorch的execution_engine
若上述方法无效,可尝试在代码开头添加以下代码,重置execution_engine:
import torch torch._C._jit_set_profiling_executor(False) torch._C._jit_set_profiling_mode(False)
内容的提问来源于stack exchange,提问作者What_How_Why
相关产品推荐
相关产品推荐

