La perte de validation et la précision restent constantes

12

J'essaie de mettre en œuvre ce document sur un ensemble d'images médicales. Je le fais à Keras. Le réseau se compose essentiellement de 4 couches conv et max-pool suivies d'une couche entièrement connectée et d'un classificateur soft max.

Pour autant que je sache, j'ai suivi l'architecture mentionnée dans l'article. Cependant, la perte de validation et la précision restent inchangées tout au long. La précision semble être fixée à ~ 57,5%.

Toute aide sur où je pourrais me tromper serait grandement appréciée.

Mon code:

from keras.models import Sequential
from keras.layers import Activation, Dropout, Dense, Flatten  
from keras.layers import Convolution2D, MaxPooling2D
from keras.optimizers import SGD
from keras.utils import np_utils
from PIL import Image
import numpy as np
from sklearn.utils import shuffle
from sklearn.cross_validation import train_test_split
import theano
import os
import glob as glob
import cv2
from matplotlib import pyplot as plt

nb_classes = 2
img_rows, img_cols = 100,100
img_channels = 3


#################### DATA DIRECTORY SETTING######################

data = '/home/raghuram/Desktop/data'
os.chdir(data)
file_list = os.listdir(data)
##################################################################

## Test lines
#I = cv2.imread(file_list[1000])
#print np.shape(I)
####
non_responder_file_list = glob.glob('0_*FLAIR_*.png')
responder_file_list = glob.glob('1_*FLAIR_*.png')
print len(non_responder_file_list),len(responder_file_list)

labels = np.ones((len(file_list)),dtype = int)
labels[0:len(non_responder_file_list)] = 0
immatrix = np.array([np.array(cv2.imread(data+'/'+image)).flatten() for image in file_list])
#img = immatrix[1000].reshape(100,100,3)
#plt.imshow(img,cmap = 'gray')


data,Label = shuffle(immatrix,labels, random_state=2)
train_data = [data,Label]
X,y = (train_data[0],train_data[1])
# Also need to look at how to preserve spatial extent in the conv network
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=4)
X_train = X_train.reshape(X_train.shape[0], 3, img_rows, img_cols)
X_test = X_test.reshape(X_test.shape[0], 3, img_rows, img_cols)
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')

X_train /= 255
X_test /= 255

Y_train = np_utils.to_categorical(y_train, nb_classes)
Y_test = np_utils.to_categorical(y_test, nb_classes)

model = Sequential()

## First conv layer and its activation followed by the max-pool layer#
model.add(Convolution2D(16,5,5, border_mode = 'valid', subsample = (1,1), init = 'glorot_normal',input_shape = (3,100,100))) # Glorot normal is similar to Xavier initialization
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size = (2,2),strides = None))
# Output is 48x48

print 'First layer setup'
###########################Second conv layer#################################
model.add(Convolution2D(32,3,3,border_mode = 'same', subsample = (1,1),init = 'glorot_normal'))
model.add(Activation('relu'))
model.add(Dropout(0.6))
model.add(MaxPooling2D(pool_size = (2,2),strides = None))
#############################################################################

print ' Second layer setup'
# Output is 2x24

##########################Third conv layer###################################
model.add(Convolution2D(64,3,3, border_mode = 'same', subsample = (1,1), init = 'glorot_normal'))
model.add(Activation('relu'))
model.add(Dropout(0.6))
model.add(MaxPooling2D(pool_size = (2,2),strides = None))
#############################################################################
# Output is 12x12

print ' Third layer setup'
###############################Fourth conv layer#############################
model.add(Convolution2D(128,3,3, border_mode = 'same', subsample = (1,1), init = 'glorot_normal'))
model.add(Activation('relu'))
model.add(Dropout(0.6))
model.add(MaxPooling2D(pool_size = (2,2),strides = None))
############################################################################# 

print 'Fourth layer setup'

# Output is 6x6x128
# Create the FC layer of size 128x6x6#
model.add(Flatten()) 
model.add(Dense(2,init = 'glorot_normal',input_dim = 128*6*6))
model.add(Dropout(0.6))
model.add(Activation('softmax'))

print 'Setting up fully connected layer'
print 'Now compiling the network'
sgd = SGD(lr=0.01, decay=1e-4, momentum=0.6, nesterov=True)
model.compile(loss = 'mse',optimizer = 'sgd', metrics=['accuracy'])

# Fit the network to the data#
print 'Network setup successfully. Now fitting the network to the data'
model. fit(X_train,Y_train,batch_size = 100, nb_epoch = 20, validation_split = None,verbose = 1)
print 'Testing'
loss,accuracy = model.evaluate(X_test,Y_test,batch_size = 32,verbose = 1)
print "Test fraction correct (Accuracy) = {:.2f}".format(accuracy)
Raghuram
la source
La perte d'entraînement diminue-t-elle?
Jan van der Vegt
Non, la perte d'entraînement reste également constante.
Raghuram
Vous n'avez défini aucune donnée de validation ou validation_split dans votre appel fit, sur quoi validerait-il? Ou vouliez-vous dire test?
Jan van der Vegt
C'est après avoir expérimenté. J'ai défini validation_split = 0,2 avant de le définir sur Aucun et j'ai également expérimenté cela.
Raghuram
2
Pouvez-vous ajuster un lot plusieurs fois pour voir si vous pouvez réduire la perte d'entraînement?
Jan van der Vegt

Réponses:

4

Il semble que vous utilisiez MSE comme fonction de perte, d'un aperçu sur le papier, il semble qu'ils utilisent NLL (entropie croisée), MSE est considéré comme enclin à être sensible au déséquilibre des données entre autres problèmes et il peut être la cause du problème que vous expérience, j'essaierais de m'entraîner en utilisant la perte de catégorical_crossentropie dans votre cas, de plus le taux d'apprentissage de 0,01 semble trop important j'essaierais de jouer avec et j'essaierais 0,001 voire 0,0001

koltun
la source
2

Bien que je sois un peu en retard ici, je voudrais mettre mes deux cents car cela m'a aidé à résoudre un problème similaire récemment. Ce qui m'est venu à la rescousse a été la mise à l'échelle des caractéristiques dans la plage (0,1) en plus de la perte d'entropie croisée catégorique. Néanmoins, il convient de dire que la mise à l'échelle des fonctionnalités n'aide que si les fonctionnalités appartiennent à différentes métriques et possèdent beaucoup plus de variations (par ordre de grandeur) les unes par rapport aux autres, comme c'était le cas dans mon cas. De plus, la mise à l'échelle pourrait être très utile si l'on utilise la hingeperte, car les classificateurs de marge maximale sont généralement sensibles aux distances entre les valeurs des entités. J'espère que cela aidera certains futurs visiteurs!

Saurav--
la source