2017-05-12 6 views
2

Ich verwende Keras 2.0.4 (TensorFlow-Backend) für eine Bildklassifizierungsaufgabe (basierend auf vortrainierten Modellen). Während des Trainings/Tunens verfolge ich alle verwendeten Metriken (z. B. categorical_accuracy, categorical crossentropy) mit CSVLogger - einschließlich der zugehörigen Metriken, die dem Validierungssatz zugeordnet sind (d. H. val_categorical_accuracy, val_categorical_crossentropy).Warum unterscheiden sich die von model.evaluate() berechneten Metriken während des Trainings in Keras?

Mit dem Rückruf ModelCheckpoint bin ich die beste Konfiguration der Gewichte (save_best_only=True). Um das Modell auf dem Validierungssatz zu bewerten, verwende ich model.evaluate().

Meine Erwartung ist: tracked Metriken von CSVLogger (der 'besten' Epoche) gleich der Metriken berechnet von model.evaluate(). Leider ist das NICHT der Fall. Die Metriken unterscheiden sich um + - 5%. Gibt es einen Grund für dieses Verhalten?


EDIT:

Nach einigen Tests habe ich einige Erkenntnisse gewinnen konnte:

  1. Wenn ich nicht einen Generator für die Ausbildung und Validierungsdaten verwenden (und somit auch keine model.fit_generator()), das Problem tritt nicht auf. -> Die Verwendung der ImageDataGenerator für Trainings- und Validierungsdaten ist die Ursache der Diskrepanz. (Bitte beachten Sie, für die Berechnung der evaluate I nicht einen Generator verwenden, aber ich die gleichen Validierungsdaten verwenden tun (zumindest, wenn DataImageGenerator funktionieren würde, wie erwartet ...).
    Ich denke, doesn der ImageDataGenerator (Bitte, siehe auch this).
  2. Wenn ich überhaupt keine Generatoren verwende, wird es dieses Problem nicht geben.Ist est tracked metrics von CSVLogger (der 'besten' Epoche) Die von model.evaluate() berechneten Werte sind gleich
    Interessanterweise gibt es ein anderes Problem: Wenn Sie die gleichen Daten für Training und Validierung verwenden, wird es eine Diskrepanz sein Tween-Trainingsmetriken (z.B. loss) und Validierungsmetriken (z.B. val_loss) am Ende jeder Epoche.
    (A similar problem)

Gebrauchte Code:

############################ import section ############################ 
from __future__ import print_function # perform like in python 3.x 
from keras.datasets import mnist 
from keras.utils import np_utils # numpy utils for to_categorical() 
from keras.models import Model, load_model 
from keras.layers import Dense, GlobalAveragePooling2D, Dropout, GaussianDropout, Conv2D, MaxPooling2D 
from keras.optimizers import SGD, Adam 
from keras import backend as K 
from keras.preprocessing.image import ImageDataGenerator 
from keras import metrics 
import os 
import sys 
from scipy import misc 
import numpy as np 
from keras.applications.vgg16 import preprocess_input as vgg16_preprocess_input 
from keras.applications import VGG16 
from keras.callbacks import CSVLogger, ModelCheckpoint 


############################ manual settings ########################### 
# general settings 
seed = 1337 

loss_function = 'categorical_crossentropy' 

learning_rate = 0.001 

epochs = 10 

batch_size = 20 

nb_classes = 5 

img_width, img_height = 400, 400 # >= 48 necessary, as VGG16 is used 

chosen_optimizer = SGD(lr=learning_rate, momentum=0.0, decay=0.0, nesterov=False) 

steps_per_epoch = 40 // batch_size # 40 train samples in 5 classes 
validation_steps = 40 // batch_size # 40 train samples in 5 classes 

data_dir = # TODO: set path where data is stored (folders: 'train', 'val', 'test'; within each folder are folders named by classes) 

# callbacks: CSVLogger & ModelCheckpoint 
filepath = # TODO: set path, where you want to store files generated by the callbacks 
file_best_checkpoint= 'best_epoch.hdf5' 
file_csvlogger = 'logged_metrics.txt' 

modelcheckpoint_best_epoch= ModelCheckpoint(filepath=os.path.join(filepath, file_best_checkpoint), 
            monitor = 'val_loss' , verbose = 1, 
            save_best_only = True, 
            save_weights_only=False, mode='auto', 
            period=1) # every epoch executed 
csvlogger = CSVLogger(os.path.join(filepath, file_csvlogger) , separator=',', append=False) 



############################ prepare data ############################## 
# get validation data (for evaluation) 
X_val, Y_val = # TODO: load train data (4darray, samples, img_width, img_height, nb_channels) IMPORTANT: 5 classes with 8 images each. 

# preprocess data 
my_preprocessing_function = mf.my_vgg16_preprocess_input 

# 'augmentation' configuration we will use for training 
train_datagen = ImageDataGenerator(preprocessing_function = my_preprocessing_function) # only preprocessing; static data set 

# 'augmentation' configuration we will use for validation 
val_datagen = ImageDataGenerator(preprocessing_function = my_preprocessing_function) # only preprocessing; static data set 

train_data_dir = os.path.join(data_dir, 'train') 
validation_data_dir = os.path.join(data_dir, 'val') 
train_generator = train_datagen.flow_from_directory(
    train_data_dir, 
    target_size=(img_width, img_height), 
    batch_size=batch_size, 
    shuffle = True, 
    seed = seed, # random seed for shuffling and transformations 
    class_mode='categorical') # label type (categorical = one-hot vector) 

validation_generator = val_datagen.flow_from_directory(
    validation_data_dir, 
    target_size=(img_width, img_height), 
    batch_size=batch_size, 
    shuffle = True, 
    seed = seed, # random seed for shuffling and transformations 
    class_mode='categorical') # label type (categorical = one-hot vector) 



############################## training ############################### 
print("\n---------------------------------------------------------------") 
print("------------------------ training model -----------------------") 
print("---------------------------------------------------------------") 
# create the base pre-trained model 
base_model = VGG16(include_top=False, weights = None, input_shape=(img_width, img_height, 3), pooling = 'max', classes = nb_classes) 
model_name = "VGG_modified" 

# do not freeze any layers --> all layers trainable 
for layer in base_model.layers: 
    layer.trainable = True 

# define topping of base_model 
x = base_model.output # get the last layer of our base_model 
x = Dense(1024, activation='relu', name='fc1')(x) 
x = Dense(1024, activation='relu', name='fc2')(x) 
predictions = Dense(nb_classes, activation='softmax', name='predictions')(x) 

# finally, stack model together 
model = Model(outputs=predictions, name= model_name, inputs=base_model.input) #Keras 1.x.x: model = Model(input=base_model.input, output=predictions) 
print(model.summary()) 

# compile the model (should be done *after* setting layers to non-trainable) 
model.compile(optimizer = chosen_optimizer, loss=loss_function, 
      metrics=['categorical_accuracy','kullback_leibler_divergence']) 

# train the model on your data 
model.fit_generator(
    train_generator, 
    steps_per_epoch=steps_per_epoch, 
    epochs=epochs, 
    validation_data=validation_generator, 
    validation_steps=validation_steps, 
    callbacks = [csvlogger, modelcheckpoint_best_epoch]) 



############################## evaluation ############################## 
print("\n\n---------------------------------------------------------------") 
print("------------------ Evaluation of Best Epoch -------------------") 
print("---------------------------------------------------------------") 
# load model (corresponding to best training epoch) 
model = load_model(os.path.join(filepath, file_best_checkpoint)) 

# evaluate model on validation data (in test mode!) 
list_of_metrics = model.evaluate(X_val, Y_val, batch_size=batch_size, verbose=1, sample_weight=None) 
index = 0 
print('\nMetrics:') 
for metric in model.metrics_names: 
    print(metric+ ':' , str(list_of_metrics[index])) 
    index += 1 

EDIT 2
auf 1 von EDIT Bezug: Wenn ich den gleichen Generator für Validierungsdaten während des Trainings und Bewertung (mithilfe von evaluate_generator()) tritt das Problem weiterhin auf. Daher ist es definitiv ein Problem, das durch die Generatoren verursacht wird ...

Antwort

0

Dies ist nur der Fall für die Auswertung der Metriken im Validierungsdatensatz.

Die auf dem Trainingsdatensatz während des Trainings berechneten Messwerte geben nicht die tatsächlichen Messwerte des Modells am Ende der Epoche wieder, da das Modell bei jedem einzelnen Batch aktualisiert (modifiziert) wird.

Hilft das?

+0

CSVLogger verfolgt Metriken auf dem Validierungsset nach jeder Epoche. Nehmen wir an, die letzte Epoche würde die beste Konfiguration von Gewichten ergeben. Das bedeutet, dass die letzten verfolgten Metriken im Validierungssatz die Metriken sind, wenn sie im Validierungssatz ausgewertet werden. Was vermisse ich? –

+0

hm Wie lautet die Metrik, um nur das Beste zu speichern? –

+0

überwacht Menge ist Validierungs Verlust ('val_categorical_crossentropy') –

Verwandte Themen