Pytorch: Несоответствие размера во время запуска тестового изображения через обученный CNN - PullRequest
0 голосов
/ 17 сентября 2018

Я прохожу учебные пособия для обучения / тестирования сверточной нейронной сети (CNN), и у меня возникла проблема с подготовкой тестового изображения для запуска его через обученную сеть.Мое первоначальное предположение состоит в том, что это имеет отношение к правильному формату тензорного ввода для сети.

Вот код для сети.

import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.nn.init as I


class Net(nn.Module):

def __init__(self):
    super(Net, self).__init__()

    ## 1. This network takes in a square (same width and height), grayscale image as input
    ## 2. It ends with a linear layer that represents the keypoints
    ## this last layer output 136 values, 2 for each of the 68 keypoint (x, y) pairs

    # input size 224 x 224 
    # after the first conv layer, (W-F)/S + 1 = (224-5)/1 + 1 = 220 
    # after one pool layer, this becomes (32, 110, 110)
    self.conv1 = nn.Conv2d(1, 32, 5)

    # maxpool layer 
    # pool with kernel_size = 2, stride = 2
    self.pool = nn.MaxPool2d(2,2)

    # second conv layer: 32 inputs, 64 outputs , 3x3 conv
    ## output size = (W-F)/S + 1 = (110-3)/1 + 1 = 108
    ## output dimension: (64, 108, 108)
    ## after another pool layer, this becomes (64, 54, 54)
    self.conv2 = nn.Conv2d(32, 64, 3)

    # third conv layer: 64 inputs, 128 outputs , 3x3 conv
    ## output size = (W-F)/S + 1 = (54-3)/1 + 1 = 52
    ## output dimension: (128, 52, 52)
    ## after another pool layer, this becomes (128, 26, 26)
    self.conv3 = nn.Conv2d(64,128,3)

    self.conv_drop = nn.Dropout(p = 0.2)
    self.fc_drop = nn.Dropout(p = 0.4)

    # 64 outputs * 5x5 filtered/pooled map  = 186624
    self.fc1 = nn.Linear(128*26*26, 1000)
    #
    self.fc2 = nn.Linear(1000, 1000)

    self.fc3 = nn.Linear(1000, 136)



def forward(self, x):
    x = self.pool(F.relu(self.conv1(x)))
    x = self.pool(F.relu(self.conv2(x)))
    x = self.pool(F.relu(self.conv3(x)))
    x = self.conv_drop(x)

    # prep for linear layer
    # flattening 
    x = x.view(x.size(0), -1) 

    # two linear layers with dropout in between
    x = F.relu(self.fc1(x))
    x = self.fc_drop(x)
    x = self.fc2(x)
    x = self.fc_drop(x)
    x = self.fc3(x) 

    return x

Может быть, мои вычисления на входах слоя неверны?

А вот блок кода для запуска теста: (вы можете думать о 'roi' как о стандартном numpy изображении.)

# loop over the detected faces from your haar cascade
for i, (x,y,w,h) in enumerate(faces):

    plt.figure(figsize=(10,5))
    ax = plt.subplot(1, len(faces), i+1)
    # Select the region of interest that is the face in the image 
    roi = image_copy[y:y+h, x:x+w]

    ## TODO: Convert the face region from RGB to grayscale
    roi = cv2.cvtColor(roi, cv2.COLOR_RGB2GRAY)

    ## TODO: Normalize the grayscale image so that its color range falls in [0,1] instead of [0,255]
    roi = np.multiply(roi, 1/255)

    ## TODO: Rescale the detected face to be the expected square size for your CNN (224x224, suggested)
    roi = cv2.resize(roi, (244,244))

    roi = roi.reshape(roi.shape[0], roi.shape[1], 1)
    roi = roi.transpose((2, 0, 1))

    ## TODO: Change to tensor
    roi = torch.from_numpy(roi)
    roi = roi.type(torch.FloatTensor)
    roi = roi.unsqueeze(0)
    print (roi.shape)

    ## TODO: run it through the net 
    output_pts = net(roi)

И я получаю сообщение об ошибке:

RuntimeError: size mismatch, m1: [1 x 100352], m2: [86528 x 1000] at /opt/conda/conda-bld/pytorch_1524584710464/work/aten/src/TH/generic/THTensorMath.c:2033

Предостережение: если я запускаю свою обученную сеть в предоставленном наборе тестов (где уже введены тензорные входы), он не выдает там ошибок и работает так, как должен.Я думаю, это означает, что нет ничего плохого в дизайне самой сетевой архитектуры.Я думаю, что что-то не так с тем, как я подготавливаю изображение.

Вывод 'roi.shape' таков:

torch.Size([1, 1, 244, 244]) 

Что должно быть хорошо, потому что ([batch_size,color_channel, x, y]).

ОБНОВЛЕНИЕ: Я распечатал форму слоев во время работы через сеть.Оказывается, совпадающие входные размеры для FC различны для тестового изображения для задачи и заданных тестовых изображений из набора тестов.Тогда я почти на 80% уверен, что моя предварительная подготовка входного изображения для сети неверна.Но как они могут иметь разные совпадающие измерения, если входной тензор для обоих имеет точное одинаковое измерение ([1,1244,244])?

при использовании предоставленного набора тестов (где он работает нормально):

input: torch.Size([1, 1, 224, 224])
layer before 1st CV: torch.Size([1, 1, 224, 224])
layer after 1st CV pool: torch.Size([1, 32, 110, 110])
layer after 2nd CV pool: torch.Size([1, 64, 54, 54])
layer after 3rd CV pool: torch.Size([1, 128, 26, 26])
flattend layer for the 1st FC: torch.Size([1, 86528])

При подготовке / запуске тестового изображения:

input: torch.Size([1, 1, 244, 244])
layer before 1st CV: torch.Size([1, 1, 244, 244])
layer after 1st CV pool: torch.Size([1, 32, 120, 120]) #<- what happened here??
layer after 2nd CV pool: torch.Size([1, 64, 59, 59])
layer after 3rd CV pool: torch.Size([1, 128, 28, 28])
flattend layer for the 1st FC: torch.Size([1, 100352])

1 Ответ

0 голосов
/ 30 декабря 2018

Вы заметили, что у вас есть эта строка в подготовке изображения.

## TODO: Rescale the detected face to be the expected square size for your CNN (224x224, suggested)
roi = cv2.resize(roi, (244,244))

так что вы просто изменили его размер до 244x244, а не до 224x224.

...