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)
Related
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.
I have 22 classes, on the output layer, respectively, 22 channels, how can I change all this so that the output is 1 channel. Number 1 corresponds to class 1, number 2 - to the second, etc.
import torch.nn.functional as F
class Net(nn.Module):
def __init__(self):
super().__init__()
self.conv1 = nn.Conv2d(1, 6, 5)
self.pool = nn.MaxPool2d(2, 2)
self.conv2 = nn.Conv2d(6, 64, 5)
self.fc1 = nn.Linear(64 * 21 * 21, 120)
self.fc2 = nn.Linear(120, 256)
self.fc3 = nn.Linear(256, 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)
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
net = Net()
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]))
i am trying to get the input and output information of a network. When debugging, i got this error, Runtime, shape ‘[-1, 400]’ is invalid for input of size 384. I tried different values, but can’t find the correct value. Is there a way to solve this issue? Thanks.
class Net(nn.Module):
def __init__(self):
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, 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
input_shape = (3, 21,21)
dummy_input = torch.randn(6,*input_shape)
graph = torch.jit._get_trace_graph(model, args=dummy_input, _force_outplace=False, _return_inputs_states=False)
Error message:
RuntimeError: shape '[-1, 400]' is invalid for input of size 384
The shape of the tensor after the convolutional layers is [6,16,2,2]. So you cannot reshape it to 16*5*5 before feeding them to the linear layers. You should change your network to the one given below if you want to use the same filter sizes as the original in the convolutional layers.
class Net(nn.Module):
def __init__(self):
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*2*2, 120) # changed the size
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*2*2) # changed the size
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
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].