I am attempting to implement a 3D CNN utilizing Keras. Nonetheless, I’m having some difficulties understanding some particulars within the outcomes obtained and additional enhancing the accuracy.

The info that I’m attempting to analyzing have the form {64(d1)x64(d2)x38(d3)}, the place d1 and d2 are the size and width of the picture (64×64 pixels) and d3 is the time dimension. In different phrases, I’ve 38 photos. The channel parameter is ready to 1 as my knowledge are literally uncooked knowledge and not likely colourful photos.

My knowledge include 219 samples, therefore 219x64x64x38. They’re divided into coaching and validation units with 20% for validation. As well as, I’ve a hard and fast 147 further knowledge for testing.

Beneath is my code that works positive. It creates a txt file that saves the outcomes for the completely different mixture of parameters in my community (grid search). Right here on this code, I solely think about tuning 2 parameters: the variety of filters and lambda for L2 regularizer. I fastened the dropout and the kernel dimension for the filters. Nonetheless, later I thought of their variations.

I additionally tried to set the seed worth in order that I’ve some kind of reproducibility (I do not suppose that I’ve achieved this process).

**My query is that:**

Given the beneath structure and code, I all the time attain for all of the given combos of parameters a convergence for the coaching accuracy in the direction of 1 (which is sweet). Nonetheless, for the validation accuracy it’s more often than not round 80% +/- 4% (not often beneath 70%) regardless of the hyper-parameters mixture. Related conduct for the take a look at accuracy. How can I improve this accuracy to above 90% ?

So far as I do know, having a niche between the practice and validation/take a look at accuracy is a outcome from overfitting. Nonetheless, in my mannequin I’m including dropouts and L2 regularizers and in addition altering the dimensions of my community which ought to by some means cut back this hole (however it isn’t).

Is there anything I can do apart from modifying my enter knowledge? Does including extra layers assist? Or is there perhaps a pre-trained 3D CNN like within the case of 2D CNN (e.g., AlexNet)? Ought to I strive ConvLSTM? Is that this the restrict of this structure?

Thanks 🙂

```
import numpy as np
import tensorflow as tf
import keras
from keras.fashions import Sequential
from keras.layers import Conv3D, MaxPooling3D, Dense, Flatten, Activation
from keras.utils import to_categorical
from keras.regularizers import l2
from keras.layers import Dropout
from keras.utils import multi_gpu_model
import scipy.io as sio
from sklearn.metrics import accuracy_score
from sklearn.metrics import f1_score
from keras.callbacks import ReduceLROnPlateau
tf.set_random_seed(1234)
def normalize_minmax(X_train):
"""
Normalize to [0,1]
"""
from sklearn import preprocessing
min_max_scaler = preprocessing.MinMaxScaler()
X_minmax_train = min_max_scaler.fit_transform(X_train)
return X_minmax_train
# generate and put together the dataset
def get_data():
# Load and put together the info
X_data = sio.loadmat('./X_train')['X_train']
Y_data = sio.loadmat('./Y_train')['targets_train']
X_test = sio.loadmat('./X_test')['X_test']
Y_test = sio.loadmat('./Y_test')['targets_test']
return X_data, Y_data, X_test, Y_test
def get_model(X_train, Y_train, X_validation, Y_validation, F1_nb, F2_nb, F3_nb, kernel_size_1, kernel_size_2, kernel_size_3, l2_lambda, learning_rate, reduce_lr, dropout_conv1, dropout_conv2, dropout_conv3, dropout_dense, no_epochs):
no_classes = 5
sample_shape = (64, 64, 38, 1)
batch_size = 32
dropout_seed = 30
conv_seed = 20
# Create the mannequin
mannequin = Sequential()
mannequin.add(Conv3D(F1_nb, kernel_size=kernel_size_1, kernel_regularizer=l2(l2_lambda), padding='similar', kernel_initializer='glorot_uniform', input_shape=sample_shape))
mannequin.add(Activation('selu'))
mannequin.add(MaxPooling3D(pool_size=(2,2,2)))
mannequin.add(Dropout(dropout_conv1, seed=conv_seed))
mannequin.add(Conv3D(F2_nb, kernel_size=kernel_size_2, kernel_regularizer=l2(l2_lambda), padding='similar', kernel_initializer='glorot_uniform'))
mannequin.add(Activation('selu'))
mannequin.add(MaxPooling3D(pool_size=(2,2,2)))
mannequin.add(Dropout(dropout_conv2, seed=conv_seed))
mannequin.add(Conv3D(F3_nb, kernel_size=kernel_size_3, kernel_regularizer=l2(l2_lambda), padding='similar', kernel_initializer='glorot_uniform'))
mannequin.add(Activation('selu'))
mannequin.add(MaxPooling3D(pool_size=(2,2,2)))
mannequin.add(Dropout(dropout_conv3, seed=conv_seed))
mannequin.add(Flatten())
mannequin.add(Dense(512, kernel_regularizer=l2(l2_lambda), kernel_initializer='glorot_uniform'))
mannequin.add(Activation('selu'))
mannequin.add(Dropout(dropout_dense, seed=dropout_seed))
mannequin.add(Dense(no_classes, activation='softmax'))
mannequin = multi_gpu_model(mannequin, gpus = 2)
# Compile the mannequin
mannequin.compile(loss=keras.losses.categorical_crossentropy,
optimizer=keras.optimizers.Adam(lr=learning_rate),
metrics=['accuracy'])
# Practice the mannequin.
historical past = mannequin.match(X_train, Y_train, batch_size=batch_size, epochs=no_epochs, validation_data=(X_validation, Y_validation),callbacks=[reduce_lr])
return mannequin, historical past
reduce_lr = ReduceLROnPlateau(monitor='val_loss', issue=0.2, persistence=5, min_lr=0.0001)
learning_rate = 0.001
no_epochs = 100
X_data, Y_data, X_test, Y_test = get_data()
# Normalize the practice/val knowledge
for i in vary(X_data.form[0]):
for j in vary(X_data.form[3]):
X_data[i,:,:,j] = normalize_minmax(X_data[i,:,:,j])
X_data = np.expand_dims(X_data, axis=4)
# Normalize the take a look at knowledge
for i in vary(X_test.form[0]):
for j in vary(X_test.form[3]):
X_test[i,:,:,j] = normalize_minmax(X_test[i,:,:,j])
X_test = np.expand_dims(X_test, axis=4)
# Shuffle the coaching knowledge
# repair random seed for reproducibility
seedValue = 40
permutation = np.random.RandomState(seed=seedValue).permutation(len(X_data))
X_data = X_data[permutation]
Y_data = Y_data[permutation]
Y_data = np.squeeze(Y_data)
Y_test = np.squeeze(Y_test)
#Break up between practice and validation (20%). Right here I didn't use the classical validation_split=0.2 simply to be sure that the info is identical for the completely different architectures I'm utilizing.
X_train = X_data[0:175,:,:,:,:]
Y_train = Y_data[0:175]
X_validation = X_data[176:,:,:,:]
Y_validation = Y_data[176:]
Y_train = to_categorical(Y_train,num_classes=5).astype(np.integer)
Y_validation = to_categorical(Y_validation,num_classes=5).astype(np.integer)
Y_test = to_categorical(Y_test,num_classes=5).astype(np.integer)
l2_lambda_list = [(1*pow(10,-4)),(2*pow(10,-4)),
(3*pow(10,-4)),
(4*pow(10,-4)),
(5*pow(10,-4)),(6*pow(10,-4)),
(7*pow(10,-4)),
(8*pow(10,-4)),(9*pow(10,-4)),(10*pow(10,-4))
]
filters_nb = [(128,64,64),(128,64,32),(128,64,16),(128,64,8),(128,32,32),(128,32,16),(128,32,8),(128,16,8),(128,8,8),
(64,64,32),(64,64,16),(64,64,8),(64,32,32),(64,32,16),(64,32,8),(64,16,16),(64,16,8),(64,8,8),
(32,32,16),(32,32,8),(32,16,16),(32,16,8),(32,8,8),
(16,16,16),(16,16,8),(16,8,8)
]
DropOut = [(0.25,0.25,0.25,0.5),
(0,0,0,0.1),(0,0,0,0.2),(0,0,0,0.3),(0,0,0,0.4),(0,0,0,0.5),
(0.1,0.1,0.1,0),(0.2,0.2,0.2,0),(0.3,0.3,0.3,0),(0.4,0.4,0.4,0),(0.5,0.5,0.5,0),
(0.1,0.1,0.1,0.1),(0.1,0.1,0.1,0.2),(0.1,0.1,0.1,0.3),(0.1,0.1,0.1,0.4),(0.1,0.1,0.1,0.5),
(0.15,0.15,0.15,0.1),(0.15,0.15,0.15,0.2),(0.15,0.15,0.15,0.3),(0.15,0.15,0.15,0.4),(0.15,0.15,0.15,0.5),
(0.2,0.2,0.2,0.1),(0.2,0.2,0.2,0.2),(0.2,0.2,0.2,0.3),(0.2,0.2,0.2,0.4),(0.2,0.2,0.2,0.5),
(0.25,0.25,0.25,0.1),(0.25,0.25,0.25,0.2),(0.25,0.25,0.25,0.3),(0.25,0.25,0.25,0.4),(0.25,0.25,0.25,0.5),
(0.3,0.3,0.3,0.1),(0.3,0.3,0.3,0.2),(0.3,0.3,0.3,0.3),(0.3,0.3,0.3,0.4),(0.3,0.3,0.3,0.5),
(0.35,0.35,0.35,0.1),(0.35,0.35,0.35,0.2),(0.35,0.35,0.35,0.3),(0.35,0.35,0.35,0.4),(0.35,0.35,0.35,0.5)
]
kernel_size = [(3,3,3),
(2,3,3),(2,3,4),(2,3,5),(2,3,6),(2,3,7),(2,3,8),(2,3,9),(2,3,10),(2,3,11),(2,3,12),(2,3,13),(2,3,14),(2,3,15),
(3,3,3),(3,3,4),(3,3,5),(3,3,6),(3,3,7),(3,3,8),(3,3,9),(3,3,10),(3,3,11),(3,3,12),(3,3,13),(3,3,14),(3,3,15),
(3,4,3),(3,4,4),(3,4,5),(3,4,6),(3,4,7),(3,4,8),(3,4,9),(3,4,10),(3,4,11),(3,4,12),(3,4,13),(3,4,14),(3,4,15),
]
for l in vary(len(l2_lambda_list)):
l2_lambda = l2_lambda_list[l]
f = open("My Outcomes.txt", "a")
lambda_Str = str(l2_lambda)
f.write("---------------------------------------n")
f.write("lambda = "+f"{lambda_Str}n")
f.write("---------------------------------------n")
for i in vary(len(filters_nb)):
F1_nb = filters_nb[i][0]
F2_nb = filters_nb[i][1]
F3_nb = filters_nb[i][2]
kernel_size_1 = kernel_size[0]
kernel_size_2 = kernel_size_1
kernel_size_3 = kernel_size_1
dropout_conv1 = DropOut[0][0]
dropout_conv2 = DropOut[0][1]
dropout_conv3 = DropOut[0][2]
dropout_dense = DropOut[0][3]
# match mannequin
mannequin, historical past = get_model(X_train, Y_train, X_validation, Y_validation, F1_nb, F2_nb, F3_nb, kernel_size_1, kernel_size_2, kernel_size_3, l2_lambda, learning_rate, reduce_lr, dropout_conv1, dropout_conv2, dropout_conv3, dropout_dense, no_epochs)
# Consider metrics
predictions = mannequin.predict(X_test)
out = np.argmax(predictions, axis=1)
Y_test = sio.loadmat('./Y_test')['targets_test']
Y_test = np.squeeze(Y_test)
loss = historical past.historical past['loss'][no_epochs-1]
acc = historical past.historical past['acc'][no_epochs-1]
val_loss = historical past.historical past['val_loss'][no_epochs-1]
val_acc = historical past.historical past['val_acc'][no_epochs-1]
# accuracy: (tp + tn) / (p + n)
accuracy = accuracy_score(Y_test, out)
# f1: 2 tp / (2 tp + fp + fn)
f1 = f1_score(Y_test, out,common='macro')
a = str(filters_nb[i][0]) + ',' + str(filters_nb[i][1]) + ',' + str(filters_nb[i][2]) + ': ' + str('f1-metric: ') + str('%f' % f1) + str(' | loss: ') + str('%f' % loss) + str(' | acc: ') + str('%f' % acc) + str(' | val_loss: ') + str('%f' % val_loss) + str(' | val_acc: ') + str('%f' % val_acc) + str(' | test_acc: ') + str('%f' % accuracy)
f.write(f"{a}n")
f.shut()
```