T
T
tj572020-01-13 01:18:01
Python
tj57, 2020-01-13 01:18:01

How to correctly change the dimension of the input data when training a convolutional network on FashionMNIST?

I'm trying to train a network on the Fashion MNIST dataset using a convolutional network. At first I used a regular network:

class HyperParameters:
    inputs = 28 * 28
    hidden_layer_1 = 128
    hidden_layer_2 = 64
    outputs = 10
    learning_rate = 0.005
    rows = 1
    epochs = 200

model = nn.Sequential(
    OrderedDict(
        input_to_hidden=nn.Linear(HyperParameters.inputs,
                                  HyperParameters.hidden_layer_1),
        activation_1=nn.ReLU(),
        hidden_to_hidden=nn.Linear(HyperParameters.hidden_layer_1,
                                   HyperParameters.hidden_layer_2),
        activation_2=nn.ReLU(),
        hidden_to_output=nn.Linear(HyperParameters.hidden_layer_2,
                                   HyperParameters.outputs),
        activation_out=nn.LogSoftmax(dim=HyperParameters.rows),
    )
)

criterion = nn.NLLLoss()
optimizer = optim.SGD(model.parameters(), lr=HyperParameters.learning_rate)

After I changed it to a convolutional network:
class DeepCNN(nn.Module):
  def __init__(self):
    super(DeepCNN, self).__init__()
    self.model = nn.Sequential(
        nn.Conv2d(1, 8, 3),
        nn.Conv2d(8, 16, 3),
        nn.Linear(16, 10)
    )
  def forward(self, t):
    t = self.model(t)
    return t

model = DeepCNN()

loss_function = nn.CrossEntropyLoss()
optimizer = optim.Adam(net.parameters())

Can't figure out how to properly resize the input to fit the convolutional network. As I understand it, you need to use np.reshape. The error looks like this:
RuntimeError: Expected 4-dimensional input for 4-dimensional weight 8 1 3 3, but
got 2-dimensional input of size [64, 784] instead

Occurs on this line:
output = model.forward(images)
Program code:
import torch
import torch.nn as nn
import torch.optim as optim
import matplotlib.pyplot as plt
import numpy as np
from collections import OrderedDict
import seaborn

import torchvision
import torchvision.transforms as transforms

batch_size = 128

training = torchvision.datasets.FashionMNIST(root = "./data",
                                               train = True, download = True,
                                               transform = transforms.ToTensor())
testing = torchvision.datasets.FashionMNIST(root='./data',
                                               train=False, download=True,
                                               transform=transforms.ToTensor())
training_batches = torch.utils.data.DataLoader(training, batch_size=64, shuffle = True)
test_batches = torch.utils.data.DataLoader(testing,
                                           batch_size=64,
                                           shuffle=True)

data_iterator = iter(training_batches)
images, labels = data_iterator.next()

means = (0.5, 0.5, 0.5)
deviations = means
transform = transforms.Compose([transforms.ToTensor(),
                                transforms.Normalize(means, deviations)])


seaborn.set(style="whitegrid",
            rc={"axes.grid": False,
                "font.family": ["sans-serif"],
                "font.sans-serif": ["Latin Modern Sans", "Lato"],
                "figure.figsize": (8, 6)},
            font_scale=1)

im = images[1]
np_im = im.numpy()
np.squeeze(np_im).shape
plt.figure(figsize = (2,2))
plt.imshow(np.squeeze(np_im), cmap = 'gray')
plt.show()

classes = ("T-shirt/top",
                "Trouser",
                "Pullover",
                "Dress",
                "Coat",
                "Sandal",
                "Shirt",
                "Sneaker",
                "Bag",
                "Ankle boot",
                )

label_decoder = dict(zip(range(10), classes))

class DeepCNN(nn.Module):
  def __init__(self):
    super(DeepCNN, self).__init__()
    self.model = nn.Sequential(
        nn.Conv2d(1, 8, 3),
        nn.Conv2d(8, 16, 3),
        nn.Linear(16, 10)
    )
  def forward(self, t):
    t = self.model(t)
    return t

model = DeepCNN()

criterion = nn.NLLLoss()
optimizer = optim.SGD(model.parameters(), lr=0.005)

def imshow(img):
    npimg = img.numpy() #convert the tensor to numpy for displaying the image
    plt.imshow(np.transpose(npimg, (1, 2, 0))) #for displaying the image, shape of the image should be height * width * channels
    plt.show()

imshow(torchvision.utils.make_grid(images))
print(' '.join(classes[labels[j]] for j in range(4)))

def accuracy_evaluation(data_loader):
    correct = 0
    total = 0
    with torch.no_grad():
        for images, labels in test_batches:
            images = images.view(images.shape[0], -1)
            outputs = model(images)
            _, predicted = torch.max(outputs.data, 1)
            total += labels.size(0)
            correct += (predicted == labels).sum().item()

    return(100 * correct/total)

loss_array = []
loss_epoch_array = []
max_epochs = 10

for epoch in range(max_epochs):
    running_loss = 0
    for images, labels in training_batches:
        # some setup
        ## Flatten the images
        images = images.view(images.shape[0], -1)
        images = np.reshape(8, 1, 3, 3)
        ## Reset the optimizer
        optimizer.zero_grad()

        # forward pass
        output = model.forward(images)

        # back-propagation
        loss = criterion(output, labels)
        loss.backward()

        # take the next step
        optimizer.step()
        running_loss += loss.item()
    loss_epoch_array.append(loss.item())

    print(f"Training loss: {running_loss/len(training_batches)}")
    print('Epoch: %d/%d, Test acc: %0.2f' % (epoch, max_epochs, accuracy_evaluation(test_batches)))

plt.plot(loss_epoch_array)
plt.xlabel("Epochs"), plt.ylabel("Loss")
plt.show()

Answer the question

In order to leave comments, you need to log in

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question