Reputation: 1
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
import torch
import torch.nn as nn
import torch.nn.functional as F
import numpy as np
from torch.autograd import Variable
from sklearn import preprocessing
batch_size = 32
num_classes = 8
epochs = 10
img_rows, img_cols = 256, 256
x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1)
x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1)
input_shape = (img_rows, img_cols, 1)
print('x_train shape:', x_train.shape)
print("Training samples: {}".format(x_train.shape[0]))
print("Test samples: {}".format
(x_test.shape[0]))
x_train = torch.Tensor(x_train).float()
x_test = torch.Tensor(x_test).float()
y_train = torch.LongTensor(y_train)
y_test = torch.LongTensor(y_test)
#Define model
model = nn.Sequential(
nn.Conv2d(256,80,1, stride=1),
nn.ReLU(),
nn.Conv2d(80,40,1, stride=1),
nn.ReLU(),
nn.MaxPool2d(4,stride=1),
nn.Conv2d(40,30,1, stride=1),
nn.ReLU(),
nn.Conv2d(30,15,1, stride=1),
nn.ReLU(),
nn.Dropout(0.2),
nn.Flatten(),
nn.Linear(32, 32),
nn.Dropout(0.1),
nn.Linear(num_classes, 256),
nn.ReLU()
)
criterion = nn.CrossEntropyLoss()# cross entropy loss
optimizer = torch.optim.Adam(model.parameters(), lr=0.01)
for epoch in range(100):
optimizer.zero_grad()
out = model(x_train)
loss = criterion(out, y_train)
loss.backward()
optimizer.step()
print(f"Epoch {epoch+1}, loss: {loss.item()}")
RuntimeError Traceback (most recent call last)
<ipython-input-10-96fa8b09f1ec> in <module>
63 for epoch in range(100):
64 optimizer.zero_grad()
---> 65 out = model(x_train)
66 loss = criterion(out, y_train)
67 loss.backward()
with the following error message
RuntimeError: Given input size: (40x256x1). Calculated output size: (40x253x-2). Output size is too small
I am unsure on how to fix this as I am new to pytorch and the original model did work in tensorflow. Any help would be much appreciated
Upvotes: 0
Views: 1110
Reputation: 40768
I'm assuming you are working with images. In that case, there are several issues with your code. Also reading from the comments, there are a couple of things I need to clarify.
I think the most important is the fact you've switched up the axes on the input shape. Unlike in Tensorflow, PyTorch multi-channel maps are shaped with (b, c, h, w)
(b
: batch size; c
: number of channels; h
xw
: height and width of a feature map.
Also you have defined the first layer as nn.Conv2d(256, 80, 1, stride=1)
which means it has 80 filters, and expects a 256-channel input! That's not what you should want, assuming you've following my first point (which is to feed (1,256,256)
images) to your model. The number of filters can stay at 80, that's up to you and your neural network design.
A little later down your model, you define a max pool with nn.MaxPool2d(4, stride=1)
. Just to point out that you are using a kernel size of 4 pixels here. Which means that, at this point, the resulting tensor will have a shape of (b, 40, 253, 253)
. The change from 256x256 to 253x253 is due to the kernel size being 4.
You flatten after your final convolution into (b, 960135)
. That's 253*253*15
(feature map dimensions times number of feature maps). Ultimately, the next dense layer needs to have that number as input size. Instead you have put nn.Linear(32, 32)
followed by nn.Linear(num_classes, 256)
. It should rather be something like nn.Linear(253*253*15, n)
followed by nn.Linear(n, num_classes)
. Where n
is arbitrarily set and I assumed you wanted an output with num_classes
logits at the end.
Also, I read in the comments
If you organize all correctly, I think you have to change the first layer in Sequential() from nn.Conv2d(256,80,1, stride=1) to nn.Conv2d(32,80,1, stride=1)
The batch size doesn't have anything to do with the layer's size parameters. Don't think about the batch axis, it's the first axis. Your model doesn't depend on your batch size!
I would recommend, increasing your kernel sizes, this will allow your feature maps to shrink in dimensions as it goes through the network, at the same time, increasing the number of channels until you hit the flatten layer and fully connected.
Here is your model with some important correction, just enough to make it run:
batch_size = 32
num_classes = 8
img_rows, img_cols = 256, 256
input_shape = (img_rows, img_cols, 1)
# dummy data, would broadcast your data with these shapes
x_train = torch.rand(batch_size, 1, img_rows, img_cols)
y_train = torch.rand(batch_size, 256)
model = nn.Sequential(
nn.Conv2d(1, 80, 1, stride=1),
nn.ReLU(),
nn.Conv2d(80, 40, 1, stride=1),
nn.ReLU(),
nn.MaxPool2d(4, stride=1),
nn.Conv2d(40, 30, 1, stride=1),
nn.ReLU(),
nn.Conv2d(30, 15, 1, stride=1),
nn.ReLU(),
nn.Dropout(0.2),
nn.Flatten(),
nn.Linear(253*253*15, 256),
nn.Dropout(0.1),
nn.Linear(256, num_classes),
nn.ReLU()
)
Upvotes: 1