Как создать нейронную сеть, которая принимает изображение и выводит другое изображение?

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

#python #машинное обучение #pytorch #conv-neural-network

Вопрос:

Я пытаюсь создать нейронную сеть, которая имеет изображение формата L (из Lab) и выводит размеры ab. Я могу передать измерение L без проблем, но у меня возникли проблемы с пониманием того, как выводить размеры ab. Выходные данные должны иметь форму 1x2xHxW, где H и W — высота и ширина входного изображения. Вот моя сеть до сих пор:

 class Model(nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        # Get the resnet18 model from torchvision.model library
        self.model = models.resnet18(pretrained=True)
        
        self.model.conv1 = nn.Conv2d(1, 64, kernel_size=7, stride=2, padding=3, bias=False)

        # Replace fully connected layer of our model to a 2048 feature vector output
        self.model.classifier = nn.Sequential()

        # Add custom classifier layers
        self.fc1 = nn.Linear(1000, 1024)
        self.Dropout1 = nn.Dropout()
        self.PRelU1 = nn.PReLU()

        self.fc2 = nn.Linear(1024, 512)
        self.Dropout2 = nn.Dropout()
        self.PRelU2 = nn.PReLU()

        self.fc3 = nn.Linear(512, 256)
        self.Dropout3 = nn.Dropout()
        self.PRelU3 = nn.PReLU()

        self.fc4 = nn.Linear(256, 313)
        # self.PRelU3 = nn.PReLU()
        
        self.softmax = nn.Softmax(dim=1)
        self.model_out = nn.Conv2d(313, 2, kernel_size=1, padding=0, dilation=1, stride=1, bias=False)
        self.upsample4 = nn.Upsample(scale_factor=4, mode='bilinear')


    def forward(self, x):
        # x is our input data
        x = self.model(x)
        x = self.Dropout1(self.PRelU1(self.fc1(x)))
        x = self.Dropout2(self.PRelU2(self.fc2(x)))
        x = self.Dropout3(self.PRelU3(self.fc3(x)))
        x = self.softmax(self.fc4(x))
        
        return x
 

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

1. Получение изображения, выполнение ваших функций и генерация того же изображения с вашими функциями, выполняемыми на нем, звучит как идеальная задача для autoencoder . Обратитесь к этому: jeremyjordan.me/autoencoders

2. Архитектуры в стиле U-net , вероятно, являются наиболее популярными типами архитектуры для этого. В основном, как сеть автоэнкодера или кодировщика / декодера, но с пропуском соединений между кодировщиком и декодером.

Ответ №1:

Я действительно не знаю, что вы подразумеваете под «размерами ab», и я не уверен, что такое «формат L», но я могу рассказать вам, как использовать cnns для генерации изображений.

Обычно вы используете автоэнкодер, но это зависит от задачи. Автоэнкодер принимает изображение в качестве входных данных и, аналогично обычной классификации, уменьшает размеры. Но, в отличие от классификации, вы не сглаживаете карты объектов и не добавляете слои классификации, а снимаете с них выборки и деконвертируете их. Итак, сначала вы «кодируете» «изображение», а затем «декодируете» его. Средний слой перед началом повышения дискретизации называется узким местом. Нет плотных слоев и не требуется активаций softmax.

Вот пример того, как это будет выглядеть как модель pytorch (автоэнкодер для набора данных cifar10):

 class Model(nn.Module):
    def __init__(self):
        super(Model, self).__init__()

        """ encoder """
        self.conv1 = nn.Conv2d(3, 32, kernel_size=(5, 5))
        self.batchnorm1 = nn.BatchNorm2d(32)

        self.conv2 = nn.Conv2d(32, 64, kernel_size=(4, 4), stride=3)
        self.batchnorm2 = nn.BatchNorm2d(64)

        self.conv3 = nn.Conv2d(64, 128, kernel_size=(3, 3), stride=3)
        self.batchnorm3 = nn.BatchNorm2d(128)

        self.maxpool2x2 = nn.MaxPool2d(2)   # not in usage

        """ decoder """
        self.upsample2x2 = nn.Upsample(scale_factor=2)   # not in usage

        self.deconv1 = nn.ConvTranspose2d(128, 64, kernel_size=(3, 3), stride=3)
        self.batchnorm1 = nn.BatchNorm2d(64)

        self.deconv2 = nn.ConvTranspose2d(64, 32, kernel_size=(4, 4), stride=3)
        self.batchnorm2 = nn.BatchNorm2d(32)

        self.deconv3 = nn.ConvTranspose2d(32, 3, kernel_size=(5, 5))
        self.batchnorm3 = nn.BatchNorm2d(3)
    

    def forward(self, x, train_: bool=True, print_: bool=False, return_bottlenecks: bool=False):

        """ encoder """
        x = self.conv1(x)
        x = self.batchnorm1(x)
        x = F.relu(x)

        x = self.conv2(x)
        x = self.batchnorm2(x)
        x = F.relu(x)

        x = self.conv3(x)
        x = self.batchnorm3(x)
        bottlenecks = F.relu(x)

        """ decoder """
        x = self.deconv1(bottlenecks)
        x = self.batchnorm1(x)
        x = F.relu(x)

        x = self.deconv2(x)
        x = self.batchnorm2(x)
        x = F.relu(x)

        x = self.deconv3(x)
        x = torch.sigmoid(x)

        return x
 

В этом примере я не использую «maxpool» и «upsample», но это зависит от вашей модели.
Upsample по сути, это противоположно maxpool, и вы ConvTranspose2d также можете видеть, что это противоположно свертке (хотя на самом деле это не было бы правильным объяснением).

Итак, вы в основном хотите, чтобы часть «декодера» была противоположной (или зеркальной версией) части «кодировщика». Определение размеров, размеров ядра и т. Д. Для каждого слоя может быть довольно сложным, но вам в основном нужно настроить их так, чтобы архитектура была почти симметричной, а выходные размеры модели соответствовали размеру изображения, которое вы хотите создать.

Вот что может понравиться архитектуре «создания изображений», например:

введите описание изображения здесь

источник: https://www.semanticscholar.org/paper/Feature-discovery-and-visualization-of-robot-data-Flaspohler-Roy/514a2f7461edd3e4c2d56d57f9002e1dc445eb58/figure/1

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

1. Спасибо за отличный ответ! Просто для пояснения, цветовое пространство Lab для изображения разбивает изображение на 3 измерения, где L — интенсивность света (оттенки серого), a для зелено-пурпурного цветового баланса и b для сине-желтого цветового баланса. Итак, в моем случае я ввожу оттенки серого и хочу вывести размеры ab. Следуя вашему примеру, у меня был бы только последний слой с 2 измерениями вместо 3 (как показано на прилагаемом изображении).