Как сохранить лучшие оптимизированные для hyperopt модели keras и их вес? - PullRequest
0 голосов
/ 20 января 2019

Я оптимизировал свою модель keras, используя hyperopt. Теперь, как сохранить лучшую оптимизированную модель keras и ее веса на диск.

Мой код:

from hyperopt import fmin, tpe, hp, STATUS_OK, Trials
from sklearn.metrics import roc_auc_score
import sys

X = []
y = []
X_val = []
y_val = []

space = {'choice': hp.choice('num_layers',
                    [ {'layers':'two', },
                    {'layers':'three',
                    'units3': hp.uniform('units3', 64,1024), 
                    'dropout3': hp.uniform('dropout3', .25,.75)}
                    ]),

            'units1': hp.choice('units1', [64,1024]),
            'units2': hp.choice('units2', [64,1024]),

            'dropout1': hp.uniform('dropout1', .25,.75),
            'dropout2': hp.uniform('dropout2',  .25,.75),

            'batch_size' : hp.uniform('batch_size', 20,100),

            'nb_epochs' :  100,
            'optimizer': hp.choice('optimizer',['adadelta','adam','rmsprop']),
            'activation': 'relu'
        }

def f_nn(params):   
    from keras.models import Sequential
    from keras.layers.core import Dense, Dropout, Activation
    from keras.optimizers import Adadelta, Adam, rmsprop

    print ('Params testing: ', params)
    model = Sequential()
    model.add(Dense(output_dim=params['units1'], input_dim = X.shape[1])) 
    model.add(Activation(params['activation']))
    model.add(Dropout(params['dropout1']))

    model.add(Dense(output_dim=params['units2'], init = "glorot_uniform")) 
    model.add(Activation(params['activation']))
    model.add(Dropout(params['dropout2']))

    if params['choice']['layers']== 'three':
        model.add(Dense(output_dim=params['choice']['units3'], init = "glorot_uniform")) 
        model.add(Activation(params['activation']))
        model.add(Dropout(params['choice']['dropout3']))    

    model.add(Dense(1))
    model.add(Activation('sigmoid'))
    model.compile(loss='binary_crossentropy', optimizer=params['optimizer'])

    model.fit(X, y, nb_epoch=params['nb_epochs'], batch_size=params['batch_size'], verbose = 0)

    pred_auc =model.predict_proba(X_val, batch_size = 128, verbose = 0)
    acc = roc_auc_score(y_val, pred_auc)
    print('AUC:', acc)
    sys.stdout.flush() 
    return {'loss': -acc, 'status': STATUS_OK}


trials = Trials()
best = fmin(f_nn, space, algo=tpe.suggest, max_evals=100, trials=trials)
print 'best: '
print best

Ответы [ 3 ]

0 голосов
/ 10 марта 2019

Сделать f_nn вернуть модель.

def f_nn(params):
    # ...
    return {'loss': -acc, 'status': STATUS_OK, 'model': model}

Модели будут доступны на trials объекте под results. Я вставил некоторые данные и получил print(trials.results), чтобы выплюнуть

[{'loss': 2.8245880603790283, 'status': 'ok', 'model': <keras.engine.training.Model object at 0x000001D725F62B38>}, {'loss': 2.4592788219451904, 'status': 'ok', 'model': <keras.engine.training.Model object at 0x000001D70BC3ABA8>}]

Используйте np.argmin, чтобы найти наименьшую потерю, затем сохраните, используя model.save

trials.results[np.argmin([r['loss'] for r in trials.results])]['model']

(Примечание: в C # это будет trials.results.min(r => r.loss).model ... если есть лучший способ сделать это в Python, пожалуйста, дайте мне знать!)

Вы можете использовать attachments на пробном объекте, если вы используете MongoDB, так как модель может быть очень большой:

attachments - словарь пар ключ-значение, ключи которого являются короткими строками (например, имена файлов), а значения - потенциально длинными строками (например, содержимым файла), которые не следует загружать из базы данных каждый раз, когда мы получаем доступ к записи. (Кроме того, MongoDB ограничивает длину обычных пар ключ-значение, поэтому, если ваше значение указано в мегабайтах, вам может потребоваться сделать его вложением.) Source.

0 голосов
/ 28 марта 2019

Trials Объект класса хранит много релевантной информации, связанной с каждой итерацией hyperopt.Мы также можем попросить этот объект сохранить обученную модель.Чтобы добиться этого, вам нужно сделать несколько небольших изменений в базе кода.

-- return {'loss': -acc, 'status': STATUS_OK}
++ return {'loss':loss, 'status': STATUS_OK, 'Trained_Model': model}

Примечание: 'Trained_Model' - просто ключ, и вы можете использовать любую другую строку.

best = fmin(f_nn, space, algo=tpe.suggest, max_evals=100, trials=trials)
model = getBestModelfromTrials(trials)

Извлечение обученной модели из испытаний объекта:

import numpy as np
from hyperopt import STATUS_OK
def getBestModelfromTrials(trials):
    valid_trial_list = [trial for trial in trials
                            if STATUS_OK == trial['result']['status']]
    losses = [ float(trial['result']['loss']) for trial in valid_trial_list]
    index_having_minumum_loss = np.argmin(losses)
    best_trial_obj = valid_trial_list[index_having_minumum_loss]
    return best_trial_obj['result']['Trained_Model']

Примечание: Я использовал этот подход в классах Scikit-Learn.

0 голосов
/ 20 января 2019

Я не знаю, как отправить какую-то переменную в f_nn или другую явную цель гиперопции. Но я использую два подхода для выполнения одной и той же задачи.
Первый подход - это некоторая глобальная переменная (не нравится, потому что она не ясна), а второй - сохранить значение метрики в файл, затем прочитать и сравнить с текущей метрикой. Последний подход кажется мне лучше.

def f_nn(params):
    ...
    # I omit a part of the code   
    pred_auc =model.predict_proba(X_val, batch_size = 128, verbose = 0)
    acc = roc_auc_score(y_val, pred_auc)

    try:
        with open("metric.txt") as f:
            min_acc = float(f.read().strip())  # read best metric,
    except FileNotFoundError:
            min_acc = acc  # else just use current value as the best

    if acc < min_acc:
         model.save("model.hd5")  # save best to disc and overwrite metric
         with open("metric.txt", "w") as f:
             f.write(str(acc))

    print('AUC:', acc)
    sys.stdout.flush() 
    return {'loss': -acc, 'status': STATUS_OK}

trials = Trials()
best = fmin(f_nn, space, algo=tpe.suggest, max_evals=100, trials=trials)
print 'best: '
print best

from keras.models import load_model
best_model = load_model("model.hd5")

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

Редактировать
Это может вызвать неожиданное поведение, если есть метрика из предыдущего запуска, но вы не удалите ее. Таким образом, вы можете принять код - удалить метрику после оптимизации или использовать метку времени и т. Д., Чтобы различать данные ваших экспериментов.

...