Creating batches within an array containing images - python

I have an array X_train containing 9957 images. I am making a Convolutional network.The desired shape of the array for feeding into the model is (batchsize, channel, height, width)
X_train.shape #gives (9957, 60, 80, 3)
X_train[1].shape #gives (60, 80, 3)
If we use
np.reshape(X_train,(-1, 3, 60, 80)) #it gives (9957, 3, 60, 80)
How can I get each array with shape (batchsize, 3, 60, 80) and the final image array for training with shape(9957, batchsize, 3, 60, 80)?

You can get from i-th image until i + batchsize image as follows.
batchsize = 16
i = 0
X_batch = X_train[i: i+batchsize]
print('X_batch.shape: ', X_batch.shape) # it should be (16, 3, 60, 80)
Please change i with for loop to get each image. For example,
for i in range(0, len(X_train), batchsize):
X_batch = X_train[i: i+batchsize]
# --- Do something with X_batch ---

Related

Dimensionality problem with PyTorch Conv layers

I'm trying to train a neural network in PyTorch with some input signals. The layers are conv1d. The shape of my input is [100, 10], meaning 100 signals of a length of 10.
But when I execute the training, I have this error:
Given groups=1, weight of size [100, 10, 1], expected input[1, 1, 10] to have 10 channels, but got 1 channels instead
config = [10, 100, 100, 100, 100, 100, 100, 100]
batch_size = 1
epochs = 10
learning_rate = 0.001
kernel_size = 1
class NeuralNet(nn.Module):
def __init__(self, config, kernel_size=1):
super().__init__()
self.config = config
self.layers = nn.ModuleList([nn.Sequential(
nn.Conv1d(self.config[i], self.config[i + 1], kernel_size = kernel_size),
nn.ReLU())
for i in range(len(self.config)-1)])
self.last_layer = nn.Linear(self.config[-1], 3)
self.layers.append(nn.Flatten())
self.layers.append(self.last_layer)
def forward(self, x):
for i, l in enumerate(self.layers):
x = l(x)
return x
def loader(train_data, batch_size):
inps = torch.tensor(train_data[0])
tgts = torch.tensor(train_data[1])
inps = torch.unsqueeze(inps, 1)
dataset = TensorDataset(inps, tgts)
train_dataloader = DataLoader(dataset, batch_size = batch_size)
return train_dataloader
At first, my code was without the unsqueez(inps) line and I had the exact same error, but then I added this line thinking that I must have an input of size (num_examples, num_channels, lenght_of_signal) but it didn't resolve the problem at all.
Thank you in advance for your answers
nn.Conv1d expects input with shape of form (batch_size, num_of_channels, seq_length). It's parameters allow to directly set number of ouput channels (out_channels) and change length of output using, for example, stride. For conv1d layer to work correctly it should know number of input channels (in_channels), which is not the case on first convolution: input.shape == (batch_size, 1, 10), therefore num_of_channels = 1, while convolution in self.layers[0] expects this value to be equal 10 (because in_channels set by self.config[0] and self.config[0] == 10). Hence to fix this append one more value to config:
config = [10, 100, 100, 100, 100, 100, 100, 100] # as in snippet above
config = [1] + config
At this point convs should be working fine, but there is another obstacle in self.layers -- linear layer at the end. So if kernel_size of 1 was used, then after final convolution batch will have shape (batch_size, 100, 10), and after flatten (batch_size, 100 * 10), while last_layer expects input of shape (batch_size, 100). So, if length of sequence after final conv layer is known (which is certainly the case if you're using kernel_size of 1 with default stride of 1 and default padding of 0 -- length stays same), last_layer should be defined as:
self.last_layer = nn.Linear(final_length * self.config[-1], 3)
and in snippet above final_length can be set to 10 (since conditions in previous brackets satisfied). To catch idea of how shapes in conv1d transformed take look at simple example in gif below (here batch_size is equal to 1):

Reshaping a dataframe into 3D

I am trying to reshape an activity recognition dataset into the 3D form to be parsed in 2D CNN. I tried multiple times, but I couldn't figure out how it can be done.
My Current shape of X_train is (1418, 80, 6), and X_Test is (355, 80, 6).
I am trying to do as follows.
X_train = X_train.reshape(1418, 20, 2, 1)
And I got the following error:
cannot reshape array of size 680640 into shape (1418,20,2,1)
Any advice on how I can reshape the data into 3d so I can pass it in a 2D CNN algorithm?
Thank you
By doing:
X_train = X_train.reshape(1418, 20, 2, 1) on some data that originally has shape (1418, 80, 6) python will output the error:
cannot reshape array of size 680640 into shape (1418,20,2,1)
This is happening because you are trying to reshape (80,6) to (20,2,1)
80 * 6 is not equal 20 * 2 * 1.
try changing it to something that would result into the same quantity of 80 * 6 such as X_train = X_train.reshape(1418, 40, 12, 1) or X_train = X_train.reshape(1418, 20, 24, 1)

Error when checking input: expected input_6 to have shape (80, 80, 1) but got array with shape (80, 80, 2400) in image segmentation

I have a medical imaging dataset with a dimension of (80,80,2900), each image is 80*80. First I loaded the mat file of the data as follow:
data = loadmat('cardiac-dig.mat')
images_LV = np.array (data['images_LV'])
val_data_size = 500
valid_images = images_LV[:,:,:val_data_size]
train_images = images_LV[:,:,val_data_size:]
valid_masks = masks[:,:,:val_data_size]
train_masks = masks[:,:,val_data_size:]
when I tried to fit the model using this:
model.fit(train_images , train_masks, epochs=2, batch_size=8)
I end up this error which says the input should be 4 dimensions:
Error when checking input: expected input_6 to have 4 dimensions, but got array with shape (80, 80, 2400)
I tried to reshape the input to 4 dimensions using:
images_LV = np.reshape(images_LV, (-1, 80,80,2900))
but I got other error:
Error when checking input: expected input_6 to have shape (80, 80, 1) but got array with shape (80, 80, 2400)
I think that the input should be like (2900,80,80,1)?
if you need more information I can share.
I found the solution. I wanted to post the answer to those may have the same issue:
based on the shape of my dataset, (80,80,2900), I needed to change the dimension from 3 to 4. Also, it was necessary to reshape the dataset as follow:
***images = np.swapaxes(images, 0, 2)
images = np.swapaxes(images, 1, 2)
images = np.reshape(images, (-1, 80,80,1))
print(images.shape)
\\(2900, 80, 80, 1)***
After above change, I simply pass the data as the input of the model:
***train_images = images[val_data_size:,:,:,:]
model.fit(train_images , train_masks, epochs=5, batch_size=8)***

Externally adding another layer to convolution output

I have a network in which the data comes from a stack of images and a vector of numbers.
I begin with two "branches": The images go through several convolutions and produce an output of shape (50, 50, 64). In the other branch I import the number and go:
x = Input(shape = (13)) # data vector is of length 13
x = Dense(50*50)(x)
x = Reshape((50,50))(x)
I now have 2 outputs from the branches - one is of shape (50, 50, 64) and the other of shape (50, 50, 1). How can I "stick" them together to get a collective (50, 50, 65) which I'd then Deconv2D?
You could use the keras Concatenate() layer as in follows:
import numpy as np
from keras import backend as K
from keras import layers
# create some dummy tensors with numpy and the keras backend
arr1 = K.constant(np.zeros((50, 50, 1)))
arr2 = K.constant(np.zeros((50, 50, 64)))
# and this is how you call the concatenate layer
combined = layers.Concatenate()([arr1, arr2])
# it should print this:
# Tensor("concatenate_1/concat:0", shape=(50, 50, 65), dtype=float32)
print(combined)
you can use numpy function : np.c_
try:
>>> x.shape
(50, 50, 64)
>>> y.shape
(50, 50, 1)
>>> z = np.c_[x,y]
>>> z.shape
(50, 50, 65)

How to reshape image array?

currently I'm working on a neural network that can classify the numbers in the Street View House Number dataset (http://ufldl.stanford.edu/housenumbers/). For now, I'm just trying to do it on the second format, the one similar to the MNIST dataset.
The problem I've encountered is that the shapes of the train and test arrays of examples are (HEIGHT, WIDTH, CHANNELS, EXAMPLES) rather than (EXAMPLES, HEIGHT, WIDTH, CHANNELS).
Is there a simple way to reshape the array to what I want without using many nested loops?
I'm not sure if the object you are trying to reshape is a Tensor or numpy.ndarray.
If it is a numpy.ndarray, you can use np.transpose. For example:
import numpy as np
a = np.zeros((299, 299, 3, 50))
print(a.shape) # (299, 299, 3, 50) H x W x C x M
b = np.transpose(a, [3, 0, 1, 2])
print(b.shape) # (50, 299, 299, 3)
If it is a Tensor, You can use tf.transpose to change the order of the dimension in exactly the same way as np.transpose. For example:
import tensorflow as tf
a = tf.zeros((299, 299, 3, 50), dtype=tf.int32)
print(a.shape.as_list()) # [299, 299, 3, 50]
b = tf.transpose(a, [3, 0, 1, 2])
print(b.shape.as_list()) # [50, 299, 299, 3]

Categories