Training a Keras model from batches of .npy files using generator? - python

Currently I am dealing with a big data issue when training Image data using Keras. I have directory which has batch of .npy file. Each batch contain 512 images. Each batch has its corresponding label file as .npy. So it looks like: {image_file_1.npy, label_file_1.npy, ..., image_file_37.npy, label_file_37}. Each image file has dimension (512, 199, 199, 3), each label file has dimension (512, 1)(eather 1 or 0) . If I load all the images in one ndarray it will be 35+ GB. So far reading all the Keras Doc. I am still not able to find how I will be able to train using custom generator. I have read about flow_from_dict and ImageDataGenerator(...).flow() but they are not ideal in that case or I do not know how to customized them.Here what I have done.
import numpy as np
import keras
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D
from keras.optimizers import SGD
from keras.preprocessing.image import ImageDataGenerator
val_gen = ImageDataGenerator(rescale=1./255)
x_test = np.load("../data/val_file.npy")
y_test = np.load("../data/val_label.npy")
val_gen.fit(x_test)
model = Sequential()
...
model_1.add(layers.Dense(512, activation='relu'))
model_1.add(layers.Dense(1, activation='sigmoid'))
model.compile(loss='categorical_crossentropy',
optimizer=sgd,
metrics=['acc'])
model.fit_generator(generate_batch_from_directory() # should give 1 image file and 1 label file
validation_data=val_gen.flow(x_test,
y_test,
batch_size=64),
validation_steps=32)
So here generate_batch_from_directory() should take image_file_i.npy and label_file_i.npy every time and optimise the weight until there is no batch left. Each image array in the .npy files has already been processed with augmentation, rotation and scaling. Each .npy file is properly mixed with data from class 1 and 0 (50/50).
If I append all the batch and create a big file such as:
X_train = np.append([image_file_1, ..., image_file_37])
y_train = np.append([label_file_1, ..., label_file_37])
It does not fit in the memory. Otherwise I could use .flow() to generate image sets to train the model.
Thanks for any advise.

Finally I was able to solve that problem. But I had to go through source code and documentation of keras.utils.Sequence to build my own generator class. This document help a lot to understand how generator works in Kears. You can read more detail in my kaggle notebook:
all_files_loc = "datapsycho/imglake/population/train/image_files/"
all_files = os.listdir(all_files_loc)
image_label_map = {
"image_file_{}.npy".format(i+1): "label_file_{}.npy".format(i+1)
for i in range(int(len(all_files)/2))}
partition = [item for item in all_files if "image_file" in item]
class DataGenerator(keras.utils.Sequence):
def __init__(self, file_list):
"""Constructor can be expanded,
with batch size, dimentation etc.
"""
self.file_list = file_list
self.on_epoch_end()
def __len__(self):
'Take all batches in each iteration'
return int(len(self.file_list))
def __getitem__(self, index):
'Get next batch'
# Generate indexes of the batch
indexes = self.indexes[index:(index+1)]
# single file
file_list_temp = [self.file_list[k] for k in indexes]
# Set of X_train and y_train
X, y = self.__data_generation(file_list_temp)
return X, y
def on_epoch_end(self):
'Updates indexes after each epoch'
self.indexes = np.arange(len(self.file_list))
def __data_generation(self, file_list_temp):
'Generates data containing batch_size samples'
data_loc = "datapsycho/imglake/population/train/image_files/"
# Generate data
for ID in file_list_temp:
x_file_path = os.path.join(data_loc, ID)
y_file_path = os.path.join(data_loc, image_label_map.get(ID))
# Store sample
X = np.load(x_file_path)
# Store class
y = np.load(y_file_path)
return X, y
# ====================
# train set
# ====================
all_files_loc = "datapsycho/imglake/population/train/image_files/"
all_files = os.listdir(all_files_loc)
training_generator = DataGenerator(partition)
validation_generator = ValDataGenerator(val_partition) # work same as training generator
hst = model.fit_generator(generator=training_generator,
epochs=200,
validation_data=validation_generator,
use_multiprocessing=True,
max_queue_size=32)

Related

How should I alter the trainable parameters to increase validation accuracy of CNN model?

I have a dataset of office items consisting of 7 objects each having 10 images resulting in a dataset of 70 samples. (this data cannot be increased). The only pre-processing I am doing to the images is resizing and converting to monochrome. It can be accessed here along with its ground truth. I am trying to obtain a trained model, I tried to increase the convolution layers, add dropout after each layer, I tried different train-test splits but (80-20) seems to be the best option, I removed some dense layers such that I can decrease the trainable parameters given the small size of the dataset. I tried using Adam optimiser but SGD achieved better training accuracy, I also tried to increase/decrease learning rate and decay rate. Not sure what I should try next. I can change the model however I like as long as validation accuracy is increased.
import tensorflow as tf
import glob
import pandas as pd
import cv2
import numpy as np
import matplotlib.pyplot as plt
from tensorflow.keras.utils import to_categorical
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense,Conv2D,MaxPooling2D,Flatten,Dropout
from tensorflow.keras.optimizers import SGD
from tensorflow.keras import regularizers
#dataset
x_train = glob.glob('Dataset/*/*.jpg', recursive=True)
print("Dataset size: ",len(x_train))
#ground truth
y_train = glob.glob('ground_truth.csv', recursive=True)
print("Parameter size: ",len(y_train))
N = len(x_train)
imgs_all = np.zeros((N,112,112), dtype = np.float64) #This is a 3-D array containing zeros for the time being
for t in range(len(x_train)):
#LOAD IMAGES
image = cv2.imread(x_train[t])
image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
image_resized_gray = cv2.resize(image_gray, (112, 112), interpolation = cv2.INTER_NEAREST)
imgs_all[t,:,:] = image_resized_gray
#GROUND TRUTH
df = pd.read_csv("ground_truth.csv")
# initial ground truth
data = np.dstack((df["Path"], df["Name"], df["Item"], df["Ground_Truth"]))[0]
GTs = data[:, 3] #1D array with shape (70,)
GTs = np.expand_dims(GTs, axis=1) #2D array with shape (70,1)
from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(imgs_all, GTs, test_size=0.2) #80:20
y_train_cat = to_categorical(y_train,7)
y_test_cat = to_categorical(y_test,7)
x_train = x_train/255
x_test = x_test/255
x_train = x_train.reshape(56,112,112,1)
x_test = x_test.reshape(14,112,112,1)
model = Sequential()
#First set of convolutional and pooling layers
model.add(Conv2D(filters=6,kernel_size=(5,5),input_shape=(112,112,1),activation='relu', padding = 'valid'))
model.add(MaxPooling2D(pool_size=(2,2), strides = 2))
model.add(Dropout(0.4))
#Second set of convolutional and pooling layers
model.add(Conv2D(filters=16,kernel_size=(5,5), activation='relu', padding = 'valid'))
model.add(MaxPooling2D(pool_size=(2,2), strides = 2))
model.add(Dropout(0.4))
#maps 2d to 1d
model.add(Flatten())
# Dropout layer with probability of retention of p = 0.5
model.add(Dropout(0.5))
#output layer
model.add(Dense(7,activation='softmax',name='output'))
print(model.summary())
# Load optimiser to configure parameters
opt = tf.keras.optimizers.SGD(lr = 0.03, decay= 1e-4)
model.compile(loss='categorical_crossentropy',
optimizer=opt,
metrics=['accuracy'])
history = model.fit(x_train,y_train_cat,
batch_size = 4,
epochs=20,
validation_data=(x_test,y_test_cat))
The following is a summary of the model:
And the training/validation achieved after the last epoch:
Your fundamental problem is that the number of samples (10) you have for each of your 7 classes is far to small. If you can not increase the size of the dataset then your next best choice is to use image augmentation to increase the number of image samples in each class. First create a dataframe with columns 'filepaths', 'labels' where the filepath column contains the full path to all the images and the labels column contains the class label of the associated image file. The use train_test_split to split the dataframe into a train_df, a test_df and a valid_df.
Then for train_df we will create augmented images for each class, store these images,
create a new datatrame (aig_df) and concatentate it with the original train_df.
The function below will accomplish that
def balance(train_df,max_samples, min_samples, column, working_dir, image_size):
train_df=train_df.copy()
# make directories to store augmented images
aug_dir=os.path.join(working_dir, 'aug')
if os.path.isdir(aug_dir):
shutil.rmtree(aug_dir)
os.mkdir(aug_dir)
for label in train_df['labels'].unique():
dir_path=os.path.join(aug_dir,label)
os.mkdir(dir_path)
# create and store the augmented images
total=0
gen=ImageDataGenerator(horizontal_flip=True, rotation_range=20, width_shift_range=.2,
height_shift_range=.2, zoom_range=.2)
groups=train_df.groupby('labels') # group by class
for label in train_df['labels'].unique(): # for every class
group=groups.get_group(label) # a dataframe holding only rows with the specified label
sample_count=len(group) # determine how many samples there are in this class
if sample_count< max_samples: # if the class has less than target number of images
aug_img_count=0
delta=max_samples-sample_count # number of augmented images to create
target_dir=os.path.join(aug_dir, label) # define where to write the images
aug_gen=gen.flow_from_dataframe( group, x_col='filepaths', y_col=None, target_size=image_size,
class_mode=None, batch_size=1, shuffle=False,
save_to_dir=target_dir, save_prefix='aug-', color_mode='rgb',
save_format='jpg')
while aug_img_count<delta:
images=next(aug_gen)
aug_img_count += len(images)
total +=aug_img_count
print('Total Augmented images created= ', total)
# create aug_df and merge with train_df to create composite training set ndf
if total>0:
aug_fpaths=[]
aug_labels=[]
classlist=os.listdir(aug_dir)
for klass in classlist:
classpath=os.path.join(aug_dir, klass)
flist=os.listdir(classpath)
for f in flist:
fpath=os.path.join(classpath,f)
aug_fpaths.append(fpath)
aug_labels.append(klass)
Fseries=pd.Series(aug_fpaths, name='filepaths')
Lseries=pd.Series(aug_labels, name='labels')
aug_df=pd.concat([Fseries, Lseries], axis=1)
train_df=pd.concat([train_df,aug_df], axis=0).reset_index(drop=True)
print (list(train_df['labels'].value_counts()) )
return train_df
now call the function as shown below
max_samples=75 # number of total samples in each class
min_samples=0
column = 'labels'
img_size=(224,224) # select an image size of the augmented images
working_dir=r'working_dir' # name of directory to store the augmented images
train_df=balance(train_df, max_samples, min_samples, column, working_dir, img_size)
train_df will end up with (75) images in each of your 7 classes. Now you can use train_df to train your model.

How to input multiple time-series data(wave) for RNN

I made the simple RNN model to learn and fit the one wave file.
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM,Dropout,Dense
from tensorflow.keras.layers import SimpleRNN
import librosa
import librosa.display
import numpy as np
a, sr = librosa.load("A.wav",sr=22050)
rawdata = librosa.stft(a, n_fft=512,hop_length= 512 // 4, window='hann') #make fourier transfered A.wav data.
rawdata = rawdata.transpose() # [Frame,Freq] => [Freq,Frame]
input_len = 10 # the frame number for learning to make next one
input=[]
target=[]
for i in range(0, len(rawdata) - input_len):
input.append( rawdata[i:i+input_len] ) # frames
target.append( rawdata[i+input_len] ) # one step forward frame for answer.
X = np.array(input)
Y = np.array(target)
#Separate 8:2 for training and test
x, val_x, y, val_y = train_test_split(X, Y, test_size=int(X.shape[0] * 0.2), shuffle=False)
n_hidden = 512
epoch = 100
model = Sequential()
model.add(SimpleRNN(n_hidden, input_shape=(input_len, n_in), return_sequences=False))
model.add(Dense(n_hidden, activation="linear"))
model.add(Dense(n_in, activation="linear"))
opt = Adam(lr=0.001)
model.compile(loss='mse', optimizer=opt)
model.summary()
history = model.fit(x, y, epochs=epoch, batch_size=10,validation_data=(val_x, val_y))
OK it works fine.
It learns the one wave file A.wav
However how can I learn multiple wave files??
B.wav C.wav
For example,
If I use model.fit() multiple times for each wav, does this model remember the past learning??
yes, model does remember previous train during fit, you can use fit multiple times as well. but its better to use model.train_on_batch this is simple version of fit to be used on small batch of data.
you can also modify your code to add other wav file feature to data.
# second way
input_len = 10 # the frame number for learning to make next one
input=[]
target=[]
for f in ['A.wav','B.wav','C.wav']:
a, sr = librosa.load(f,sr=22050)
rawdata = librosa.stft(a, n_fft=512,hop_length= 512 // 4, window='hann') #make fourier transfered A.wav data.
rawdata = rawdata.transpose() # [Frame,Freq] => [Freq,Frame]
for i in range(0, len(rawdata) - input_len):
input.append( rawdata[i:i+input_len] ) # frames
target.append( rawdata[i+input_len] ) # one step forward frame for answer.

Error when checking target: expected dense_2 to have shape (6,) but got array with shape (3,)

enter image description here
I am trying to train a model that will detect the native language of the speaker from the speech data which is already taken which will be in the English language.
I got this error while I am trying to run the below code and it is unable to train the model.
What is the mistake anyone explain?
Below is the code snippet of the training model :
import pandas as pd
from collections import Counter
import sys
sys.path.append('../dialectdetect-master/src>')
import getsplit
from keras import utils
import accuracy
import multiprocessing
import librosa
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Flatten
from keras.layers.convolutional import MaxPooling2D, Conv2D
from keras.preprocessing.image import ImageDataGenerator
from keras.callbacks import EarlyStopping, TensorBoard
DEBUG = True
SILENCE_THRESHOLD = .01
RATE = 24000
N_MFCC = 13
COL_SIZE = 30
EPOCHS = 10 #35#250
def to_categorical(y):
'''
Converts list of languages into a binary class matrix
:param y (list): list of languages
:return (numpy array): binary class matrix
'''
lang_dict = {}
for index,language in enumerate(set(y)):
lang_dict[language] = index
y = list(map(lambda x: lang_dict[x],y))
return utils.to_categorical(y, len(lang_dict))
def get_wav(language_num):
'''
Load wav file from disk and down-samples to RATE
:param language_num (list): list of file names
:return (numpy array): Down-sampled wav file
'''
y, sr = librosa.load('../audio/{}.wav'.format(language_num))
return(librosa.core.resample(y=y,orig_sr=sr,target_sr=RATE, scale=True))
def to_mfcc(wav):
'''
Converts wav file to Mel Frequency Ceptral Coefficients
:param wav (numpy array): Wav form
:return (2d numpy array: MFCC
'''
return(librosa.feature.mfcc(y=wav, sr=RATE, n_mfcc=N_MFCC))
def remove_silence(wav, thresh=0.04, chunk=5000):
'''
Searches wav form for segments of silence. If wav form values are lower than 'thresh' for 'chunk' samples, the values will be removed
:param wav (np array): Wav array to be filtered
:return (np array): Wav array with silence removed
'''
tf_list = []
for x in range(len(wav) / chunk):
if (np.any(wav[chunk * x:chunk * (x + 1)] >= thresh) or np.any(wav[chunk * x:chunk * (x + 1)] <= -thresh)):
tf_list.extend([True] * chunk)
else:
tf_list.extend([False] * chunk)
tf_list.extend((len(wav) - len(tf_list)) * [False])
return(wav[tf_list])
def normalize_mfcc(mfcc):
'''
Normalize mfcc
:param mfcc:
:return:
'''
mms = MinMaxScaler()
return(mms.fit_transform(np.abs(mfcc)))
def make_segments(mfccs,labels):
'''
Makes segments of mfccs and attaches them to the labels
:param mfccs: list of mfccs
:param labels: list of labels
:return (tuple): Segments with labels
'''
segments = []
seg_labels = []
for mfcc,label in zip(mfccs,labels):
for start in range(0, int(mfcc.shape[1] / COL_SIZE)):
segments.append(mfcc[:, start * COL_SIZE:(start + 1) * COL_SIZE])
seg_labels.append(label)
return(segments, seg_labels)
def segment_one(mfcc):
'''
Creates segments from on mfcc image. If last segments is not long enough to be length of columns divided by COL_SIZE
:param mfcc (numpy array): MFCC array
:return (numpy array): Segmented MFCC array
'''
segments = []
for start in range(0, int(mfcc.shape[1] / COL_SIZE)):
segments.append(mfcc[:, start * COL_SIZE:(start + 1) * COL_SIZE])
return(np.array(segments))
def create_segmented_mfccs(X_train):
'''
Creates segmented MFCCs from X_train
:param X_train: list of MFCCs
:return: segmented mfccs
'''
segmented_mfccs = []
for mfcc in X_train:
segmented_mfccs.append(segment_one(mfcc))
return(segmented_mfccs)
def train_model(X_train,y_train,X_validation,y_validation, batch_size=128): #64
'''
Trains 2D convolutional neural network
:param X_train: Numpy array of mfccs
:param y_train: Binary matrix based on labels
:return: Trained model
'''
# Get row, column, and class sizes
rows = X_train[0].shape[0]
cols = X_train[0].shape[1]
val_rows = X_validation[0].shape[0]
val_cols = X_validation[0].shape[1]
num_classes = len(y_train[0])
# input image dimensions to feed into 2D ConvNet Input layer
input_shape = (rows, cols, 1)
X_train = X_train.reshape(X_train.shape[0], rows, cols, 1 )
X_validation = X_validation.reshape(X_validation.shape[0],val_rows,val_cols,1)
print('X_train shape:', X_train.shape)
print(X_train.shape[0], 'training samples')
model = Sequential()
model.add(Conv2D(32, kernel_size=(3,3), activation='relu',
data_format="channels_last",
input_shape=input_shape))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(64,kernel_size=(3,3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(num_classes, activation='softmax'))
model.compile(loss='categorical_crossentropy',
optimizer='adadelta',
metrics=['accuracy'])
# Stops training if accuracy does not change at least 0.005 over 10 epochs
es = EarlyStopping(monitor='acc', min_delta=.005, patience=10, verbose=1, mode='auto')
# Creates log file for graphical interpretation using TensorBoard
tb = TensorBoard(log_dir='..\logs', histogram_freq=0, batch_size=32, write_graph=True, write_grads=True,
write_images=True, embeddings_freq=0, embeddings_layer_names=None,
embeddings_metadata=None)
# Image shifting
datagen = ImageDataGenerator(width_shift_range=0.05)
# Fit model using ImageDataGenerator
model.fit_generator(datagen.flow(X_train, y_train, batch_size=batch_size),
steps_per_epoch=len(X_train) / 32
, epochs=EPOCHS,
callbacks=[es,tb], validation_data=(X_validation,y_validation))
return (model)
def save_model(model, model_filename):
'''
Save model to file
:param model: Trained model to be saved
:param model_filename: Filename
:return: None
'''
model.save('../models/{}.h5'.format(model_filename)) # creates a HDF5 file 'my_model.h5'
############################################################
#######################################
if __name__ == '__main__':
'''
Console command example:
python trainmodel.py bio_metadata.csv model50
'''
# Load arguments
# print(sys.argv)
file_name = sys.argv[1]
model_filename = sys.argv[2]
# Load metadata
df = pd.read_csv(file_name)
# Filter metadata to retrieve only files desired
filtered_df = getsplit.filter_df(df)
# filtered_df = filter_df(df)
# print(filtered_df)
# print("filterd df is empty {}".format(filtered_df))
# Train test split
X_train, X_test, y_train, y_test = getsplit.split_people(filtered_df)
# Get statistics
train_count = Counter(y_train)
test_count = Counter(y_test)
print("Entering main")
# import ipdb;
# ipdb.set_trace()
acc_to_beat = test_count.most_common(1)[0][1] / float(np.sum(list(test_count.values())))
# To categorical
y_train = to_categorical(y_train)
y_test = to_categorical(y_test)
# Get resampled wav files using multiprocessing
if DEBUG:
print('Loading wav files....')
pool = multiprocessing.Pool(processes=multiprocessing.cpu_count())
X_train = pool.map(get_wav, X_train)
X_test = pool.map(get_wav, X_test)
# Convert to MFCC
if DEBUG:
print('Converting to MFCC....')
X_train = pool.map(to_mfcc, X_train)
X_test = pool.map(to_mfcc, X_test)
# Create segments from MFCCs
X_train, y_train = make_segments(X_train, y_train)
X_validation, y_validation = make_segments(X_test, y_test)
# Randomize training segments
X_train, _, y_train, _ = train_test_split(X_train, y_train, test_size=50)
# Train model
model = train_model(np.array(X_train), np.array(y_train), np.array(X_validation),np.array(y_validation))
# Make predictions on full X_test MFCCs
y_predicted = accuracy.predict_class_all(create_segmented_mfccs(X_test), model)
# Print statistics
print('Training samples:', train_count)
print('Testing samples:', test_count)
print('Accuracy to beat:', acc_to_beat)
print('Confusion matrix of total samples:\n', np.sum(accuracy.confusion_matrix(y_predicted, y_test),axis=1))
print('Confusion matrix:\n',accuracy.confusion_matrix(y_predicted, y_test))
print('Accuracy:', accuracy.get_accuracy(y_predicted,y_test))
# Save model
save_model(model, model_filename)

Input Pipeline for LSTM with Timeseries Data Using a Large Dataset with Multiple .csv in Tensorflow

Currently I can train a LSTM network using one csv file based on this tutorial: https://machinelearningmastery.com/how-to-develop-lstm-models-for-time-series-forecasting/
This code generate sliding windows where the last n_steps of the features are saved to predict the actual target (similar to this: Keras LSTM - feed sequence data with Tensorflow dataset API from the generator):
#%% Import
import pandas as pd
import tensorflow as tf
from tensorflow.python.keras.models import Sequential, model_from_json
from tensorflow.python.keras.layers import LSTM
from tensorflow.python.keras.layers import Dense
# for path
import pathlib
import os
#%% Define functions
# Function to split multivariate input data into samples according to the number of timesteps (n_steps) used for the prediction ("sliding window")
def split_sequences(sequences, n_steps):
X, y = list(), list()
for i in range(len(sequences)):
# find end of this pattern
end_ix = i + n_steps
# check if beyond maximum index of input data
if end_ix > len(sequences):
break
# gather input and output parts of the data in corresponding format (depending on n_steps)
seq_x, seq_y = sequences[i:end_ix, :-1], sequences[end_ix-1, -1]
X.append(seq_x)
y.append(seq_y)
#Append: Adds its argument as a single element to the end of a list. The length of the list increases by one.
return array(X), array(y)
# Set source files
csv_train_path = os.path.join(dir_of_file, 'SimulationData', 'SimulationTrainData', 'SimulationTrainData001.csv')
# Load data
df_train = pd.read_csv(csv_train_path, header=0, parse_dates=[0], index_col=0)
#%% Select features and target
features_targets_considered = ['Fz1', 'Fz2', 'Fz3', 'Fz4', 'Fz5', 'Fz_res']
n_features = len(features_targets_considered)-1 # substract the target
features_targets_train = df_train[features_targets_considered]
# "Convert" to array
train_values = features_targets_train.values
# Set number of previous timesteps, which are considered to predict
n_steps = 100
# Convert into input (400x5) and output (1) values
X, y = split_sequences(train_values, n_steps)
X_test, y_test = split_sequences(test_values, n_steps)
#%% Define model
model = Sequential()
model.add(LSTM(200, activation='relu', return_sequences=True, input_shape=(n_steps, n_features)))
model.add(LSTM(200, activation='relu', return_sequences=True))
model.add(LSTM(200, activation='relu'))
model.add(Dense(1))
model.compile(optimizer='adam', loss='mse', metrics=['mae'])
#%% Fit model
history = model.fit(X, y, epochs=200, verbose=1)
I now want to expand this example to efficiently train the network with different csv files. In the data folder I have the files 'SimulationTrainData001.csv', 'SimulationTrainData002.csv', ..., 'SimulationTrainData300.csv' (about 14 GB).
To achieve this, I tried to adopt the code of this input pipeline example: https://www.tensorflow.org/guide/data#consuming_sets_of_files, which works to a certain extend. I can show the training files in the folder with this change:
# Set source folders
csv_train_path = os.path.join(dir_of_file, 'SimulationData', 'SimulationTrainData')
csv_train_path = pathlib.Path(csv_train_path)
#%% Show five example files from training folder
list_ds = tf.data.Dataset.list_files(str(csv_train_path/'*'))
for f in list_ds.take(5):
print(f.numpy())
One problem is, that in the example the files are pictures of flowers and not time series values and I do not know at which point I can use the split_sequences(sequences, n_steps) function to create the sliding windows to provide the necessary data format to train the LSTM network.
Also, as far as I know, it would be better for the training process, if the generated windows of the different files would be shuffled. I could use the split_sequences(sequences, n_steps) function on every csv file (to generate X_test , y_test) and join the result in one big variable or file and shuffle the windows, but I do not think this is an efficient way and it also had to be redone if n_steps will be changed.
If somebody could suggest a (established) method or example to preprocess my data, I would be very thankful.
You can use the TimeSeriesGenerator after consuming those sets of files.
Here is the reference link.
As per the documentation:
'''
This class takes in a sequence of data-points gathered at equal intervals, along with time-series parameters such as stride, length of history, etc., to produce batches for training/validation.
'''
Provided examples for both univariate & multiple variate scenario
Univariate Example:
from tensorflow.keras.preprocessing.sequence import TimeseriesGenerator
from tensorflow.keras import Sequential
from tensorflow.keras.layers import Dense, LSTM
import numpy as np
import tensorflow as tf
# define dataset
series = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
# reshape to [10, 1]
n_features = 1
series = series.reshape((len(series), n_features))
# define generator
n_input = 2
generator = TimeseriesGenerator(series, series, length=n_input, batch_size=8)
# create model
model = Sequential()
model.add(LSTM(100, activation='relu', input_shape=(n_input, n_features)))
model.add(Dense(1))
model.compile(optimizer='adam', loss='mse')
# fit model
model.fit_generator(generator, steps_per_epoch=1, epochs=500, verbose=1)
#sample prediction
inputs = np.array([9, 10]).reshape((1, n_input, n_features))
result = model.predict(inputs, verbose=0)
print(result)
Multi-variate Example
from tensorflow.keras.preprocessing.sequence import TimeseriesGenerator
from tensorflow.keras import Sequential
from tensorflow.keras.layers import Dense, LSTM
import numpy as np
import tensorflow as tf
# define dataset
in_seq1 = np.array([10, 20, 30, 40, 50, 60, 70, 80, 90, 100])
in_seq2 = np.array([15, 25, 35, 45, 55, 65, 75, 85, 95, 105])
# reshape series
in_seq1 = in_seq1.reshape((len(in_seq1), 1))
in_seq2 = in_seq2.reshape((len(in_seq2), 1))
# horizontally stack columns
dataset = np.hstack((in_seq1, in_seq2))
# define generator
n_features = dataset.shape[1]
n_input = 2
generator = TimeseriesGenerator(dataset, dataset, length=n_input, batch_size=8)
# define model
model = Sequential()
model.add(LSTM(100, activation='relu', input_shape=(n_input, n_features)))
model.add(Dense(2))
model.compile(optimizer='adam', loss='mse')
# fit model
model.fit_generator(generator, steps_per_epoch=1, epochs=500, verbose=1)
# make a one step prediction out of sample
inputs = np.array([[90, 95], [100, 105]]).reshape((1, n_input, n_features))
result = model.predict(inputs, verbose=1)
print(result)
Note: All of these were simulated using Google Colaboratory

How to use a image set in RNN model

Hello I am trying to do my first RNN using Keras and Tensorflow, but I am getting stuck on an issue or reshaping my images to fit into the model.
I have looked at this post but could not figure out about the reshaping:
Keras - Input a 3 channel image into LSTM
What I have is a bunch of images that are taken at every frame in a video. I saved all the frames outside of python so I have a very large folder of images.I separated the frames into 21 frames for a segment so 21 images per motion that I want to capture. I want to read in these 21 images as one sequence. I have the same sequence captured from multiple cameras/angles which I want to us in this model. What I want to try is to model a movement and see if a person is doing this movement or not, so it is a binary model yes or no basically. Not the most sophisticated but its a learning process to use this model and keras.
I need help figuring out how to use these images inside the keras model. I have looked at a few tutorials on MINST data set but that didnt help me figure this out.
Any help will be appreciated.
This is the error that is given to me when I try to train the model
ValueError: Error when checking input: expected lstm_1_input to have 3 dimensions, but got array with shape (2026, 200, 200, 1)
My code is this:
from keras.models import Sequential
from keras.layers import Dense, Activation
from keras.layers import LSTM
from tqdm import tqdm
import cv2
import os
import numpy as np
imageSize = 200
#create lables for each image
def labelImage(img):
wordLabel = img.split('.')[-3]
#Conversion to one hot array [lat,not]
if wordLabel == "FWAC":
return[1,0]
else:
return[0,1]
#Process images and add lables
#Convert data into an array and add its lable
def makeTrainingData():
print("Creating Training Data")
trainingData = []
for img in tqdm(os.listdir(trainDir)):
label = labelImage(img)
path = os.path.join(trainDir,img)
img = cv2.imread(path, cv2.IMREAD_GRAYSCALE)
img = cv2.resize(img, (imageSize,imageSize))
trainingData.append([np.array(img),np.array(label)])
#Save the array file to load it into other models if needed
np.save("trainingData.npy", trainingData)
print("Training Data Saved")
return trainingData
#process the testing data in the same manner
def processTestData():
print("Creating Testing Data")
testData = []
for img in tqdm(os.listdir(testDri)):
print("image", img)
path = os.path.join(testDri, img)
imgNum = img.split(".")[0]
img = cv2.imread(path, cv2.IMREAD_GRAYSCALE)
img = cv2.resize(img, (imageSize, imageSize))
testData.append([np.array(img), imgNum])
np.save("testingData.npy", testData)
print("Testing Data Saved")
return testData
rnnSize = 512
model = Sequential()
model.add(LSTM(rnnSize, input_shape=(imageSize, imageSize)))
model.add(Dense(1024))
model.add(Activation('relu'))
model.add(Dense(50))
model.add(Activation('sigmoid'))
model.add(Dense(3))
model.add(Activation('softmax'))
model.compile(loss='mean_squared_error', optimizer='adam',metrics=['accuracy'])
#Data
trainDir = "D:/TrainingDataSets/TrainingSet/"
testDri = "D:/TrainingDataSets/TestingSet/"
#trainData = makeTrainingData()
#testData = processTestData()
trainData = np.load('trainingData.npy')
testData = np.load("testingData.npy")
#resize the image to this See above
train = trainData[:-500]
test = trainData[-200:]
x = []
y = []
for xi in trainData:
x.append(xi[0].reshape((-1, imageSize, imageSize)))
y.append(xi[1])
x_train = np.array([i[0] for i in train]).reshape(-1,imageSize, imageSize,1)
y_train = [i[1] for i in train]
test_x = np.array([i[0] for i in test]).reshape(-1,imageSize , imageSize,1)
test_y = [i[1] for i in test]
epoch = 5
batchSize = 100
model.fit(x_train, y_train, epochs=epoch, batch_size= batchSize, verbose=1, shuffle=False)
For the error before dense layers add this line:
model.add(Flatten())
Previously, you should import:
from keras.layers import Flatten

Categories

Resources