Utrata walidacji i dokładność pozostają stałe


12

Próbuję zaimplementować ten artykuł na zestawie obrazów medycznych. Robię to w Keras. Sieć zasadniczo składa się z 4 warstw konwekcyjnych i maksymalnych pul, po których następuje w pełni połączona warstwa i miękki klasyfikator maksymalny.

O ile wiem, postępowałem zgodnie z architekturą wymienioną w artykule. Jednak utrata walidacji i dokładność pozostają płaskie. Dokładność wydaje się być ustalona na ~ 57,5%.

Byłbym bardzo wdzięczny za wszelką pomoc dotyczącą tego, gdzie popełniłem błąd.

Mój kod:

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)

Czy spada strata treningowa?
Jan van der Vegt

Nie, utrata treningu również pozostaje stała.
Raghuram

Nie ustawiłeś żadnych danych sprawdzających poprawność ani sprawdzania poprawności w sprawdzonym połączeniu, na czym by się sprawdził? Czy miałeś na myśli test?
Jan van der Vegt

To jest po eksperymentowaniu wokół. Ustawiłem validation_split = 0.2 przed ustawieniem go na None i eksperymentowałem z tym również.
Raghuram

2
Czy zdołasz dopasować jedną partię wiele razy, aby sprawdzić, czy uda ci się obniżyć straty treningowe?
Jan van der Vegt

Odpowiedzi:


4

Wygląda na to, że używasz MSE jako funkcji utraty, z rzutu oka na papier wydaje się, że używają NLL (cross entropii), MSE jest uważany za podatny na wrażliwość na nierównowagę danych wśród innych problemów i może być przyczyną problemu doświadczenie, spróbowałbym trenować z wykorzystaniem utraty categorical_crossentropy w twoim przypadku, ponadto wskaźnik uczenia się wynoszący 0,01 wydaje się zbyt duży Próbowałbym z nim grać i wypróbować 0,001 lub nawet 0,0001


2

Chociaż jestem tutaj trochę spóźniony, chciałbym włożyć moje dwa centy, ponieważ pomogło mi to ostatnio rozwiązać podobny problem. Na ratunek przyszło mi skalowanie cech do zakresu (0,1) oprócz kategorycznej utraty entropii krzyżowej. Niemniej jednak warto powiedzieć, że skalowanie funkcji pomaga tylko wtedy, gdy cechy należą do różnych metryk i mają znacznie większą zmienność (w rzędach wielkości) względem siebie, jak to było w moim przypadku. Również skalowanie może być bardzo przydatne, jeśli używa się hingestraty, ponieważ klasyfikatory o maksymalnym marginesie są ogólnie wrażliwe na odległości między wartościami cech. Mam nadzieję, że pomoże to niektórym przyszłym użytkownikom!

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.