I am attempting a CNN for classification of biological data (EEG data). However, after importing and splitting the data into train/test/dev sets and building the CNN, I cannot get the input array shape to match the expected array shape.
Note: Data contains 5 trials/samples for each participant(ID's) in the study, so GSS was used to ensure data from each participant was not mixed train and test sets.
Code and error as follows:
#Load Data
def load_all_data(filename):
import numpy as np
a = np.load(filename)
d = (dict(zip(("data1{}".format(k) for k in a), (a[k] for k in a))))
return d
filename = ("dataname.npz")
X = load_all_data(filename)['array_0']
y = load_all_data(filename)['array_1']
IDs = load_all_data(filename)['array_2']
#Split Test Data with Groupshuffle Split
from sklearn.model_selection import GroupShuffleSplit
import numpy as np
test_size = 0.2
gss = GroupShuffleSplit(n_splits = 1, test_size = 0.2)
for train,test in gss.split(X, y, IDs):
X_train = X[train]
y_train = y[train]
IDs_train = IDs[train]
X_test = X[test]
y_test = y[test]
IDs_test = IDs[test]
fileoutname = 'train_test_data'
np.savez(fileoutname,X_train, y_train, X_test, y_test,IDs_train,IDs_test)
#Split Train, Test Data
gss = GroupShuffleSplit(1, test_size)
for train,test in gss.split(X, y, IDs):
X_train2 = X[train]
y_train2 = y[train]
IDs_train = IDs[train]
X_dev = X[test]
y_dev = y[test]
IDs_test = IDs[test]
#Add dimension to X and Convert y to Categorical
X_train2 = np.expand_dims(X_train2,axis=0)
y_train2 = keras.utils.to_categorical(y_train2,num_classes=2)
X_dev = np.expand_dims(X_test,axis=0)
y_dev = keras.utils.to_categorical(y_test,num_classes=2)
X = np.expand_dims(X,axis=0)
#Build the CNN
def simpleCNN(self, units = 10):
import keras
from keras.layers import Dense
from keras.layers import Conv2D
from keras.layers import Flatten
from keras.models import Model, Input
inp = Input(shape = self.shape[1:], name='inp')
#layer 1
x = Conv2D(units, kernel_size=(1,1), strides = (1,1), activation='relu', data_format='channels_last')(inp)
#layer 2
x = Conv2D(units, kernel_size=(2,2), strides = (1,1), activation='relu', data_format='channels_last')(x)
#layer 3
x = Flatten()(x)
#layer4
out = Dense(2, activation='softmax',name='out')(x)
model = Model(inputs = inp, outputs = out)
return model
#Fit the Data
model = simpleCNN(X)
from keras.optimizers import Adamax
adamax = Adamax(lr=3e-4, beta_1=0.9, beta_2=0.999, epsilon=1e-08, decay=0.0); #3e-4; 2e-3 is a default.
model.compile(optimizer=adamax, loss='categorical_crossentropy', metrics=['acc'])
model.fit(X_train2, y_train2, epochs=20, batch_size=32, verbose = 1, validation_data = (X_dev, y_dev))
ValueError: Error when checking input: expected inp to have shape (11459, 26, 60) but got array with shape (9065, 26, 60)
Related
I wanna use predictions in real time, but I want to test that the results are the same as in the case of giving all the data as input only once. This is the code:
import numpy as np
from keras.layers import Input, Dense, SimpleRNN
from keras.models import Model
#MODEL 1, for training
x = Input(shape=(None, 1))
h = SimpleRNN(30, return_sequences=True)(x)
out = Dense(1)(h)
model = Model(x, out)
model.compile(loss='mse', optimizer='adam')
X_train = np.random.rand(100, 50, 1)
y_train = np.random.rand(100, 50, 1)
model.fit(X_train, y_train, verbose = False)
#MODEL 1, for predictions in real time
x = Input(batch_shape=(1, None, 1))
h = SimpleRNN(30, stateful=True, return_sequences=True)(x)
out = Dense(1)(h)
predict_model = Model(x, out)
predict_model.set_weights(model.get_weights())
X = np.random.rand(2, 2, 1)
predictions = model.predict(X, verbose = False)
for sim in range(len(predictions)):
for i in range(len(predictions[0])):
pred = predict_model.predict(X[sim:(sim+1), i:(i + 1), :], verbose = False)
print(pred[0][0]) #Predictions in real time
print(predictions[sim][i]) #Predictions with MODEL 1
print()
predict_model.reset_states()
It prints this:
[0.09156141]
[0.09156139]
[-0.38076958]
[-0.38076955]
[0.12214336]
[0.12214339]
[-0.52013564]
[-0.5201356]
The results must be exactly the same because both have the same weights. What is happening?
I'm currently playing around with a basic LSTM-based Autoencoder using the Tensorflow library. The goal is for the Autoencoder to reconstruct multivariate time-series. I'm interested in moving the feature-wise normalization of the data from the data pipeline to inside the model.
Currently I normalize data the following way:
normalizer = Normalization(axis=-1)
normalizer.adapt(data_train)
data_train = normalizer(data_train)
inputs = Input(shape=[None, n_inputs])
x = LSTM(4, return_sequences=True)(inputs)
x = LSTM(2, return_sequences=True)(x)
x = LSTM(2, return_sequences=True)(x)
x = LSTM(4, return_sequences=True)(x)
x = TimeDistributed((Dense(n_inputs)))(x)
model = Model(inputs, x)
Which works as intended, leads to respectable loss (~1e-2) but is outside the model.
According to the documentation (under "Preprocessing data before the model or inside the model"), the following code should be equivalent to the above snippet, except that it runs inside the model:
normalizer = Normalization(axis=-1)
normalizer.adapt(data_train)
inputs = Input(shape=[None, n_inputs])
x = normalizer(inputs)
x = LSTM(4, return_sequences=True)(x)
x = LSTM(2, return_sequences=True)(x)
x = LSTM(2, return_sequences=True)(x)
x = LSTM(4, return_sequences=True)(x)
x = TimeDistributed((Dense(n_inputs)))(x)
model = Model(inputs, x)
However, running the latter variant leads to astronomical loss values (~1e3) and also worse results in testing. Hence my question is: what am I doing wrong? Could it be that I'm misunderstanding the documentation?
Any advice greatly appreciated!
The two methods seem to give consistent results as long as the normalizer is applied only to the inputs (i.e. to the feature matrix) when used outside the model:
import numpy as np
from tensorflow.keras import Input
from tensorflow.keras.layers import Dense, LSTM, TimeDistributed
from tensorflow.keras.models import Model
from tensorflow.keras.layers.experimental.preprocessing import Normalization
np.random.seed(42)
# define the input parameters
num_samples = 100
time_steps = 10
train_size = 0.8
# generate the data
X = np.random.normal(loc=10, scale=5, size=(num_samples, time_steps, 1))
y = np.mean(X, axis=1) + np.random.normal(loc=0, scale=1, size=(num_samples, 1))
# split the data
X_train, X_test = X[:np.int(train_size * X.shape[0]), :], X[np.int(train_size * X.shape[0]):, :]
y_train, y_test = y[:np.int(train_size * y.shape[0]), :], y[np.int(train_size * y.shape[0]):, :]
# normalize the inputs inside the model
normalizer = Normalization()
normalizer.adapt(X_train)
inputs = Input(shape=[None, 1])
x = normalizer(inputs)
x = LSTM(4, return_sequences=True)(x)
x = LSTM(2, return_sequences=True)(x)
x = LSTM(2, return_sequences=True)(x)
x = LSTM(4, return_sequences=True)(x)
x = TimeDistributed((Dense(1)))(x)
model = Model(inputs, x)
model.compile(loss='mae', optimizer='adam')
model.fit(X_train, y_train, batch_size=32, epochs=10, verbose=0)
print(model.evaluate(X_test, y_test))
# 10.704551696777344
# normalize the inputs outside the model
normalizer = Normalization()
normalizer.adapt(X_train)
X_train_normalized = normalizer(X_train)
X_test_normalized = normalizer(X_test)
inputs = Input(shape=[None, 1])
x = LSTM(4, return_sequences=True)(inputs)
x = LSTM(2, return_sequences=True)(x)
x = LSTM(2, return_sequences=True)(x)
x = LSTM(4, return_sequences=True)(x)
x = TimeDistributed((Dense(1)))(x)
model = Model(inputs, x)
model.compile(loss='mae', optimizer='adam')
model.fit(X_train_normalized, y_train, batch_size=32, epochs=10, verbose=0)
print(model.evaluate(X_test_normalized, y_test))
# 10.748750686645508
Suppose, I have a following dictionary constructed as below:
od = OrderedDict()
od['a'] = 1
od['b'] = 2
od['c'] = 3
od['d'] = 4
and let's say I need to pass this to the LSTM call() function. So, the code for model definition along with other code is as below:
import numpy
import matplotlib.pyplot as plt
from pandas import read_csv
import math
from tensorflow.keras.models import *
from tensorflow.keras.layers import Dense, Input
#from tensorflow.keras.layers import LSTM
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import mean_squared_error
# convert an array of values into a dataset matrix
def create_dataset(dataset, look_back=1):
dataX, dataY = [], []
for i in range(len(dataset)-look_back-1):
a = dataset[i:(i+look_back), 0]
dataX.append(a)
dataY.append(dataset[i + look_back, 0])
return numpy.array(dataX), numpy.array(dataY)
# fix random seed for reproducibility
numpy.random.seed(7)
# load the dataset
dataframe = read_csv('https://raw.githubusercontent.com/jbrownlee/Datasets/master/airline-passengers.csv', usecols=[1], engine='python')
dataset = dataframe.values
dataset = dataset.astype('float32')
# normalize the dataset
scaler = MinMaxScaler(feature_range=(0, 1))
dataset = scaler.fit_transform(dataset)
# split into train and test sets
train_size = int(len(dataset) * 0.67)
test_size = len(dataset) - train_size
train, test = dataset[0:train_size,:], dataset[train_size:len(dataset),:]
# reshape into X=t and Y=t+1
look_back = 1
trainX, trainY = create_dataset(train, look_back)
testX, testY = create_dataset(test, look_back)
# reshape input to be [samples, time steps, features]
trainX = numpy.reshape(trainX, (trainX.shape[0], 1, trainX.shape[1]))
testX = numpy.reshape(testX, (testX.shape[0], 1, testX.shape[1]))
# create and fit the LSTM network
# model = Sequential()
# model.add(LSTM(4, input_shape=(1, look_back)))
# model.add(Dense(1))
inp = Input(shape = (1, look_back), name = "Input")
#od_tensor = K.variable([od])
#inp2 = Input(tensor = od_tensor)
x = LSTM(4)([inp, od])
out = Dense(1)(x)
model = Model(inp, out)
model.compile(loss='mean_squared_error', optimizer='adam')
model.summary()
model.fit(trainX, trainY, epochs=100, batch_size=1, verbose=2)
Within the call() function of LSTM layer, I want to check, if the function is getting the inputs, so the code will be like below:
def call(self, inputs, mask=None, training=None, initial_state=None):
print("inputs[0]: ", inputs[0])
print("inputs[1]: ", inputs[1])
inputs_0 = inputs[0]
self._maybe_reset_cell_dropout_mask(self.cell)
return super(LSTM, self).call(
inputs_0, mask=mask, training=training, initial_state=initial_state)
The data structure will not change at any point during training, but will be used for some other processing purpose. Is there a way to get this working by passing the dictionary to the call function? How can this data structure be converted to tensor format?
I have this piece of code. But when I try to run the prediction value code there's an error
# Creating a data structure with n timesteps
X_test = []
for i in range(5, 25):
X_test.append(inputs[i-5:i, 0])
X_test = np.array(X_test)
# Reshape to a new dimension
X_test = np.reshape(X_test, (X_test.shape[0], X_test.shape[1], 1))
# Identify the predicted values
predicted_number = regressor.predict(X_test)
# Inverse the scaling to put them back to the normal values
predicted_number = sc.inverse_transform(predicted_number)
the error is like this
AttributeError Traceback (most recent call last)
<ipython-input-364-17fa061596c6> in <module>()
1 # Identify the predicted values
----> 2 predicted_number = regressor.predict(X_test)
3 # Inverse the scaling to put them back to the normal values
4 predicted_number = sc.inverse_transform(predicted_number)
5 KerasRegressor.model
~\Anaconda3\lib\site-packages\keras\wrappers\scikit_learn.py in predict(self, x, **kwargs)
320 """
321 kwargs = self.filter_sk_params(Sequential.predict, kwargs)
--> 322 preds = np.array(self.model.predict(x, **kwargs))
323 if preds.shape[-1] == 1:
324 return np.squeeze(preds, axis=-1)
AttributeError: 'KerasRegressor' object has no attribute 'model'
in case if needed, below is the full script
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
dataset_train = pd.read_csv('Datatraining.csv')
training_set = dataset_train.iloc[:, 1:2].values
from sklearn.preprocessing import MinMaxScaler
sc = MinMaxScaler(feature_range = (0, 1))
training_set_scaled = sc.fit_transform(training_set)
X_train = []
y_train = []
for i in range(60, 72):
X_train.append(training_set_scaled[i-60:i, 0])
y_train.append(training_set_scaled[i, 0])
X_train, y_train = np.array(X_train), np.array(y_train)
X_train = np.reshape(X_train, newshape = (X_train.shape[0], X_train.shape[1], 1))
from keras.models import Sequential
from keras.layers import Dense, LSTM, Dropout
regressor = Sequential()
# Adding the first LSTM layer and some Dropout regularisation
regressor.add(LSTM( units = 50, return_sequences = True, input_shape = (X_train.shape[1], 1) ))
regressor.add(Dropout(0.2))
# Adding the second LSTM layer and some Dropout regularisation
regressor.add(LSTM(units = 50, return_sequences = True))
regressor.add(Dropout(0.2))
# Adding the third LSTM layer and some Dropout regularisation
regressor.add(LSTM(units = 50, return_sequences = True))
regressor.add(Dropout(0.2))
# Adding the fourth LSTM layer and some Dropout regularisation
regressor.add(LSTM(units = 50))
regressor.add(Dropout(0.2))
regressor.add(Dense(units = 1))
regressor.compile(optimizer = 'adam', loss = 'mean_squared_error')
regressor.fit(X_train, y_train, epochs = 300, batch_size = 32)
dataset_test = pd.read_csv('Datatesting.csv')
real_number_arrivals = dataset_test.iloc[:, 1:2].values
dataset_total = pd.concat( (downloads['China'], dataset_test['China']), axis = 0 )
inputs = dataset_total[len(dataset_total) - len(dataset_test) - 72:].values
inputs = inputs.reshape(-1, 1)
inputs = sc.transform(inputs)
# Creating a data structure with n timesteps
X_test = []
for i in range(5, 25):
X_test.append(inputs[i-5:i, 0])
X_test = np.array(X_test)
# Reshape to a new dimension
X_test = np.reshape(X_test, (X_test.shape[0], X_test.shape[1], 1))
# Identify the predicted values
predicted_number = regressor.predict(X_test)
# Inverse the scaling to put them back to the normal values
predicted_number = sc.inverse_transform(predicted_number)
any solution would be really helpful. Thanks in advance
You have forgotten to fit the model first.
You did not share the whole code, but I believe you have some X_train and Y_train somewhere in your code. So try this line:
regressor.fit(X_train, Y_train)
And then you can run the prediction.
I'm trying to create CNN model using keras ad tensorflow as backend.
below is code for the same..
Cannot understand what input it is expecting...
import cv2,os
import glob
import numpy as np
from sklearn.utils import shuffle
from sklearn.cross_validation import train_test_split
from keras.utils import to_categorical
from keras.models import Sequential
from keras.layers import Input, Convolution2D, MaxPooling2D, Dense, Dropout, Flatten
PATH = os.getcwd()
data_path = PATH + '/data1/cat/*.PNG'
files = glob.glob(data_path)
X_data = []
for myFile in files:
image = cv2.imread (myFile)
image_resize = cv2.resize(image,(128,128))
X_data.append (image_resize)
image_data = np.array(X_data)
image_data = image_data.astype('float32')
image_data /= 255
print('X_data shape:', image_data.shape)
#Class ani labels
class_num = 2
total_Images = image_data.shape[0]
labels = np.ones((total_Images),dtype='int64')
labels[0:30] = 0
labels[31:] = 1
Y = to_categorical(labels,class_num)
#print(Y);
# Shuffle the dataset
x, y = shuffle(image_data, Y, random_state=2)
# Split the dataset
X_train, X_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=2)
input_shape = image_data[0].shape
#print(input_shape)
model = Sequential()
conv1 = Convolution2D(32,(3,3),padding='same',activation='relu')(input_shape)
conv2 = Convolution2D(32,(3,3),padding='same',activation='relu')(conv1)
pool_1 = MaxPooling2D(pool_size=(2,2))(conv2)
drop1 = Dropout(0.5)(pool_1)
conv3 = Convolution2D(64,(3,3),padding='same',activation='relu')(drop1)
conv4 = Convolution2D(64,(3,3),padding='same',activation='relu')(conv3)
pool_2 = MaxPooling2D(pool_size=(2,2))(conv4)
drop2 = Dropout(0.5)(pool_2)
flat = Flatten()(drop2)
hidden = Dense(64,activation='relu')(flat)
drop3 = Dropout(0.5)(hidden)
out = Dense(class_num,activation='softmax')(drop3)
model.compile(loss = 'categorical_crossentropy', optimizer= 'adam', metrics=['accuracy'])
model.fit(X_train,y_train,batch_size=16,nb_epoch=20, verbose=1, validation_data=(X_test,y_test))
model.evaluate(X_test,y_test,verbose=1)
Error: ValueError: Layer conv2d_1 was called with an input that isn't a
symbolic tensor. Received type: <class 'tuple'>. Full input: [(128, 128,3)].
All inputs to the layer should be tensors.
You are attempting to use the functional API and the sequential model all at once you need to first eliminate this line
model = Sequential()
Then, from the documentation of the functional API, we add an Input(channels,rows,columns) layer, and fill in the size values from your X_train matrix.
input_shape = Input()