Faster-RCNN with nn.CrossEntopyLoss:为什么即使在 loss.backward() 之后 tensor.grad = None?

时间:2021-07-27 03:47:21

标签: gradient object-detection loss-function loss faster-rcnn

总结:我的项目是尝试从各个角度测试对对象检测模型的 3D 对抗性攻击,我目前正在尝试获得模型纹理的累积梯度。我的方法是使用 torch.nn.CrossEntropyLoss() 来计算带有 loss.backward() 的纹理张量的损失。然后,我将获取纹理张量的梯度并将其添加到名为 accum_texture_grad 的值上。如果这是我通过循环的第一次迭代,它只会将 accum_texture_grad 的值设置为 texture_tensor.grad。

我的主要问题是,即使在调用 loss.backward() 之后,texture_tensor.grad 的值仍然为 None。因此,由于错误“AttributeError: 'NoneType' object has no attribute 'data'”,我无法设置累积纹理梯度值。有没有另一种方法可以让 texture_tensor.grad 获得一个值,或者以其他方式让累积的纹理渐变起作用?

基于 StackOverflow 上的类似问题,我尝试了一些解决方案。我已经测试过是否是纹理张量不是叶子的问题,或者损失值的 grad_fn 是否不正确。当我尝试打印这些值时,texture_tensor.is_leaf 为 True,并且打印损失显示 grad_fn 为 NllLossBackward,这应该是正确的。

此处显示了我当前代码的一些重要片段。

#(imports)
model = models.detection.fasterrcnn_resnet50_fpn(pretrained=True)
#model = models.inception_v3(pretrained=True)

#Sets model to evaluation mode (results in layers/parts of model behaving differently such as BatchNorm layers)
model.eval()

# Defining a function for get a prediction result from the model

def get_prediction(img_path, threshold):
  img = Image.open(img_path) # Load the image
  print(type(img))
  transform = tr.Compose([tr.ToTensor()]) # Defing PyTorch Transform
  #model(img.tensors)
  #img= model.transform(img)
  img = transform(img) # Apply the transform to the image
  print(type(img))
  pred = model([img]) # Pass the image to the model
  print(pred)
  pred_class = [COCO_INSTANCE_CATEGORY_NAMES[i] for i in list(pred[0]['labels'].numpy())] # Get the Prediction Score
  pred_boxes = [[(i[0], i[1]), (i[2], i[3])] for i in list(pred[0]['boxes'].detach().numpy())] # Bounding boxes
  pred_score = list(pred[0]['scores'].detach().numpy())
  true_pred_score = [pred_score]
  global pred_tensor
  pred_tensor = torch.tensor(true_pred_score).requires_grad_()
  pred_t = [pred_score.index(x) for x in pred_score if x > threshold][-1] # Get list of index with score greater than threshold.
  pred_boxes = pred_boxes[:pred_t+1]
  pred_class = pred_class[:pred_t+1]
  return pred_boxes, pred_class

# Defining a api function for object detection

def object_detection_api(img_path, threshold=0.5, rect_th=3, text_size=1.5, text_th=3):
 
  boxes, pred_cls = get_prediction(img_path, threshold) # Get predictions
  img = cv2.imread(img_path) # Read image with cv2
  img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # Convert to RGB
  for i in range(len(boxes)):
    cv2.rectangle(img, boxes[i][0], boxes[i][1],color=(0, 255, 0), thickness=rect_th) # Draw Rectangle with the coordinates
    cv2.putText(img,pred_cls[i], boxes[i][0],  cv2.FONT_HERSHEY_SIMPLEX, text_size, (0,255,0),thickness=text_th) # Write the prediction class
    class_arr.append(pred_cls[i])
  plt.figure(figsize=(15,20)) # display the output image
  plt.imshow(img)
  plt.xticks([])
  plt.yticks([])
  plt.show()

target = Variable(torch.LongTensor([true_num_target]), requires_grad=False)
target = target.to(device)

#...(skipping to loss section)


  #Calculate the loss
  loss_fun = torch.nn.CrossEntropyLoss()
  loss = loss_fun(pred_tensor, target)

  #Calculate gradients of model in backward pass
  loss.backward()
          
  #Collect datagrad and accumulate
  if accum_texture_grad is None:
    print('LOSS')
    print(loss)
    print('IS LEAF')
    print(texture_tensor.is_leaf)
    print('DATA')
    print(texture_tensor.data)
    print('GRAD')
    print(texture_tensor.grad)

    accum_texture_grad = texture_tensor.grad.data.detach().clone()
  else:
    accum_texture_grad += texture_tensor.grad.data.detach().clone()

谢谢,如果需要任何其他信息,请随时告诉我。

0 个答案:

没有答案