I am trying to predict the of number peaks in time series data by using a CNN and keep on getting a data shape error. My data looks as follows:
X = list of 520 lists (each is a time series) of various lengths (shortest = 137 elements, longest = 2297 elements)
y = list with 520 elements, each being the number of peaks for the respective time series
Due to the various lengths of the time series, I padded X. The shapes of X_train and X_test, after converting them from numpy arrays to tensors are:
X_train.shape = TensorShape([390, 2297])
X_test.shape = TensorShape([130, 2297])
I am new to keras and I am very unsure about the input_size in the first Conv1D layer. According to this post (Keras/Tensorflow Conv1D expected input shape) I chose it as (2297, 1) or (520, 1), but none of them works. The documentation of Keras says that the input shape should be (batch_size, feature_size, channels), where batch_size is omitted though.
from sklearn.model_selection import train_test_split
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras.layers import *
from tensorflow.keras.optimizers import Adam
#for structure of X and y, see explanation above
X_padded = tf.keras.preprocessing.sequence.pad_sequences(X)
X_train, X_test, y_train, y_test = train_test_split(X_padded, y, test_size=0.25, random_state=33)
X_train = tf.convert_to_tensor(X_train)
X_test = tf.convert_to_tensor(X_test)
y_train = tf.convert_to_tensor(y_train)
y_test = tf.convert_to_tensor(y_test)
model = keras.Sequential()
model.add(Conv1D(filters=16, kernel_size=3, activation = 'relu', strides = 1, padding = 'same', input_shape=(2297, 1)))
model.add(Dropout(0.1))
model.add(Conv1D(filters=32, kernel_size=3, activation = 'relu', strides = 1, padding = 'same'))
model.add(Dropout(0.2))
model.add(Flatten())
model.add(Dense(9, activation='softmax')) # '9' because there are 9 possible peak counts in the data
model.compile(optimizer=Adam(learning_rate = 0.001), loss = 'sparse_categorical_crossentropy', metrics = ['accuracy'])
progress = model.fit(X_train, y_train, epochs = 15, validation_data = (X_test, y_test), verbose=1)
Error:
ValueError: Input 0 of layer sequential is incompatible with the layer: expected ndim=3, found ndim=2. Full shape received: [None, 2297]
What might be the issue here?
I was able to solve it. The correct input shape is given here Convolutional neural network Conv1d input shape in the answer of user 'rnso'.
I shaped my X_train and X_test (being numpy.arrays) as
X_train = X_train.reshape(X_train.shape[0], X_train.shape[1], 1)
X_test = X_test.reshape(X_test.shape[0], X_test.shape[1], 1)
and stated the input_shape in the Conv1D statement as input_shape=(ncols, 1)
input_shape=(2297, 1)
Related
i'm a deep learning enthusiasts, and i want finetune the keras.application deep model to train a new model, but something wrong. And the code is :
import keras.applications.resnet_v2
from keras.applications.resnet_v2 import ResNet50V2
from keras.applications.resnet_v2 import preprocess_input, decode_predictions
import numpy as np
import keras
import tensorflow as tf
from keras.layers import Dense, Input
from keras.models import Model
import os
mnist = tf.keras.datasets.mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()#train_szie :(60000, 28, 28)
print(x_train.shape)#(60000, 28, 28)
print(y_train.shape)#(60000,)
x_train = [cv2.cvtColor(cv2.resize(img,(28,28)),cv2.COLOR_GRAY2BGR) for img in x_train]
x_train = np.asarray(x_train)
x_test = [cv2.cvtColor(cv2.resize(img,(28,28)),cv2.COLOR_GRAY2BGR) for img in x_test]
x_test = np.asarray(x_test)
x_train, x_test = x_train / 255.0, x_test / 255.0
base_model = ResNet50V2( weights='imagenet', include_top = False)
x = base_model.get_layer("conv2_block1_preact_bn").output
x = Dense(1024, activation='relu')(x)
predictions = Dense(200, activation='softmax')(x)
model = Model(inputs=base_model.input, outputs=predictions)
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
model.fit(x_train, y_train, epochs=1)
when i run it, the code is error,named
"res = tf.nn.sparse_softmax_cross_entropy_with_logits(
Node: 'sparse_categorical_crossentropy/SparseSoftmaxCrossEntropyWithLogits/SparseSoftmaxCrossEntropyWithLogits'
logits and labels must have the same first dimension, got logits shape [1568,10] and labels shape [32]
[[{{node sparse_categorical_crossentropy/SparseSoftmaxCrossEntropyWithLogits/SparseSoftmaxCrossEntropyWithLogits}}]] [Op:__inference_train_function_4157]"
but when i write the code, is now running fine.
x = base_model.output
I don't know why,i need your help, thanks
Quite a few changes required in your code and has multiple issues.
You're missing a Flatten layer in the middle. Because of that, when computing loss (with a 1D vector of labels), tensorflow squash all of the dimensions except the last together giving [7 x 7 x32 = 1568, 200] sized set of logits. Here 7x7 is the output width and height for a 28x28 sized input by your last conv layer. 32 is default batch size when using model.fit(). This is not compatible with the labels which would simply be a 32 item 1d vector in one iteration.
base_model = ResNet50V2(weights='imagenet', include_top = False)
# Input the way you've defined has undefined width and heigh
# dimension. This is an important requirement for the Flatten layer downstream
input = Input(shape=(28,28,3))
x = input
# Getting only the layers we care about
for layer in base_model.layers:
x = layer(x)
if layer.name == "conv2_block1_preact_bn":
break
# Before feeding data into the dense layer, you need to flatten
x = Flatten()(x)
x = Dense(1024, activation='relu')(x)
predictions = Dense(200, activation='softmax')(x)
model = Model(inputs=input, outputs=predictions)
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
One concern I have is that mnist has 10 classes, so your last layer should only need 10 not 200
I'm trying to make a binary Classification by combining CNN (con1D) with GRU. my dataset dataset is like that :
X_train shape : (223461, 5)
y_train shape :(223461,)
the X_train is like that and the Y_train is a labels (0,1) like that
first I convert that train dataset :
dataset = X_train.values
dataset=dataset[1:]
dataset = dataset.astype('float32')
dataset
the same for y-train:
dataset_target = y_train.values
dataset_target=dataset_target[1:]
dataset_target = dataset_target.astype('float32')
dataset_target
now the shapes are dataset.shape =(223460, 5)
, dataset_target.shape = (223460,)
than my model structure is :
verbose, epochs, batch_size = 0, 100, 64
n_timesteps, n_features, n_outputs = dataset.shape[0], dataset.shape[1], dataset_target.shape[0]
model = Sequential()
model.add(Conv1D(filters=64, kernel_size=3, activation='relu', input_shape= (n_timesteps,n_features)))
model.add(MaxPooling1D(pool_size=2))
model.add(GRU(64))
model.add(Dropout(0.4))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.4))
model.add(Dense(1, activation='sigmoid'))
opt = Adam(learning_rate=0.01)
model.compile(loss=tf.keras.losses.BinaryCrossentropy(), optimizer=opt , metrics=['accuracy'])
model.summary()
and when I want to fit dataset to my model:
# fit network
model.fit(dataset, dataset_target, epochs=epochs, batch_size=batch_size, verbose=1)
# evaluate model
_, accuracy = model.evaluate(X_test, y_test, batch_size=batch_size, verbose=1)
#accuracy
I get an error Input 0 of layer "sequential" is incompatible with the layer: expected shape=(None, 223460, 5), found shape=(64, 5)
Is the first axis of the dataset (233460 samples) actually time steps, and do you have 5 'channels' of data? In that case, it would help if you slice the dataset along the first axis and then assign to each 'slice' single label, for example, the last value related to the slice from the y_train. In that case, n_timesteps would be the length of the slice, and the shape of the dataset something like (n_samples, n_timesteps, 5). Basically, Conv1D expects each training sample to be 2D, but in you case it's 1D, because the first dimension is just a number of samples.
I might have interpreted the dataset the wrong way. In that case, please clarify how it works so I would fix my suggestion.
Here's the example:
import tensorflow as tf
import tensorflow.keras as keras
from tensorflow.keras.layers import Conv1D, MaxPooling1D, GRU, \
Dropout, Flatten, Dense
from tensorflow.keras import Sequential
from tensorflow.keras.optimizers import Adam
import numpy as np
X_train = np.random.normal(0, 1, (223461, 5))
y_train = np.random.randint(0, 2, 223461)
dataset = X_train[1:]
dataset_target = y_train[1:]
n_timesteps = 10
# Slice dataset and target
dataset = np.stack(np.split(dataset, n_timesteps)[:-1])
dataset_target = np.stack([y[-1] for y in np.split(dataset_target, n_timesteps)[:-1]])
Define and train the model:
def get_model(dataset, n_timesteps):
verbose, epochs, batch_size = 0, 100, 64
n_timesteps, n_features = dataset.shape[1], dataset.shape[2]
model = Sequential()
model.add(Conv1D(filters=64, kernel_size=3, activation='relu', input_shape = (n_timesteps, n_features)))
model.add(MaxPooling1D(pool_size=2))
model.add(GRU(64))
model.add(Dropout(0.4))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.4))
model.add(Dense(1, activation='sigmoid'))
opt = Adam(learning_rate=0.01)
model.compile(loss=tf.keras.losses.BinaryCrossentropy(), optimizer=opt , metrics=['accuracy'])
model.summary()
return model
verbose, epochs, batch_size = 0, 1, 64
model = get_model(dataset, n_timesteps)
model.fit(dataset, dataset_target, epochs=epochs, batch_size=batch_size, verbose=1)
Hope it helps!
I am getting into Convolutional Neural Networks and want to create one for MNIST data. Whenever I add a convolutional Layer to my CNN, I get an error:
Input 0 is incompatible with layer conv2d_4: expected ndim=4, found ndim=5
I have attemped to reshape X_Train data set but was not successful
I tried to add a flatten layer first but that returns this error:
Input 0 is incompatible with layer conv2d_5: expected ndim=4, found ndim=2
import keras
from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.layers import Convolution2D
from keras.layers import Flatten, Dense, Dropout
img_width, img_height = 28, 28
mnist = keras.datasets.mnist
(X_train, Y_train), (X_test, Y_test) = mnist.load_data()
(X_train, y_train), (X_test, y_test) = mnist.load_data()
X_train = keras.utils.normalize(X_train, axis=1) #Normalizes from 0-1 (originally each pixel is valued 0-255)
X_test = keras.utils.normalize(X_test, axis=1) #Normalizes from 0-1 (originally each pixel is valued 0-255)
Y_train = keras.utils.to_categorical(Y_train) #Reshapes to allow ytrain to work with x train
Y_test = keras.utils.to_categorical(Y_test)
from sklearn import preprocessing
lb = preprocessing.LabelBinarizer()
Y_train = lb.fit_transform(Y_train)
Y_test = lb.fit_transform(Y_test)
#Model
model = Sequential()
model.add(Flatten())
model.add(Convolution2D(16, 5, 5, activation='relu', input_shape=(1,img_width, img_height, 1)))
model.add(Dense(128, activation='relu'))
model.add(Dense(128, activation='relu'))
model.add(Dropout(.2))
model.add(Dense(64, activation='relu'))
model.add(Dense(10, activation='softmax'))
model.compile(optimizer = 'adam',
loss='categorical_crossentropy',
metrics=['accuracy'])
model.fit(X_train, Y_train, epochs=3, verbose=2)
val_loss, val_acc = model.evaluate(X_test, Y_test) #Check to see if model fits test
print(val_loss, val_acc)
If I comment out the Convolutional layer, it works very well (accuracy>95%), but I am planning on making a more complex neural network that requires Convolution in the future and this is my starting point
Keras is looking for a tensor of dimension 4 but it's getting ndim as number of dimension as 2.
first make sure you kernel size in Conv2D layer is in parenthesis
model.add(Convolution2D(32, (3, 3), activation='relu', input_shape=(img_height, img_height, 1)))
Second you need to reshape the X_train, X_test variable as Conv2D layer is expecting a tensor input.
X_train = X_train.reshape(-1,28, 28, 1) #Reshape for CNN - should work!!
X_test = X_test.reshape(-1,28, 28, 1)
model.fit(X_train, Y_train, epochs=3, verbose=2)
For more information about Conv2D you can look into Keras Documentation here
Hope this helps.
There are two issues in your code.
You are encoding your labels two times, once using to_categorical, and another time using LabelBinarizer. The latter is no needed here, so just encode your labels into categorical once, using to_categorical.
2.- Your input shape is incorrect, it should be (28, 28, 1).
Also you should add a Flatten layer after the convolutional layers so the Dense layer works properly.
I have the following code that creates LSTM network using Keras with TensorFlow backend.
This code runs well.
import numpy as np
import pandas as pd
from sklearn import model_selection
from keras.models import Sequential
from keras.layers import Dense, Activation, Dropout
from keras.layers.recurrent import LSTM
from keras.utils import np_utils
flights = {
'flight_stage': [1,0,1,1,0,0,1],
'scheduled_hour': [16,16,17,17,17,18,18],
'delay_category': [1,0,2,2,1,0,2]
}
columns = ['flight_stage', 'scheduled_hour', 'delay_category']
df = pd.DataFrame(flights, columns=columns)
X = df.drop('delay_category',1)
y = df['delay_category']
X_train, X_test, y_train, y_test = model_selection.train_test_split(X, y, test_size=0.25, random_state=42)
nb_features = X_train.shape[1]
nb_classes = y.nunique()
hidden_neurons = 32
timestamps = X_train.shape[0]
# Reshape input data to 3D array
X_train = X_train.values.reshape(1, X_train.shape[0], X_train.shape[1])
X_test = X_test.values.reshape(1, X_test.shape[0], X_test.shape[1])
y_train = np_utils.to_categorical(y_train, nb_classes)
y_test = np_utils.to_categorical(y_test, nb_classes)
model = Sequential()
model.add(LSTM(
units=hidden_neurons,
return_sequences=True,
input_shape=(timestamps,nb_features)
)
)
model.add(Dropout(0.2))
model.add(Dense(activation='softmax', units=nb_classes))
model.compile(loss="categorical_crossentropy",
optimizer='adadelta')
But when I start training the model, it fails:
history = model.fit(X_train, y_train, validation_split=0.25, epochs=500, batch_size=2, shuffle=True, verbose=0)
Error:
ValueError: Error when checking target: expected dense_19 to have 3 dimensions, but got array with shape (5, 3)
This error refers to the final Dense layer. I used model.summary() to get exact dimensions. The output shape of a Dense layer is (None, 5, 3).
However I do not understand why does it have 3 dimensions and what None stands for (how did it appear in this last layer)?
3 is the number of units returned by the last layer. It is the number of classes for the softmax activation
5 is the number of units returned by the lstm which indicates the size of the sequences returned
None is the number of element by batch for the last layer. It simply means that the last layer can accept different size for each batches of tensor of shape [5, 3]
X_train shape: (1, 5, 2),
X_test shape: (1, 2, 2),
y_train shape: (5,3),
y_test shape: (2,3)
Looking at the data shape, there is clearly a mismatch between the batchsize of the features and that of the labels. The most left number should be equal between the features shape X and the labels shape y. It is the batchsize.
'1', 5, 2 => batch size of 1
'2', 3 => batch size of 2
There is a mismatch here.
Also to solve the issue between the output of the lstm layer and the input of the last layer, one can use a layer.flatten
nb_classes = 3
hidden_neurons = 32
model = Sequential()
model.add(LSTM(
units=hidden_neurons,
return_sequences=True,
input_shape=(5, 2)
)
)
model.add(Dropout(0.2))
model.add(Flatten())
model.add(Dense(activation='softmax', units=nb_classes))
model.compile(loss="categorical_crossentropy",
optimizer='adadelta')
model.compile(loss='categorical_crossentropy',
optimizer='adam')
live code
I have a dataset of 3000 observations. Each observation consists of 3 timeseries of length 200 samples. As the output I have 5 class labels.
So I build train as test sets as follows:
test_split = round(num_samples * 3 / 4)
X_train = X_all[:test_split, :, :] # Start upto just before test_split
y_train = y_all[:test_split]
X_test = X_all[test_split:, :, :] # From test_split to end
y_test = y_all[test_split:]
# Print shapes and class labels
print(X_train.shape)
print(y_train.shape)
> (2250, 200, 3)
> (22250, 5)
I build my network using Keras functional API:
from keras.models import Model
from keras.layers import Dense, Activation, Input, Dropout, concatenate
from keras.layers.recurrent import LSTM
from keras.constraints import maxnorm
from keras.optimizers import SGD
from keras.callbacks import EarlyStopping
series_len = 200
num_RNN_neurons = 64
ch1 = Input(shape=(series_len, 1), name='ch1')
ch2 = Input(shape=(series_len, 1), name='ch2')
ch3 = Input(shape=(series_len, 1), name='ch3')
ch1_layer = LSTM(num_RNN_neurons, return_sequences=False)(ch1)
ch2_layer = LSTM(num_RNN_neurons, return_sequences=False)(ch2)
ch3_layer = LSTM(num_RNN_neurons, return_sequences=False)(ch3)
visible = concatenate([
ch1_layer,
ch2_layer,
ch3_layer])
hidden1 = Dense(30, activation='linear', name='weighted_average_channels')(visible)
output = Dense(num_classes, activation='softmax')(hidden1)
model = Model(inputs= [ch1, ch2, ch3], outputs=output)
# Compile model
model.compile(loss='categorical_crossentropy', optimizer=SGD(), metrics=['accuracy'])
monitor = EarlyStopping(monitor='val_loss', min_delta=1e-4, patience=5, verbose=1, mode='auto')
Then, I try to fit the model:
# Fit the model
model.fit(X_train, y_train,
epochs=epochs,
batch_size=batch_size,
validation_data=(X_test, y_test),
callbacks=[monitor],
verbose=1)
and I get the following error:
ValueError: Error when checking model input: the list of Numpy arrays that you are passing to your model is not the size the model expected. Expected to see 3 array(s), but instead got the following list of 1 arrays...
How should I reshape my data, to solve the issue?
You magically assume a single input with 3 time series X_train will split into 4 channels and be assigned to different inputs. Well this doesn't happen and that is what the error is complaining about. You have 1 input:
ch123_in = Input(shape=(series_len, 3), name='ch123')
latent = LSTM(num_RNN_neurons)(ch123_in)
hidden1 = Dense(30, activation='linear', name='weighted_average_channels')(latent)
By merging the series together into single LSTM, the model might pickup relations across time series as well. Now your target shape has to be y_train.shape == (2250, 5), the first dimension must match X_train.shape[0].
Another point is you have Dense layer with linear activation, that is almost useless as it doesn't provide any non-linearity. You might want to use a non-linear activation function like relu.