A perda e a precisão da validação permanecem constantes


12

Estou tentando implementar este artigo em um conjunto de imagens médicas. Eu estou fazendo isso em Keras. A rede consiste essencialmente em 4 camadas conv e max-pool, seguidas por uma camada totalmente conectada e um classificador soft max.

Até onde sei, segui a arquitetura mencionada no artigo. No entanto, a perda e a precisão da validação permanecem inalteradas. A precisão parece estar fixada em ~ 57,5%.

Qualquer ajuda sobre onde eu poderia estar errado seria muito apreciada.

Meu 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)

A perda de treinamento está diminuindo?
Jan van der Vegt

Não, a perda de treinamento também permanece constante o tempo todo.
Raghuram

Você não definiu nenhum dado de validação ou validation_split em sua chamada de ajuste. Em que validaria? Ou você quis dizer teste?
Jan van der Vegt

Isso é depois de experimentar. Defino validation_split = 0.2 antes de defini-lo como None e experimentei isso também.
Raghuram

2
Você pode ajustar um lote várias vezes para ver se a perda de treinamento é menor?
Jan van der Vegt

Respostas:


4

Parece que você usa o MSE como a função de perda; de um relance no papel parece que eles usam NLL (entropia cruzada), o MSE é considerado propenso a ser sensível ao desequilíbrio de dados entre outros problemas e pode ser a causa do problema que você experiência, eu tentaria treinar usando perda de categoric_crossentropy no seu caso, além disso, a taxa de aprendizado de 0,01 parece muito grande Eu tentaria brincar com ele e tentaria 0,001 ou mesmo 0,0001


2

Embora eu esteja um pouco atrasado aqui, gostaria de colocar meus dois centavos, pois me ajudou a resolver um problema semelhante recentemente. O que veio ao meu resgate foi escalar os recursos no intervalo (0,1), além da perda categórica de entropia cruzada. No entanto, vale dizer que o dimensionamento de recursos ajuda apenas se os recursos pertencerem a métricas diferentes e possuírem muito mais variação (em ordem de magnitudes) em relação um ao outro, como foi no meu caso. Além disso, o dimensionamento pode ser realmente útil se a hingeperda for usada , pois os classificadores de margem máxima geralmente são sensíveis às distâncias entre os valores dos recursos. Espero que isso ajude alguns futuros visitantes!

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.