首页 文章

Keras:进行超参数网格搜索时内存不足

提问于
浏览
10

我正在运行多个嵌套循环来进行超参数网格搜索 . 每个嵌套循环遍历超级参数值列表,并且在最内层循环内部,每次使用生成器构建和评估Keras顺序模型 . (我没有做任何训练,我只是随机初始化,然后多次评估模型,然后检索平均损失) .

我的问题是,在这个过程中,Keras似乎填满了我的GPU内存,所以我最终得到了一个OOM错误 .

在评估模型后,是否有人知道如何解决这个问题并释放GPU内存?

在评估之后我根本不需要模型,我可以在内循环的下一次传递中构建一个新模型之前完全抛弃它 .

我正在使用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()

2 回答

  • 1

    如图所示,使用的后端是Tensorflow . 使用Tensorflow后端,当前模型不会被破坏,因此您需要清除会话 .

    使用完模型之后只需:

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

    包括后端:

    from keras import backend as K
    

    您也可以使用sklearn包装器进行网格搜索 . 检查此示例:here . 此外,对于更高级的超参数搜索,您可以使用hyperas .

  • 14

    使用indraforyou给出的提示,我添加了代码以清除我传递给GridSearchCV的函数内的TensorFlow会话,如下所示:

    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)
    

    它应该工作 .

    干杯!

相关问题