Related
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):
I am new to Deep learning and trying to develop LSTM for COVID-19 time series prediction based on the number of confirmed cases.
Here is my dataset:
dataset
I tried the below parameters. However, I got all results less than one.
Can you please help me?
X_train1, y_train1 = X1[:500], y1[:500]
X_val1, y_val1 = X1[500:550], y1[500:550]
X_test1, y_test1 = X1[550:], y1[550:]
X_train1.shape, y_train1.shape, X_val1.shape, y_val1.shape,
X_test1.shape, y_test1.shape
((500, 5, 1), (500,), (50, 5, 1), (50,), (218, 5, 1), (218,))
model1 = Sequential()
model1.add(InputLayer((5, 1)))
model1.add(LSTM(64))
model1.add(Dense(8, 'relu'))
model1.add(Dense(1, 'linear'))
cp1 = ModelCheckpoint('model1/', save_best_only=True)
model1.compile(loss=MeanSquaredError(), optimizer=Adam(learning_rate=0.0001), metrics=[RootMeanSquaredError()])
model1.fit(X_train1, y_train1, validation_data=(X_val1, y_val1), epochs=10, callbacks=[cp1])
please check this picture for the results sample:
results sample
It would be nice if you could share more of your code. My hunch is that you are normalizing data during training, so the model's predictions are normalized as well. De-normalizing them may give you your desired results.
Reshape your input training, validation and testing data to to be 3D [samples, timesteps, features]:
X_train1 = X_train1.reshape((X_train1.shape[0], 1, X_train1.shape[1]))
X_val1 = X_val1.reshape((X_val1.shape[0], 1, X_val1.shape[1]))
X_test1 = X_test1.reshape((X_test1.shape[0], 1, X_test1.shape[1]))
X_train1.shape, y_train1.shape, X_val1.shape, y_val1.shape,
X_test1.shape, y_test1.shape
# Output (500, 1, 5), (500,), (50, 1, 5), (50,), (218, 1, 5), (218,)
such as the input shape=[1,64,12,60,33]
when i use
nn.Conv3d(in_channels=128, out_channels=64, kernel_size=(3, 3, 3), stride=2, padding=1)
the out put shape =[1,64,6,30,17]
after that i want to let the output return to [1,64,12,60,33]
but when i use
nn.ConvTranspose3d(in_channels=128, out_channels=64, kernel_size=(3, 3, 3), stride=2, padding=1,output_padding=1)
the out put become to [1, 64, 12, 60, 34] that is not i want.
how can i fixed this problem? i mean i want the nextwork doesn't matter the input's shape(of course i don't use dense layer, just conv and deconv)
for example:
input = torch.randn((1,64,12,60,33))
C3d=torch.nn.Conv3d(64,64,kernel_size=(3,3,3),stride=2 ,padding=1)
output_conv = C3d(input)#shape==[1,64,6,30,17]
de_C3d = torch.nn.ConvTranspose3d(64,64,(3,3,3),stride=2,padding=1)
output_deconv=de_C3d(out_conv) #shape = [1,64,11,59,33]
i just want the output_deconv.shape equal to input
If you're dealing with tensors of arbitrary shapes, this can be difficult. If they're fixed you can add ad hoc fixes which should solve your problem. One way is to utilise the fact that you can pass tuples to the arguments padding and output_padding, which will work in your case:
input = torch.randn((1,64,12,60,33))
C3d=torch.nn.Conv3d(64,64,kernel_size=(3,3,3),stride=2 ,padding=1)
output_conv = C3d(input) #shape==[1,64,6,30,17]
de_C3d = torch.nn.ConvTranspose3d(64,64,(3,3,3),stride=2,padding=1,output_padding=(1,1,0))
output_de=de_C3d(out_conv) #shape = [1,64,12,60,33]
You could also pad and then crop, which is commonly done in UNet architectures:
de_C3d = torch.nn.ConvTranspose3d(64,64,(3,3,3),stride=2,padding=0)
output_deconv=de_C3d(out_conv) #shape = [1,64,13,61,35]
output_deconv = output_deconv[:,:,:input.shape[2],:input.shape[3],:input.shape[4]]
I guess one way to fix this is to add different padding to the inputs depending on whether they're odd or even:
de_C3d = torch.nn.ConvTranspose3d(64,64,(3,3,3),stride=2,padding=1,
output_padding=tuple([(i+1)%2 for i in input.shape[2:]]))
output_deconv=de_C3d(out_conv) #shape = [1,64,12,60,33]
I am new to keras.
My goal is to have total of 4 max pooling layers. All of them take same input with shape (N, 256). The first layer does global max pooling and give 1 output. The second layer with N / 2 pooling size and N / 2 stride, gives 2 outputs. The third gives 4 outputs and the fourth gives 8 outputs. Here is my code.
test_x = np.random.rand(N, 256, 1)
model = Sequential()
input1 = Input(shape=test_x.shape, name='input1')
input2 = Input(shape=test_x.shape, name='input2')
input3 = Input(shape=test_x.shape, name='input3')
input4 = Input(shape=test_x.shape, name='input4')
max1 = MaxPooling2D(pool_size=(N, 256), strides=N)(input1)
max2 = MaxPooling2D(pool_size=(N / 2, 256), strides=N / 2)(input2)
max3 = MaxPooling2D(pool_size=(N / 4, 256), strides=N / 4)(input3)
max4 = MaxPooling2D(pool_size=(N / 8, 256), strides=N / 8)(input4)
mrg = Merge(mode='concat')([max1, max2, max3, max4])
After creating 4 max pooling layers, I try to merge them together, but keras gives this error.
ValueError: Dimension 1 in both shapes must be equal, but are 4 and 8 for 'merge_1/concat' (op: 'ConcatV2') with input shapes: [?,1,1,1], [?,2,1,1], [?,4,1,1], [?,8,1,1], [] and with computed input tensors: input[4] = <3>.
How can I solve this issue? Is merging the correct way to achieve my goal in keras?
For concatenation, all dimensions must have the same number of elements, except for the concat dimension itself.
As you can see, your results have shape:
(?, 1, 1, 1)
(?, 2, 1, 1)
(?, 4, 1, 1)
(?, 8, 1, 1)
Naturally, the only possible way to concatenate them is in the second axis (axis=1)
mrg = Concatenate(axis=1)([max1,max2,max3,max4])
But notice that (unless you have specific reasons for that and know exaclty what you're doing) this will result in a very weird image, since you're concatenating in a spatial dimension, not in a channel dimension.
I've been searching for a way to visualize parameters in Caffe after traning the network, I found this link. it send a transpose of parameter with
filters = net.params['conv1'][0].data
vis_square(filters.transpose(0, 2, 3, 1))
Which i don't understand why it transpose the data? and in the vis_square it use this code:
data = data.reshape((n, n) + data.shape[1:]).transpose((0, 2, 1, 3) + tuple(range(4, data.ndim + 1)))
data = data.reshape((n * data.shape[1], n * data.shape[3]) + data.shape[4:])
Which is too compressed to understand, any explanation would be appreciated. and then when i changed the code to get conv2 instead of conv1:
filters = net.params['conv2'][0].data
vis_square(filters.transpose(0, 2, 3, 1))
I get
TypeError: Invalid dimensions for image data
, Is there any different between conv1 and conv2 which cause this error ? How can we change the code to fix it and it work for all layer ?
Some debugging data :
net.params['conv1'][0].data.shape : (96, 3, 11, 11)
net.params['conv1'][1].data.shape : (96,)
net.params['conv2'][0].data.shape : (256, 48, 5, 5)
net.params['conv2'][1].data.shape : (256,)
net.params['conv3'][0].data.shape : (384, 256, 3, 3)
net.params['conv3'][1].data.shape : (384,)
for conv2:
data.shape[0] : 256
np.sqrt(data.shape[0]) : 16.0
np.ceil(np.sqrt(data.shape[0])) : 16.0
data.shape[0] : 256
data.shape[0:] : (256, 6, 6, 48)
data.shape[1] : 6
data.shape[1:] : (6, 6, 48)
data.ndim : 4
range(4, data.ndim + 1)) : [4]
tuple(range(4, data.ndim + 1)) : (4,)
AND after :
data = np.pad(data, padding, mode='constant', constant_values=1)
for conv2:
data.shape : (10, 12, 10, 12, 3)
and after
data = data.reshape((n, n) + data.shape[1:]).transpose((0, 2, 1, 3) + tuple(range(4, data.ndim + 1)))
data became :
data.shape : (120, 120, 3)
The code you inspected is written to visualize (i.e., convert to RGB image) convolutional filters.
The shape of conv1 filters (in your example) is (96, 3, 11, 11) which means
- 96 : you have 96 filters in conv1 of your net (i.e., num_output: 96), therefore you would wish to view 96 different filters.
- 3 : the input dimension of each filter is 3, because the input to conv1 in your net is an RGB image with three channels.
- 11, 11: the spatial size of each kernel/filter in your case is 11x11 (i.e., kernel_size: 11).
Therefore, to visualize 96 filters as 11x11x3 thumbnails.
However, when trying to visualize conv2 (or any other deeper layer) you have a problem. There is no longer RGB meaning to filter dimensions. The filters of conv2 work on the output feature of conv1 (which in your case is a 96-dim space). To date, AFAIK, there is no straight-forward way to convert a 96-dim data to a simple 3D RGB representation.
So, you cannot use the same code to visualize conv2 filters. You must use some other method for visualization.