Как загрузить изображение и преобразовать его в правильный тензор для PyTorch? - PullRequest
0 голосов
/ 19 мая 2018

Я пытаюсь загрузить некоторые файлы изображений (JPG-файлы) с некоторыми метками и передать их в сверточную нейронную сеть (CNN) в PyTorch, следуя примеру здесь .Тем не менее, похоже, что нет приличных сквозных обучающих программ .Проблема, с которой я сталкиваюсь, заключается в следующем.

RuntimeError: thnn_conv2d_forward is not implemented for type
torch.ByteTensor

Мой Dataset выглядит следующим образом.

class ImageData(Dataset):
    def __init__(self, width=256, height=256, transform=None):
        self.width = width
        self.height = height
        self.transform = transform
        y, x = get_images() #y is a list of labels, x is a list of file paths
        self.y = y
        self.x = x

    def __getitem__(self, index):
        img = Image.open(self.x[index]) # use pillow to open a file
        img = img.resize((self.width, self.height)) # resize the file to 256x256
        img = img.convert('RGB') #convert image to RGB channel
        if self.transform is not None:
            img = self.transform(img)

        img = np.asarray(img).transpose(-1, 0, 1) # we have to change the dimensions from width x height x channel (WHC) to channel x width x height (CWH)
        img = torch.from_numpy(np.asarray(img)) # create the image tensor
        label = torch.from_numpy(np.asarray(self.y[index]).reshape([1, 1])) # create the label tensor
        return img, label

    def __len__(self):
        return len(self.x)

CNN взята из здесь имодифицируется для обработки NCWH (пакет х канал х ширина х высота) следующим образом.

class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(3, 256, 256)
        self.pool = nn.MaxPool2d(2, 2)
        self.conv2 = nn.Conv2d(6, 16, 5)
        self.fc1 = nn.Linear(16 * 5 * 5, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)

    def forward(self, x):
        x = self.pool(F.relu(self.conv1(x)))
        x = self.pool(F.relu(self.conv2(x)))
        x = x.view(-1, 16 * 5 * 5)
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x

Цикл обучения также взят из того же учебника и выглядит следующим образом.

for epoch in range(2):  # loop over the dataset multiple times

    running_loss = 0.0
    for i, data in enumerate(dataloader, 0):
        # get the inputs
        inputs, labels = data

        # zero the parameter gradients
        optimizer.zero_grad()

        # forward + backward + optimize
        outputs = net(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

        # print statistics
        running_loss += loss.item()
        if i % 2000 == 1999:    # print every 2000 mini-batches
            print('[%d, %5d] loss: %.3f' %
                  (epoch + 1, i + 1, running_loss / 2000))
            running_loss = 0.0

print('Finished Training')

Тем не менее, RuntimeError, упомянутый выше, выбрасывается.Любые идеи о том, что я делаю неправильно?

Кроме того, я знаю, что без транспонирования данных изображения он имеет форму WHC, но модель NN требует его как CWH.Проблема в том, что если мы перейдем с WHC на CWH, то мы больше не сможем просто отобразить изображения, если переберем DataLoader.

data = ImageData()
dataloader = DataLoader(data, batch_size=10, shuffle=True, num_workers=1)
imgs, labels = next(iter(dataloader))
plt.imshow(imgs.numpy()[0,:,:,:])
plt.show()

Попытка выполнить приведет к следующей ошибке.

TypeError: Invalid dimensions for image data

Для меня эта Подушка дает вам WHC, и вы можете использовать это для построения графика, но PyTorch CNN хочет, чтобы CWH обрабатывал, это неприятность.Любая идея о том, как последовательно или легко не делать так много преобразований, но быть в состоянии построить и передать данные в CNN?Или это несоответствие WHC и CWH - просто то, с чем нам приходится жить?

Без транспонирования изображения при подаче его в CNN выдается следующая ошибка.

RuntimeError: Given groups=1, weight[256, 3, 256, 256], so expected
input[10, 256, 256, 3] to have 3 channels, but got 256 channels

.

Ответы [ 2 ]

0 голосов
/ 08 сентября 2018

«входы» ваших тренировочных данных относятся к типу ByteTensor, но torch.conv2d () поддерживает большинство операций только для FloatTensor и DoubleTensor.так что просто нужно добавить это:

inputs = inputs.type(torch.FloatTensor)

или

inputs = inputs.type(torch.DoubleTensor)

, прежде чем положить его в Net

0 голосов
/ 19 мая 2018

conv2d работает на поплавковых тензорах.Обычной и хорошей практикой является нормализация входных изображений перед передачей их в нейронную сеть.

Я бы добавил строку img = img/255 непосредственно перед тем, как преобразовать ее в тензор факела в __getitem__, затем он будет преобразовантензор float, а не тензор byte и, следовательно, будет совместим с методом conv2d.

...