yolov8adversarial-attack

Extracting YOLOv8 backbone weights


I'm trying to extract the classification backbone from my YOLOv8 model. I saw an issue on the official Ultralytics repository about that but when I tried the method mentioned it didn't work. Here's the link for the issue

What I want to do is extract the weights of the backbone and then use it as if it was a classification model to perform FGSM attack because I tried to do it on the whole model it didn't work even after I extracted class logits from yolo using pytorch hooks

import torch
import torch.nn as nn
from ultralytics import YOLO  

# Step 1: Load trained YOLOv8 model
model = YOLO('/content/best.pt') 
image = '/content/stop.png'

# Step 2: Extract the backbone (CSPDarknet53)
backbone = model.model[0] 
labels = torch.tensor([22])

num_classes = 29  
classify_model = nn.Sequential(
    backbone,  # Use the CSPDarknet53 backbone
    nn.AdaptiveAvgPool2d((1, 1)),  # Global Average Pooling to reduce to (batch_size, channels, 1, 1)
    nn.Flatten(),  # Flatten to (batch_size, channels)
    nn.Linear(in_features=backbone[-1].out_channels, out_features=num_classes)  # Linear layer for classification
)

# Example FGSM attack
def fgsm_attack(model, images, labels, epsilon):
    images.requires_grad = True
    outputs = model(images)
    loss = nn.CrossEntropyLoss()(outputs, labels)
    model.zero_grad()
    loss.backward()  # Compute gradients with respect to input images
    grad_sign = images.grad.data.sign()
    perturbed_image = images + epsilon * grad_sign  # Apply perturbation
    return perturbed_image

# apply FGSM on `classify_model`
perturbed_image = fgsm_attack(classify_model, image, labels, 0.3)

But I get this error 'TypeError: 'DetectionModel' object is not subscriptable'

I tried to do FGSM on the whole model it didn't work even after I extracted class logits from yolo using pytorch hooks. I also tried to extract YOLOv8 backbone and use it as a classification model but this also is not working.


Solution

  • Try this solution to extract the YOLOv8 backbone in your code:

    # Step 2: Extract the backbone (CSPDarknet53)
    backbone = model.model.model[:10]
    

    First, instead of just model.model go deeper into the model structure to avoid the 'TypeError: 'DetectionModel' object is not subscriptable' error. Let's see in detail what we have and what we need here.

    Look for instance at the model = YOLO('yolov8n.pt') object:

    model = YOLO('yolov8n.pt')
    print(model)
    
    # OUTPUT
    '''
    YOLO(
      (model): DetectionModel(
        (model): Sequential(
          (0): Conv(
            (conv): Conv2d(3, 16, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
            (bn): BatchNorm2d(16, eps=0.001, momentum=0.03, affine=True, track_running_stats=True)
            (act): SiLU(inplace=True)
          )
          (1): Conv(
            (conv): Conv2d(16, 32, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
            (bn): BatchNorm2d(32, eps=0.001, momentum=0.03, affine=True, track_running_stats=True)
            (act): SiLU(inplace=True)
          )
    ...
            (dfl): DFL(
              (conv): Conv2d(16, 1, kernel_size=(1, 1), stride=(1, 1), bias=False)
            )
          )
        )
      )
    )
    '''
    

    We need to reach these enumerated modules (0, 1 ...) which are the elements of the Sequential container. So, let's see where it lies:

    type(model)
    
    # OUTPUT
    ultralytics.models.yolo.model.YOLO
    <...>
    YOLO (You Only Look Once) object detection model.
    
    type(model.model)
    
    # OUTPUT
    ultralytics.nn.tasks.DetectionModel
    <...>
    YOLOv8 detection model.
    
    type(model.model.model)
    
    # OUTPUT
    torch.nn.modules.container.Sequential
    A sequential container.
    

    Here it is, so the simplified view of the model is the following, and we need to call model.model.model[:] to reach all the numerated blocks.

    YOLO(
        DetectionModel(
            Sequential(
                0: Conv, 
                1: Conv, 
                2, 
                3,
                ...
            )
        )
    )
    

    Second, if you look at the model's structure, the backbone is the first 10 layers of the model (0-9), not just the first one. Here comes the final solution backbone = model.model.model[:10].