выбор модели с Keras и Theano занимает очень много времени

Я выполняю вложенную перекрестную проверку для выбора модели и оценки производительности для набора рекуррентных нейронных сетей с различными архитектурами и параметрами, используя Keras и Theano, которые настроены для работы на экземпляре AWS P2 с графическим процессором Tesla K80 с CUDA и cuDNN установлен/включен.

Чтобы выполнить выбор модели, я сравниваю 30 моделей, выбранных из пространства параметров, используя

param_grid = {
             'nb_hidden_layers': [1, 2, 3],
             'dropout_frac': [0.15, 0.20],
             'output_activation': ['sigmoid', 'softmax'],
             'optimization': ['Adedelta', 'RMSprop', 'Adam'],
             'learning_rate': [0.001, 0.005, 0.010],
             'batch_size': [64, 100, 150, 200],
             'nb_epoch': [10, 15, 20],
             'perform_batchnormalization': [True, False]
             }
params_list = list(ParameterSampler(param_grid, n_iter = 30))

Затем я создаю модель RNN, используя функцию NeuralNetworkClassifier(), определенную ниже.

def NeuralNetworkClassifier(params, units_in_hidden_layer = [50, 75, 100, 125, 150]):
    nb_units_in_hidden_layers = np.random.choice(units_in_hidden_layer, size = params['nb_hidden_layers'], replace = False)

    layers = [8]    # number of features in every week
    layers.extend(nb_units_in_hidden_layers)
    layers.extend([1])  # node identifying quit/stay

    model = Sequential()

    # constructing all layers up to, but not including, the penultimate one
    layer_idx = -1  # this ensures proper generalization nb_hidden_layers = 1 (for which the loop below will never run)
    for layer_idx in range(len(layers) - 3):
        model.add(LSTM(input_dim = layers[layer_idx], output_dim = layers[layer_idx + 1], init = 'he_uniform', return_sequences = True))    # all LSTM layers, up to and including the penultimate one, need return_sequences = True
        if params['perform_batchnormalization'] == True:
            model.add(BatchNormalization())
            model.add(Activation('relu'))
        model.add(Dropout(params['dropout_frac']))
    # constructing the penultimate layer
    model.add(LSTM(input_dim = layers[layer_idx + 1], output_dim = layers[(layer_idx + 1) + 1], init = 'he_uniform', return_sequences = False)) # the last LSTM layer needs return_sequences = False
    if params['perform_batchnormalization'] == True:
        model.add(BatchNormalization())
        model.add(Activation('relu'))
    model.add(Dropout(params['dropout_frac']))
    # constructing the final layer
    model.add(Dense(output_dim = layers[-1], init = 'he_normal'))
    model.add(Activation(params['output_activation']))

    if params['optimization'] == 'SGD':
        optim = SGD()
        optim.lr.set_value(params['learning_rate'])
    elif params['optimization'] == 'RMSprop':
        optim = RMSprop()
        optim.lr.set_value(params['learning_rate'])
    elif params['optimization'] == 'Adam':
        optim = Adam()
    elif params['optimization'] == 'Adedelta':
        optim = Adadelta()

    model.compile(loss = 'binary_crossentropy', optimizer = optim, metrics = ['precision'])

    return model

которые строят RNN, количество скрытых слоев которой задается параметром 'nb_hidden_layers' в param_grid, а количество скрытых единиц в каждом слое выбирается случайным образом из списка [50, 75, 100, 125, 150]. В конце эта функция compiles модель и возвращает ее.

Во время вложенной перекрестной проверки (CV) внутренний цикл (который выполняется IN раз) сравнивает производительность 30 случайно выбранных моделей. После этого шага я выбираю наиболее эффективную модель во внешнем цикле и оцениваю ее производительность на удержанном наборе данных; эта схема повторяется OUT раз. Поэтому я compileпросматриваю модель RNN OUTxINx30 раз, и это занимает очень много времени; например, когда OUT=4 и IN=3, мой метод занимает от 6 до 7 часов.

Я вижу, что GPU используется спорадически (но использование GPU никогда не превышает 40%); однако в большинстве случаев используется ЦП. Мое (необразованное) предположение заключается в том, что compile выполняется на ЦП много раз и занимает большую часть вычислительного времени, тогда как подгонка модели и прогнозирование выполняются на графическом процессоре и занимают короткое время.

Мои вопросы:

  1. Есть ли способ исправить эту ситуацию?
  2. Действительно ли compile выполняется на процессоре?
  3. Как люди делают вложенные резюме, чтобы выбрать лучшую архитектуру RNN?
  4. Разумно ли мне выполнять эту схему на рабочем сервере? Вы предлагаете мне сделать одно большое вложенное резюме, которое может занять 24 часа, чтобы выбрать наиболее эффективную модель, а затем просто использовать эту модель на рабочем сервере?

Спасибо вам всем.


person darXider    schedule 12.01.2017    source источник
comment
Комментарий nikicc здесь предлагает .compile()ing один раз во время самого первого сгиба и повторное использование начальных весов для остальных складок в перекрестной проверке. Попытка этого дала мне большой прирост скорости.   -  person darXider    schedule 17.01.2017


Ответы (1)


Я не могу ответить на все ваши вопросы, но все же надеюсь, что это поможет.

Компиляция выполняется в ЦП, поскольку она в основном состоит из операций с символическим графом и генерации кода. Что еще хуже, оптимизация графа ано использует чистый код Python, который может быть накладным по сравнению с реализацией C/C++.

Чтобы улучшить время компиляции theano (за счет производительности во время выполнения):

Используйте менее агрессивную оптимизацию

В /home/ec2-user/.theanorc добавить строку:

optimizer = fast_compile

Или полностью отключить оптимизацию с помощью:

optimizer = None

Прекомпилировать некоторые блоки

Если в ваших моделях есть общие блоки, вы можете предварительно скомпилировать их с помощью theano.OpFromGraph

Однако вы не можете сделать это в одном Керасе.

Переключить фреймворк

Keras поддерживает бэкенд tensorflow. По сравнению с theano, tensorflow больше похож на виртуальную машину, чем на компилятор. Обычно TF работает медленнее, чем theano, но компилируется намного быстрее.

person Kh40tiK    schedule 13.01.2017
comment
Спасибо за помощь. Я попробую первое предложение. Однако я не могу переключиться с Theano (меня попросили использовать Theano). - person darXider; 16.01.2017