Получение выходного размера слоя CNN в def init PyTorch

#python #machine-learning #deep-learning #neural-network #pytorch

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

Вопрос:

При определении нашей архитектуры модели в PyTorch нам нужно указать размер выходного слоя CNN для загрузки в nn.Linear слой. Как мы можем найти размер этого слоя в def __init__ функции (не в def forward() )

 class model(nn.Module):

    def __init__(self,word_count,img_channel,n_out):
        super(multimodal,self).__init__()

        # CNN image encoding hyperparameters
        conv1_channel_out = 8
        conv1_kernel = 5

        pool1_size = 2

        conv2_channel_out = 16
        conv2_kernel = 16

        pool2_size = 2

        conv3_channel_out = 32
        conv3_kernel = 4

        dropout_rate = 0.1

        cnn_fc_out = 512

        comb_fc1_out = 512
        comb_fc2_out = 128

        # FNN text encoding hyperparameters
        text_fc1_out = 4096
        text_fc2_out = 512


        # Text encoding
        self.text_fc1 = nn.Linear(word_count, text_fc1_out)
        self.text_fc2 = nn.Linear(text_fc1_out, text_fc2_out)


        # Image encoding
        self.conv1 = nn.Conv2d(img_channel, conv1_channel_out, conv1_kernel)
        self.max_pool1 = nn.MaxPool2d(pool1_size)
        self.conv2 = nn.Conv2d(conv1_channel_out, conv2_channel_out, conv2_kernel)
        self.max_pool2 = nn.MaxPool2d(pool2_size)
        self.conv3 = nn.Conv2d(conv2_channel_out, conv3_channel_out, conv3_kernel)

        self.cnn_dropout = nn.Dropout(dropout_rate)
        self.cnn_fc = nn.Linear(32*24*12, cnn_fc_out)

        #Concat layer
        concat_feat = cnn_fc_out   text_fc2_out
        self.combined_fc1 = nn.Linear(concat_feat, comb_fc1_out)
        self.combined_fc2 = nn.Linear(comb_fc1_out, comb_fc2_out)
        self.output_fc = nn.Linear(comb_fc2_out, n_out)


    def forward(self, text, img):
        # Image Encoding
        x = F.relu(self.conv1(img))
        x = self.max_pool1(x)
        x = F.relu(self.conv2(x))
        x = self.max_pool2(x)
        x = F.relu(self.conv3(x))
        x = x.view(-1, 32*24*12)
        x = self.cnn_dropout(x)
        img = F.relu(self.cnn_fc(x))

        # Text Encoding
        text = F.relu(self.text_fc1(text))
        text = F.relu(self.text_fc2(text))

        # Concat the features
        concat_inp = torch.cat((text, img), 1)
        out = F.relu(self.combined_fc1(concat_inp))
        out = F.relu(self.combined_fc2(out))
        return torch.sigmoid(self.output_fc(out))
 

Если вы видите выше, я определяю размер выходного слоя CNN как 32 24 12 вручную
self.cnn_fc = nn.Linear(32*24*12, cnn_fc_out)

Как я могу этого избежать? Я знаю, что мы могли бы вызвать [model_name].[layer_name].in_features def forward() , но не в def __init__()

Ответ №1:

Я не думаю, что есть конкретный способ сделать это. Вам нужно будет запустить образец (вы можете просто использовать x = torch.rand((1, C, W, H)) для тестирования), а затем распечатать форму слоя conv прямо перед вашим линейным слоем, затем вы запоминаете это число и жестко кодируете его в init. Или вы можете использовать формулы для вычисления формы слоя conv на основе размеров входных данных, размера ядра, заполнения и т.д. Вот тема об этих формулах.

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

1. Да, это возможные решения, которые я могу придумать на данный момент. Спасибо!

Ответ №2:

Общего способа сделать это нет, поскольку размеры ввода и вывода не являются фиксированными в CNN. Что вы можете вывести, так это количество каналов, но модуль будет принимать и преобразовывать любые размеры изображения по высоте и ширине (при условии, что они достаточно велики, чтобы выдавать результаты, достаточно большие для следующего слоя после незакрепленных сверток, объединения и т. Д.).

Следовательно, вы не можете включить это в init (наивный для ввода, создание экземпляра объекта), только в forward (вычисляется при просмотре ввода).