Как использовать Pytorch для создания пользовательской эффективной сети с корректно написанным последним слоем

#machine-learning #deep-learning #pytorch #classification #conv-neural-network

#машинное обучение #глубокое обучение #pytorch #классификация #conv-нейронная сеть

Вопрос:

У меня есть проблема с классификацией, чтобы предсказать, например, 8 классов, которые я использую EfficientNetB3 в pytorch отсюда. Однако я запутался в том, правильно ли написан мой пользовательский класс. Я думаю, что хочу удалить последний слой предварительно обученной модели, чтобы соответствовать 8 выходам правильно? Правильно ли я это сделал? Потому что, когда я печатаю y_preds = model(images) в my DataLoader , мне кажется, что он дает мне 1536 прогнозы. Это ожидаемое поведение?

 !pip install geffnet 
import geffnet

class EfficientNet(nn.Module):
    def __init__(self, config):
        super().__init__()
        self.config = config
        self.model = geffnet.create_model(config.effnet, pretrained=True)
        n_features = self.model.classifier.in_features
        # does the name fc matter?
        self.fc = nn.Linear(n_features, config.num_classes)
        self.model.classifier = nn.Identity()
        
    def extract(self, x):
        x = self.model(x)
        return x

    def forward(self, x):
        x = self.extract(x).squeeze(-1).squeeze(-1)
        return x
    
model = EfficientNet(config=config)
if torch.cuda.is_available():
    model.cuda()
 

Пример кода для печати y_pred :

device = torch.device(‘cuda’, если torch.cuda.is_available() иначе ‘cpu’)

 for step, (images, labels) in enumerate(sample_loader):
    images = images.to(device)
    labels = labels.to(device)
    batch_size = images.shape[0]        
    y_preds = model(images)
    print('The predictions of the 4 images is as followsn', y_preds)
    break
 

Ответ №1:

Вы даже не используете self.fc прямой проход.

Либо просто представьте его как:

 def forward(self, x):
    ....
    x = extract(x)...
    x = fc(x)
    return x
 

Или вы можете просто заменить слой с именем classifier (таким образом, вам не нужен слой идентификации):

 self.model.classifier = nn.Linear(n_features, config.num_classes)
 

Кроме того, здесь config.num_classes должно быть 8.

Комментарии:

1. Большое спасибо за объяснение, еще один вопрос, если можно, зачем нам это нужно self.extract(x).squeeze(-1).squeeze(-1) на forward проходе, почему мы не можем просто сказать: x = self.model(x) и удалить extract метод?

2. torch.squeeze удаляет дополнительное измерение 1, оно здесь не нужно. вы можете напрямую вызвать self.model(x) . Я не знаю, почему вы использовали его в первую очередь.

3. Спасибо за ответ, ценю его. Когда вы хотели бы использовать squeeze tho? Как я видел, некоторые люди это делали.

4. Иногда вы можете получить дополнительные измерения, такие как (1, 1, 3, 224, 224), чтобы сделать его совместимым с другими операциями, которые могут работать только с 4 измерениями, вы можете использовать squeeze . Вы также, вероятно, использовали unsqeeze() бы, например, перед подачей одного тензора изображения размером (3, 224, 224) для моделирования таким образом, чтобы его размер стал (1, 3, 224, 224), поскольку pytorch требует формы как [N, C,H, W], где N — batch_size .

5. Кристально ясное объяснение. Я бы проголосовал за вас дважды, если бы мог.