Keras: memoria insuficiente cuando se realiza una búsqueda en una malla de parámetros hiper

Estoy ejecutando múltiples bucles nesteds para hacer la búsqueda de la cuadrícula de hiper parámetros. Cada bucle nested se ejecuta a través de una lista de valores de hiperparámetros y, dentro del bucle más interno, se construye y evalúa un modelo secuencial de Keras cada vez que se utiliza un generador. (No estoy haciendo ningún entrenamiento, solo estoy inicializando al azar y luego evaluando el modelo varias veces y luego recuperando la pérdida promedio).

Mi problema es que durante este proceso, Keras parece estar llenando la memoria de mi GPU, por lo que eventualmente recibo un error de OOM.

¿Alguien sabe cómo resolver esto y liberar la memoria de la GPU cada vez que se evalúa un modelo?

Ya no necesito el modelo después de que se haya evaluado, puedo desecharlo por completo cada vez antes de construir uno nuevo en la próxima pasada del ciclo interno.

Estoy usando el backend Tensorflow.

Aquí está el código, aunque gran parte de él no es relevante para el problema general. El modelo está construido dentro del cuarto bucle,

for fsize in fsizes: 

Supongo que los detalles de cómo se construye el modelo no importan mucho, pero aquí está todo de todos modos:

 model_losses = [] model_names = [] for activation in activations: for i in range(len(layer_structures)): for width in layer_widths[i]: for fsize in fsizes: model_name = "test_{}_struc-{}_width-{}_fsize-{}".format(activation,i,np.array_str(np.array(width)),fsize) model_names.append(model_name) print("Testing new model: ", model_name) #Structure for this network structure = layer_structures[i] row, col, ch = 80, 160, 3 # Input image format model = Sequential() model.add(Lambda(lambda x: x/127.5 - 1., input_shape=(row, col, ch), output_shape=(row, col, ch))) for j in range(len(structure)): if structure[j] == 'conv': model.add(Convolution2D(width[j], fsize, fsize)) model.add(BatchNormalization(axis=3, momentum=0.99)) if activation == 'relu': model.add(Activation('relu')) if activation == 'elu': model.add(ELU()) model.add(MaxPooling2D()) elif structure[j] == 'dense': if structure[j-1] == 'dense': model.add(Dense(width[j])) model.add(BatchNormalization(axis=1, momentum=0.99)) if activation == 'relu': model.add(Activation('relu')) elif activation == 'elu': model.add(ELU()) else: model.add(Flatten()) model.add(Dense(width[j])) model.add(BatchNormalization(axis=1, momentum=0.99)) if activation == 'relu': model.add(Activation('relu')) elif activation == 'elu': model.add(ELU()) model.add(Dense(1)) average_loss = 0 for k in range(5): model.compile(optimizer="adam", loss="mse") val_generator = generate_batch(X_val, y_val, resize=(160,80)) loss = model.evaluate_generator(val_generator, len(y_val)) average_loss += loss average_loss /= 5 model_losses.append(average_loss) print("Average loss after 5 initializations: {:.3f}".format(average_loss)) print() 

Como se indica, el backend que se utiliza es Tensorflow. Con el backend de Tensorflow, el modelo actual no se destruye, por lo que debe borrar la sesión.

Después de que el uso del modelo acaba de poner:

 if K.backend() == 'tensorflow': K.clear_session() 

Incluir el backend:

 from keras import backend as K 

También puedes usar sklearn wrapper para hacer la búsqueda de cuadrícula. Mira este ejemplo: aquí . También para una búsqueda más avanzada de hiperparámetros puede usar hiperas .

Usando la sugerencia proporcionada por indraforyou, agregué el código para borrar la sesión de TensorFlow dentro de la función que paso a GridSearchCV, como esto:

 def create_model(): # cleanup K.clear_session() inputs = Input(shape=(4096,)) x = Dense(2048, activation='relu')(inputs) p = Dense(2, activation='sigmoid')(x) model = Model(input=inputs, outputs=p) model.compile(optimizer='SGD', loss='mse', metrics=['accuracy']) return model 

Y luego puedo invocar la búsqueda de cuadrícula:

 model = KerasClassifier(build_fn=create_model) grid = GridSearchCV(estimator=model, param_grid=param_grid, n_jobs=1) 

Deberia de funcionar.

¡Aclamaciones!