La pérdida de validación y la precisión permanecen constantes


12

Estoy tratando de implementar este documento en un conjunto de imágenes médicas. Lo estoy haciendo en Keras. La red consiste esencialmente en 4 capas conv y max-pool seguidas de una capa completamente conectada y un clasificador soft soft.

Hasta donde sé, he seguido la arquitectura mencionada en el documento. Sin embargo, la pérdida de validación y la precisión permanecen planas en todo momento. La precisión parece estar fijada en ~ 57.5%.

Cualquier ayuda sobre dónde podría estar yendo mal sería muy apreciada.

Mi código:

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)

¿Está bajando la pérdida de entrenamiento?
Jan van der Vegt

No, la pérdida de entrenamiento también permanece constante en todo momento.
Raghuram

No ha establecido ningún dato de validación o validation_split en su llamada de ajuste, ¿en qué validaría? ¿O quisiste decir prueba?
Jan van der Vegt

Eso es después de experimentar. Configuré validation_split = 0.2 antes de configurarlo en Ninguno y también experimenté con eso.
Raghuram el

2
¿Puedes encajar un lote muchas veces para ver si puedes lograr que la pérdida de entrenamiento sea menor?
Jan van der Vegt

Respuestas:


4

Parece que usa MSE como la función de pérdida, de un vistazo en el papel parece que usan NLL (entropía cruzada), MSE se considera propenso a ser sensible al desequilibrio de datos entre otros problemas y puede ser la causa del problema experiencia, trataría de entrenar usando la pérdida de crossentropía categórica en su caso, además, la tasa de aprendizaje de 0.01 parece demasiado grande, trataría de jugar con ella y probar 0.001 o incluso 0.0001


2

Aunque llegué un poco tarde aquí, me gustaría poner mis dos centavos porque me ayudó a resolver un problema similar recientemente. Lo que vino a mi rescate fue escalar las características en el rango (0,1) además de la pérdida categórica de entropía cruzada. Sin embargo, vale la pena decir que el escalado de características ayuda solo si las características pertenecen a diferentes métricas y poseen mucha más variación (en órdenes de magnitud) entre sí, como fue en mi caso. Además, la escala podría ser realmente útil si uno usa la hingepérdida, ya que los clasificadores de margen máximo son generalmente sensibles a las distancias entre los valores de las características. Espero que esto ayude a algunos futuros visitantes!

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.