Керас: Недостаточно памяти при поиске по сетке гиперпараметров

Я запускаю несколько вложенных циклов для поиска по сетке гиперпараметров. Каждый вложенный цикл проходит через список значений гиперпараметров, а внутри самого внутреннего цикла создается последовательная модель Keras, которая каждый раз оценивается с помощью генератора. (Я не занимаюсь обучением, я просто произвольно инициализирую, а затем несколько раз оцениваю модель, а затем извлекаю среднюю потерю).

Моя проблема в том, что во время этого процесса Keras, кажется, заполняет мою память графического процессора, поэтому я в конечном итоге получаю ошибку OOM.

Кто-нибудь знает, как решить эту проблему и освободить память графического процессора каждый раз после оценки модели?

Мне больше не нужна модель после того, как она была оценена, я могу полностью выбросить ее каждый раз, прежде чем строить новую на следующем проходе внутреннего цикла.

Я использую бэкэнд Tensorflow.

Вот код, хотя большая часть его не имеет отношения к общей проблеме. Модель строится внутри четвертого контура,

for fsize in fsizes:

Я предполагаю, что детали того, как построена модель, не имеют большого значения, но в любом случае вот все:

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

person Alex    schedule 05.02.2017    source источник
comment
Вы используете тензорный поток или бэкэнд Theano?   -  person indraforyou    schedule 05.02.2017
comment
@indraforyou Я использую бэкэнд Tensorflow, извините, что не упомянул об этом!   -  person Alex    schedule 05.02.2017


Ответы (2)


Как указано, используется бэкэнд Tensorflow. С бэкэндом Tensorflow текущая модель не уничтожается, поэтому вам нужно очистить сеанс.

После использования модели просто поставьте:

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

Включите бэкэнд:

from keras import backend as K

Также вы можете использовать оболочку sklearn для поиска по сетке. Проверьте этот пример: здесь. Также для более расширенного поиска по гиперпараметрам вы можете использовать гиперы.

person indraforyou    schedule 05.02.2017
comment
Ты великолепен! Большое спасибо, это именно то, что мне нужно было понять. И большое спасибо за то, что указали мне на гиперопт / гиперы! - person Alex; 05.02.2017
comment
Я думал, keras.wrappers.scikit_learn.KerasClassifier позаботится об этом. Проблем при запуске данного примера у меня не возникло. Если вы столкнулись с проблемой, отправьте ее на Keras github. - person indraforyou; 10.01.2018

Используя совет, данный indraforyou, я добавил код для очистки сеанса TensorFlow внутри функции, которую я передаю GridSearchCV, например:

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

Затем я могу вызвать поиск по сетке:

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

Он должен работать.

Ваше здоровье!

person Andrey Kuehlkamp    schedule 28.11.2018