RuntimeError: mat1 and mat2 shapes cannot be multiplied (5400x64 and 5400x64) - pytorch

I'm working on an image classification network and got a problem with the right values of inputs and outputs in the forward() function. I don't have an idea to solve this, because they seem the same to me. The error comes from this line:
x = F.relu(self.fc1(x)), but I can't figure it out.
Can anyone please help me with this problem?
That's my code:
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(3, 8, kernel_size=2)
self.conv2 = nn.Conv2d(8, 12, kernel_size=2)
self.conv3 = nn.Conv2d(12, 18, kernel_size=2)
self.conv4 = nn.Conv2d(18, 24, kernel_size=2)
self.fc1 = nn.Linear(5400, 64)
self.fc2 = nn.Linear(64, 2)
def forward(self, x):
print(f'1. {x.size()}')
x = self.conv1(x)
x = F.max_pool2d(x, 2)
x = F.relu(x)
print(f'2. {x.size()}')
x = self.conv2(x)
x = F.max_pool2d(x, 2)
x = F.relu(x)
print(f'3. {x.size()}')
x = self.conv3(x)
x = F.max_pool2d(x, 2)
x = F.relu(x)
print(f'4. {x.size()}')
x = self.conv4(x)
x = F.max_pool2d(x, 2)
x = F.relu(x)
print(f'5. {x.size()}')
x = x.view(-1, x.size(0))
print(f'6. {x.size()}')
x = F.relu(self.fc1(x))
print(f'7. {x.size()}')
x = self.fc2(x)
print(f'8. {x.size()}')
return torch.sigmoid(x)
That's the print output:
1. torch.Size([64, 3, 256, 256])
2. torch.Size([64, 8, 127, 127])
3. torch.Size([64, 12, 63, 63])
4. torch.Size([64, 18, 31, 31])
5. torch.Size([64, 24, 15, 15])
6. torch.Size([5400, 64])

I think changing
x = x.view(-1, x.size(0))
to
x = x.view([-1, 5400], x.size(0))
Will solve your problem, You see that in print 6:
6. torch.Size([5400, 64])
the batch size 64 is in the 1 axes and not in the 0 axes. The fully connected layer expects an input of size 5400 therefore changing this will likely solve since you do not know that batch size but you know that the input to the fully-connected is 5400.

Related

Expected input batch_size (56180) to match target batch_size (100)

i am getting following error.
ValueError: Expected input batch_size (56180) to match target batch_size (100).
My model's input is 3 channel(RGB) 227x227 images
And batch size is 100.
And following is summary.
torch.Size([100, 3, 227, 227])
torch.Size([100, 10, 111, 111])
torch.Size([100, 20, 53, 53])
torch.Size([56180, 100])
torch.Size([56180, 64])
torch.Size([56180, 64])
torch.Size([56180, 32])
torch.Size([56180, 32])
torch.Size([56180, 1])
This is binary classification(True, False), so i make final output is 1
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
#input image 227x227x3
self.conv1 = nn.Conv2d(3, 10, kernel_size=5)
self.conv2 = nn.Conv2d(10, 20, kernel_size=5)
self.conv2_drop = nn.Dropout2d()
self.fc1 = nn.Linear(100, 64)
self.fc3 = nn.Linear(64, 32)
self.fc6 = nn.Linear(32, 1)
def forward(self, x):
print(x.shape)
x = F.relu(F.max_pool2d(self.conv1(x), 2))
print(x.shape)
x = F.relu(F.max_pool2d(self.conv2_drop(self.conv2(x)), 2))
print(x.shape)
x = x.view(-1, x.size(0))
print(x.shape)
x = F.relu(self.fc1(x))
print(x.shape)
x = F.dropout(x, training=self.training)
print(x.shape)
x = self.fc3(x)
print(x.shape)
x = F.dropout(x, training=self.training)
print(x.shape)
x = self.fc6(x)
print(x.shape)
return x
def train(model, train_loader, optimizer):
model.train()
for batch_idx, (data, target) in enumerate(train_loader):
data, target = data.to(DEVICE), target.to(DEVICE)
optimizer.zero_grad()
output = model(data)
target = target.unsqueeze(-1)
loss = F.cross_entropy(output, target)
loss.backward()
optimizer.step()
My question is that i have 100 batch images so that target(Y) is 100 units. But Why i am getting 56180 unit result?
Change the view function (in forward method):
x = x.view(x.size(0), -1)
The batch size must be in the 0 dimension.
Your forward method should be defined like this:
def forward(self, x):
x = F.relu(F.max_pool2d(self.conv1(x), 2))
x = F.relu(F.max_pool2d(self.conv2_drop(self.conv2(x)), 2))
x = x.view(x.size(0), -1)
x = F.relu(self.fc1(x))
x = F.dropout(x, training=self.training)
x = self.fc3(x)
x = F.dropout(x, training=self.training)
x = self.fc6(x)
return x

Change the layer format to a different image resolution

There is a class where everything is set to 32x32 image format Taken from here
class Net(nn.Module):
def __init__(self):
super().__init__()
self.conv1 = nn.Conv2d(1, 6, 5) # here I changed the image channel from 3 to 1
self.pool = nn.MaxPool2d(2, 2)
self.conv2 = nn.Conv2d(6, 64, 5)
self.fc1 = nn.Linear(64 * 5 * 5, 120)
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, 22) # here I changed the number of output neurons from 10 to 22
def forward(self, x):
x = self.pool(F.relu(self.conv1(x)))
x = self.pool(F.relu(self.conv2(x)))
x = torch.flatten(x, 1) # flatten all dimensions except batch
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
How to change all this under resolution 96 to 96? Channel 1 (grayscale)?
At resolution 32x32 the output of conv2 is shaped (1, 64, 5, 5). On the other hand, if the input is at resolution 96x96, it will be (1, 64, 21, 21). This means fc1 needs to have 28_224 input neurons.
>>> self.fc1 = nn.Linear(64 * 21 * 21, 120)
Alternatively, you can use nn.LazyLinear which will infer this number for you, based on the first inference.
>>> self.fc1 = nn.Linear(120)

Pytorch - AttributeError: 'tuple' object has no attribute 'dim'

I am trying to use this architecture:
class Net(BaseFeaturesExtractor):
def __init__(self, observation_space: gym.spaces.Box, features_dim: int = 512):
super(Net, self).__init__(observation_space, features_dim)
self.conv1 = nn.Conv2d(1, 64, 3, stride=1, padding=1)
self.conv2 = nn.Conv2d(64, 64, 3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 64, 3, stride=1)
self.conv4 = nn.Conv2d(64, 64, 3, stride=1)
self.bn1 = nn.BatchNorm2d(64)
self.bn2 = nn.BatchNorm2d(64)
self.bn3 = nn.BatchNorm2d(64)
self.bn4 = nn.BatchNorm2d(64)
self.fc1 = nn.Linear(64 * (7 - 4) * (6 - 4), 128)
self.fc_bn1 = nn.BatchNorm1d(128)
self.fc2 = nn.Linear(128, 64)
self.fc_bn2 = nn.BatchNorm1d(64)
self.fc3 = nn.Linear(64, 7)
self.fc4 = nn.Linear(64, 1)
def forward(self, s):
# s: batch_size x board_x x board_y
s = s.view(-1, 1, 7, 6) # batch_size x 1 x board_x x board_y
s = F.relu(self.bn1(self.conv1(s))) # batch_size x num_channels x board_x x board_y
s = F.relu(self.bn2(self.conv2(s))) # batch_size x num_channels x board_x x board_y
s = F.relu(self.bn3(self.conv3(s))) # batch_size x num_channels x (board_x-2) x (board_y-2)
s = F.relu(self.bn4(self.conv4(s))) # batch_size x num_channels x (board_x-4) x (board_y-4)
s = s.view(-1,64 * (7 - 4) * (6 - 4))
s = F.dropout(
F.relu(self.fc_bn1(self.fc1(s))),
p=0.3,
training=self.training) # batch_size x 128
s = F.dropout(
F.relu(self.fc_bn2(self.fc2(s))),
p=0.3,
training=self.training) # batch_size x 64
pi = self.fc3(s) # batch_size x action_size
v = self.fc4(s) # batch_size x 1
return F.log_softmax(pi, dim=1), th.tanh(v)
When I am trying to use this architecture, I am getting following error:
Traceback (most recent call last):
File "/Users/joe/Documents/JUPYTER/ConnectX/training3.py", line 130, in <module>
learner.learn(total_timesteps=iterations, callback=eval_callback)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/stable_baselines3/ppo/ppo.py", line 264, in learn
reset_num_timesteps=reset_num_timesteps,
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/stable_baselines3/common/on_policy_algorithm.py", line 222, in learn
continue_training = self.collect_rollouts(self.env, callback, self.rollout_buffer, n_rollout_steps=self.n_steps)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/stable_baselines3/common/on_policy_algorithm.py", line 154, in collect_rollouts
actions, values, log_probs = self.policy.forward(obs_tensor)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/stable_baselines3/common/policies.py", line 545, in forward
latent_pi, latent_vf, latent_sde = self._get_latent(obs)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/stable_baselines3/common/policies.py", line 564, in _get_latent
latent_pi, latent_vf = self.mlp_extractor(features)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/torch/nn/modules/module.py", line 727, in _call_impl
result = self.forward(*input, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/stable_baselines3/common/torch_layers.py", line 220, in forward
shared_latent = self.shared_net(features)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/torch/nn/modules/module.py", line 727, in _call_impl
result = self.forward(*input, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/torch/nn/modules/container.py", line 117, in forward
input = module(input)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/torch/nn/modules/module.py", line 727, in _call_impl
result = self.forward(*input, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/torch/nn/modules/linear.py", line 93, in forward
return F.linear(input, self.weight, self.bias)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/torch/nn/functional.py", line 1688, in linear
if input.dim() == 2 and bias is not None:
AttributeError: 'tuple' object has no attribute 'dim'
How this problem can be fixed?
I tried to reproduce a small working code based on the class definitions given by you and I was able to get the outputs from the model. Here is the following code:
# BaseFeaturesExtractor class
import gym
import torch as th
from torch import nn
class BaseFeaturesExtractor(nn.Module):
"""
Base class that represents a features extractor.
:param observation_space:
:param features_dim: Number of features extracted.
"""
def __init__(self, observation_space: gym.Space, features_dim: int = 0):
super(BaseFeaturesExtractor, self).__init__()
assert features_dim > 0
self._observation_space = observation_space
self._features_dim = features_dim
#property
def features_dim(self) -> int:
return self._features_dim
def forward(self, observations: th.Tensor) -> th.Tensor:
raise NotImplementedError()
# Net class
class Net(BaseFeaturesExtractor):
def __init__(self, observation_space: gym.spaces.Box, features_dim: int = 512):
super(Net, self).__init__(observation_space, features_dim)
self.conv1 = nn.Conv2d(1, 64, 3, stride=1, padding=1)
self.conv2 = nn.Conv2d(64, 64, 3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 64, 3, stride=1)
self.conv4 = nn.Conv2d(64, 64, 3, stride=1)
self.bn1 = nn.BatchNorm2d(64)
self.bn2 = nn.BatchNorm2d(64)
self.bn3 = nn.BatchNorm2d(64)
self.bn4 = nn.BatchNorm2d(64)
self.fc1 = nn.Linear(64 * (7 - 4) * (6 - 4), 128)
self.fc_bn1 = nn.BatchNorm1d(128)
self.fc2 = nn.Linear(128, 64)
self.fc_bn2 = nn.BatchNorm1d(64)
self.fc3 = nn.Linear(64, 7)
self.fc4 = nn.Linear(64, 1)
def forward(self, s):
# s: batch_size x board_x x board_y
s = s.view(-1, 1, 7, 6) # batch_size x 1 x board_x x board_y
s = F.relu(self.bn1(self.conv1(s))) # batch_size x num_channels x board_x x board_y
s = F.relu(self.bn2(self.conv2(s))) # batch_size x num_channels x board_x x board_y
s = F.relu(self.bn3(self.conv3(s))) # batch_size x num_channels x (board_x-2) x (board_y-2)
s = F.relu(self.bn4(self.conv4(s))) # batch_size x num_channels x (board_x-4) x (board_y-4)
s = s.view(-1,64 * (7 - 4) * (6 - 4))
s = F.dropout(
F.relu(self.fc_bn1(self.fc1(s))),
p=0.3,
training=self.training) # batch_size x 128
s = F.dropout(
F.relu(self.fc_bn2(self.fc2(s))),
p=0.3,
training=self.training) # batch_size x 64
pi = self.fc3(s) # batch_size x action_size
v = self.fc4(s) # batch_size x 1
return F.log_softmax(pi, dim=1), th.tanh(v)
# Minimal code to reproduce a forward pass
import numpy as np
import torch
import torch.nn.functional as F
params = gym.spaces.Box(np.array([-1,0,0]), np.array([+1,+1,+1]))
model = Net(params)
inputs = torch.randn(2, 1, 7, 6)
outputs = model(inputs)
print(outputs[0].shape, outputs[1].shape) # prints (torch.Size([2, 7]), torch.Size([2, 1]))

PyTorch custom DataLoader dimension issues for CNN

I have written a custom Dataset and DataLoader for a PyTorch CNN project. Here is the relevant code for the dataset
class MyDataset(Dataset):
def __init__(self):
pass
def __len__(self):
return COUNT
def __getitem__(self, idx):
x, y = X[idx], Y[idx]
x = image_augment(x) # custom func to resize image to 32x32
return x, y
The shape of each training x is [4, 32, 32, 3].
And here is my Net code, taken directly from this PyTorch example.
class Net(nn.Module):
def __init__(self, nc):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(3, 6, 5)
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, nc)
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
When I try to train this net on my data from my DataLoader, I get the error statement Given groups=1, weight of size [6, 3, 5, 5], expected input[4, 32, 32, 3] to have 3 channels, but got 200 channels instead. It seems to me my issue is with the shape of my data coming from my DataLoader using x.view(4, 3, 32, 32), but then I got an error saying I couldn't use Conv2D on a ByteTensor. I'm a little lost here and would really appreciate any help. Thanks!
I got it eventually. Had to x = x.view(x.shape[0], 3, self.img_height, self.img_width).type('torch.FloatTensor'). for example. This would make that swap from [4, 32, 32, 3] to [4, 3, 32, 32].

Convolution Neural Network for regression using pytorch

I am trying to do create CNN for regression purpose. Input is image data.
For learning purpose , i have 10 image of shape (10,3,448,448), where 10 are images, 3 are channel and 448 are hieght and width.
Output lables are (10,245).
Here is my architecture
class CNN(nn.Module):
def __init__(self):
super(CNN, self).__init__()
self.conv1 = nn.Conv2d(3, 32, kernel_size=5)
self.conv2 = nn.Conv2d(32, 32, kernel_size=5)
self.conv3 = nn.Conv2d(32,64, kernel_size=5)
self.fc1 = nn.Linear(3*3*64, 256)
self.fc2 = nn.Linear(256, 245)
def forward(self, x):
x = F.relu(self.conv1(x))
#x = F.dropout(x, p=0.5, training=self.training)
x = F.relu(F.max_pool2d(self.conv2(x), 2))
x = F.dropout(x, p=0.5, training=self.training)
x = F.relu(F.max_pool2d(self.conv3(x),2))
x = F.dropout(x, p=0.5, training=self.training)
x = x.view(-1,3*3*64 )
x = F.relu(self.fc1(x))
x = F.dropout(x, training=self.training)
x = self.fc2(x)
return x
cnn = CNN()
print(cnn)
it = iter(train_loader)
X_batch, y_batch = next(it)
print(cnn.forward(X_batch).shape)
Using batch size 2 i am expecting data shape produced by model is (2,245). But it is producing data of shape (2592, 245)
after self.conv3 you have tensors of shape [2, 64, 108, 108] which produces [2592, 576] after reshape. So this is where 2592 comes from.
Change the lines:
"self.fc1 = nn.Linear(3*3*64, 256)"
and
"x = x.view(-1,3*3*64)"
so that they use proper image size after the layers.
below is the fixed code:
class CNN(nn.Module):
def __init__(self):
super(CNN, self).__init__()
self.conv1 = nn.Conv2d(3, 32, kernel_size=5)
self.conv2 = nn.Conv2d(32, 32, kernel_size=5)
self.conv3 = nn.Conv2d(32,64, kernel_size=5)
self.fc1 = nn.Linear(108*108*64, 256)
self.fc2 = nn.Linear(256, 245)
def forward(self, x):
print (x.shape)
x = F.relu(self.conv1(x))
print (x.shape)
#x = F.dropout(x, p=0.5, training=self.training)
x = F.relu(F.max_pool2d(self.conv2(x), 2))
print (x.shape)
x = F.dropout(x, p=0.5, training=self.training)
print (x.shape)
x = F.relu(F.max_pool2d(self.conv3(x),2))
print (x.shape)
x = F.dropout(x, p=0.5, training=self.training)
print (x.shape)
x = x.view(-1,108*108*64 )
print (x.shape)
x = F.relu(self.fc1(x))
x = F.dropout(x, training=self.training)
x = self.fc2(x)
return x
cnn = CNN()
print(cnn)
# X_batch, y_batch = next(it)
print(cnn.forward(X_batch).shape)

Resources