Convolution - Deconvolution for even and odd size - pytorch

I have two different size tensors to put in the network.
C = nn.Conv1d(1, 1, kernel_size=1, stride=2)
TC = nn.ConvTranspose1d(1, 1, kernel_size=1, stride=2)
a = torch.rand(1, 1, 100)
b = torch.rand(1, 1, 101)
a_out, b_out = TC(C(a)), TC(C(b))
The results are
a_out = torch.size([1, 1, 99]) # What I want is [1, 1, 100]
b_out = torch.size([1, 1, 101])
Is there any method to handle this problem?
I need your help.
Thanks

It is expected behaviour as per documentation. May be padding can be used when even input length is detected to get same length as input.
Something like this
class PadEven(nn.Module):
def __init__(self, conv, deconv, pad_value=0, padding=(0, 1)):
super().__init__()
self.conv = conv
self.deconv = deconv
self.pad = nn.ConstantPad1d(padding=padding, value=pad_value)
def forward(self, x):
nd = x.size(-1)
x = self.deconv(self.conv(x))
if nd % 2 == 0:
x = self.pad(x)
return x
C = nn.Conv1d(1, 1, kernel_size=1, stride=2)
TC = nn.ConvTranspose1d(1, 1, kernel_size=1, stride=2)
P = PadEven(C, TC)
a = torch.rand(1, 1, 100)
b = torch.rand(1, 1, 101)
a_out, b_out = P(a), P(b)

Related

RuntimeError: Given groups=1, weight of size [32, 3, 3, 3], expected input[8, 1, 256, 256] to have 3 channels, but got 1 channels instead

I got this error RuntimeError: Given groups=1, weight of size [32, 3, 3, 3], expected input[8, 1, 256, 256] to have 3 channels, but got 1 channels instead. This is my code
I haven't found the cause for this. Can anyone help me to figure out the problems? Thank you
"'"
"'"
class UNet(nn.Module):
def __init__(self, in_channels=3, features=[32,64,128,512], num_classes=3):
super().__init__()
self.down = []
self.pool = nn.MaxPool2d(2,2)
for i in range(len(features)):
if i == 0:
self.down.append(
nn.Sequential(
DoubleConv(in_channels, features[i])
)
)
else:
self.down.append(
nn.Sequential(
DoubleConv(features[i-1], features[i])
)
)
self.down = nn.ModuleList(self.down)
self.lower = DoubleConv(features[-1], features[-1]*2)
self.up = []
self.dbc = []
features.reverse()
for i in range(len(features)):
if i == 0:
self.up.append(
nn.Sequential(
nn.ConvTranspose2d(features[0]*2,features[i], 2, 2),
nn.ReLU()
)
)
self.dbc.append(DoubleConv(features[i]*2, features[i]))
else:
self.up.append(
nn.Sequential(
nn.ConvTranspose2d(features[i-1], features[i],2,2),
nn.ReLU(),
)
)
self.dbc.append(DoubleConv(features[i]*2, features[i]))
self.up = nn.ModuleList(self.up)
self.classifier = nn.Conv2d(features[-1], num_classes, 3, 1, 1)
def forward(self, x):
x1 = self
x_down = []
for i, layer in enumerate(self.down):
x_down.append(layer(x))
x = self.pool(x_down[-1])
print(x.shape)
x_lower = self.lower(x)
print(x_lower.shape)
x_down.reverse()
x_up = []
for i, (layer_up, layer_dbc) in enumerate(zip(self.up, self.dbc)):
if i == 0:
temp_x = layer_up(x_lower)
print(temp_x.shape)
temp_x = torch.cat((temp_x, x_down[i]), dim=1)
x_up.append(layer_dbc(temp_x))
else:
temp_x = layer_up(x_up[-1])
temp_x = torch.cat((temp_x, x_down[i]), dim=1)
x_up.append(layer_dbc(temp_x))
# print(x_up[-1].shape)
x_classifier = self.classifier(x_up[-1])
print(x_classifier.shape)
return x_classifier
I tried to check the model with the input
model = UNet()
x = torch.randn(3,3,256,256)
output = model(x)
and work

Access individual gradients - TensorFlow2

For a toy LeNet-5 CNN architecture on MNIST implemented in TensorFlow-2.10 + Python-3.10, with a batch-size = 256:
class LeNet5(Model):
def __init__(self):
super(LeNet5, self).__init__()
self.conv1 = Conv2D(
filters = 6, kernel_size = (5, 5),
strides = (1, 1), activation = None,
input_shape = (28, 28, 1)
)
self.pool1 = AveragePooling2D(
pool_size = (2, 2), strides = (2, 2)
)
self.conv2 = Conv2D(
filters = 16, kernel_size = (5, 5),
strides = (1, 1), activation = None
)
self.pool2 = AveragePooling2D(
pool_size = (2, 2), strides = (2, 2)
)
self.flatten = Flatten()
self.dense1 = Dense(
units = 120, activation = None
)
self.dense2 = Dense(
units = 84, activation = None
)
self.output_layer = Dense(
units = 10, activation = None
)
def call(self, x):
x = tf.nn.relu(self.conv1(x))
x = self.pool1(x)
x = tf.nn.relu(self.conv2(x))
x = self.pool2(x)
x = self.flatten(x)
x = tf.nn.relu(self.dense1(x))
x = tf.nn.relu(self.dense2(x))
x = tf.nn.softmax(self.output_layer(x))
return x
def shape_computation(self, x):
print(f"Input shape: {x.shape}")
x = self.conv1(x)
print(f"conv1 output shape: {x.shape}")
x = self.pool1(x)
print(f"pool1 output shape: {x.shape}")
x = self.conv2(x)
print(f"conv2 output shape: {x.shape}")
x = self.pool2(x)
print(f"pool2 output shape: {x.shape}")
x = self.flatten(x)
print(f"flattened shape: {x.shape}")
x = self.dense1(x)
print(f"dense1 output shape: {x.shape}")
x = self.dense2(x)
print(f"dense2 output shape: {x.shape}")
x = self.output_layer(x)
print(f"output shape: {x.shape}")
del x
return None
# Initialize an instance of LeNet-5 CNN-
model = LeNet5()
model.build(input_shape = (None, 28, 28, 1))
# Define loss and optimizer-
loss_fn = tf.keras.losses.CategoricalCrossentropy(reduction = tf.keras.losses.Reduction.NONE)
# optimizer = tf.keras.optimizers.Adam(learning_rate = 0.0003)
optimizer = tf.keras.optimizers.SGD(
learning_rate = 10e-3, momentum = 0.0,
nesterov = False
)
with tf.GradientTape() as grad_tape:
pred = model(x)
loss = loss_fn(y, pred)
loss.shape
TensorShape([256])
This computes individual loss for each of the 256 training images in a given batch.
# Compute gradient using loss wrt parameters-
grads = grad_tape.gradient(loss, model.trainable_variables)
type(grads), len(grads)
# (list, 10)
for i in range(len(grads)):
print(f"i: {i}, grads.shape: {grads[i].shape}")
"""
i: 0, grads.shape: (5, 5, 1, 6)
i: 1, grads.shape: (6,)
i: 2, grads.shape: (5, 5, 6, 16)
i: 3, grads.shape: (16,)
i: 4, grads.shape: (256, 120)
i: 5, grads.shape: (120,)
i: 6, grads.shape: (120, 84)
i: 7, grads.shape: (84,)
i: 8, grads.shape: (84, 10)
i: 9, grads.shape: (10,)
"""
Corresponding to loss for each training example, how can I compute gradient corresponding to each training example?

RuntimeError: Given groups=1, weight of size [16, 1, 3, 3, 3], expected input[250, 64, 4, 4, 4] to have 1 channels, but got 64 channels instead

This is the architecture based on a research paper.
class NBV_Net(nn.Module):
def __init__(self, dropout_prob):
super(NBV_Net, self).__init__()
#dropout_prob = 0.0 # 1 - 0.7
# Four 3D convolutional layers
self.conv1 = nn.Conv3d(1,16, 3, stride=1, padding=1)
self.pool1 = nn.MaxPool3d(kernel_size=(2,2,2), stride = (2,2,2))
self.conv2 = nn.Conv3d(16, 32, 3, stride=1, padding=1)
self.pool2 = nn.MaxPool3d(kernel_size=(2,2,2), stride = (2,2,2))
self.conv3 = nn.Conv3d(32, 64, 3, stride=1, padding=1)
self.conv3_drop = nn.Dropout(dropout_prob)
self.pool3 = nn.MaxPool3d(kernel_size=(2,2,2), stride = (2,2,2))
self.conv4 = nn.Conv3d(64, 64, 3, stride=1, padding=1)
self.conv4_drop = nn.Dropout(dropout_prob)
# Five fully connected layers
self.fc1 = nn.Linear(4096, 1500)
self.fc1_drop = nn.Dropout(dropout_prob)
self.fc2 = nn.Linear(1500, 500)
self.fc2_drop = nn.Dropout(dropout_prob)
self.fc3 = nn.Linear(500, 100)
self.fc3_drop = nn.Dropout(dropout_prob)
self.fc4 = nn.Linear(100, 50)
self.fc4_drop = nn.Dropout(dropout_prob)
self.fc5 = nn.Linear(50, 3)
def forward(self, x):
## feedforward behavior of NBV-net
x = self.pool1(F.relu(self.conv1(x)))
x = self.pool2(F.relu(self.conv2(x)))
x = self.pool3(F.relu(self.conv3(x)))
x = self(F.relu(self.conv4(x)))
# Aplanar
x = x.view(x.size(0), -1)
x = F.relu(self.fc1(x))
x = self.fc1_drop(x)
x = F.relu(self.fc2(x))
x = self.fc2_drop(x)
x = F.relu(self.fc3(x))
x = self.fc3_drop(x)
x = F.relu(self.fc4(x))
x = self.fc4_drop(x)
x = F.tanh(self.fc5(x))
return x
RuntimeError: Given groups=1, weight of size [16, 1, 3, 3, 3], expected input[250, 64, 4, 4, 4] to have 1 channels, but got 64 channels instead
But this code gives the Runtime Error. Similar errors are there but I could not understand what Group 1 and other dimensions mentioned exactly mean , any idea about the background of this error ?
The input shape for nn.Conv3d(1,16, 3, stride=1, padding=1) is (batch, channels, depth, height, width).
You define that the channel size is 1 but your input tensor has 64 channels.
self.conv1 = nn.Conv3d(64,16, 3, stride=1, padding=1) will resolve you error

ValueError: out_channels must be divisible by groups

I want to implement these three layers in a single class, but I face this problem
ValueError: out_channels must be divisible by groups
I don't understand where is the mistake?!
THis is the code:
class Block(nn.Module):
def __init__(self, in_channels, out_channels, exp=1, stride=1, type=''):
super().__init__()
self.t = type
self.stride = stride
self.inc, self.outc = in_channels, out_channels
self.exp = exp
self.blockc = nn.Sequential(
nn.Conv2d(self.inc, self.inc* self.exp, kernel_size=1),
nn.ReLU(),
nn.Conv2d(self.inc * self.exp, self.outc, kernel_size=3, groups= self.inc * self.exp, stride= self.stride),
nn.ReLU(),
nn.Conv2d(self.outc, self.outc * self.exp, kernel_size=1),
nn.Linear(self.outc * self.exp, self.outc * self.exp))
def forward(self, x):
out = self.blockc(x)
if self.t == 'A':
out = torch.sum(out,x)
return out
and here is the layers consists of depthwise convolution and conv 1x1 also there is a param exp which means out_channels = exp* in_channles
Here is a possible implementation, you will have to adjust the channels and padding for your needs:
class BType(Enum):
A = 0
B = 1
C = 2
class Block(nn.Module):
def __init__(self, c_in: int, c_out: int, btype: BType) -> nn.Module:
super().__init__()
self.btype = btype
if btype == BType.A:
assert c_in == c_out
self.c1 = nn.Sequential(
nn.Conv2d(c_in, c_in, kernel_size=1),
nn.ReLU())
self.c2 = nn.Sequential(
nn.Conv2d(c_in, c_in, kernel_size=3, groups=c_in,
stride=2 if btype == BType.C else 1,
padding=2 if btype == BType.C else 1),
nn.ReLU())
self.c3 = nn.Conv2d(c_in, c_out, kernel_size=1)
def forward(self, x: torch.Tensor) -> torch.Tensor:
out = self.c1(x)
out = self.c2(out)
out = self.c3(out)
if self.btype == BType.A:
out += x
return out
Here is a test with all three block types:
block A:
>>> block = Block(3, 3, BType.A)
>>> block(torch.rand(2,3,10,10)).shape
torch.Size([2, 3, 10, 10])
block B:
>>> block = Block(3, 10, BType.B)
>>> block(torch.rand(2,3,10,10)).shape
torch.Size([2, 10, 10, 10])
block C:
>>> block = Block(3, 10, BType.C)
>>> block(torch.rand(2,3,10,10)).shape
torch.Size([2, 10, 6, 6])

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].

Resources