Завантажте треновану модель Keras і продовжуйте тренування


98

Мені було цікаво, чи можливо зберегти частково навчену модель Keras і продовжити навчання після завантаження моделі знову.

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

Я використовую такі функції:

#Partly train model
model.fit(first_training, first_classes, batch_size=32, nb_epoch=20)

#Save partly trained model
model.save('partly_trained.h5')

#Load partly trained model
from keras.models import load_model
model = load_model('partly_trained.h5')

#Continue training
model.fit(second_training, second_classes, batch_size=32, nb_epoch=20)

Редагування 1: додано повністю робочий приклад

З першим набором даних через 10 епох втрата останньої епохи становитиме 0,0748, а точність 0,9863.

Після збереження, видалення та перезавантаження моделі втрати та точність моделі, навченої на другому наборі даних, становитимуть 0,1711 та 0,9504 відповідно.

Це спричинено новими даними про навчання чи повністю перекваліфікованою моделлю?

"""
Model by: http://machinelearningmastery.com/
"""
# load (downloaded if needed) the MNIST dataset
import numpy
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense
from keras.utils import np_utils
from keras.models import load_model
numpy.random.seed(7)

def baseline_model():
    model = Sequential()
    model.add(Dense(num_pixels, input_dim=num_pixels, init='normal', activation='relu'))
    model.add(Dense(num_classes, init='normal', activation='softmax'))
    model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
    return model

if __name__ == '__main__':
    # load data
    (X_train, y_train), (X_test, y_test) = mnist.load_data()

    # flatten 28*28 images to a 784 vector for each image
    num_pixels = X_train.shape[1] * X_train.shape[2]
    X_train = X_train.reshape(X_train.shape[0], num_pixels).astype('float32')
    X_test = X_test.reshape(X_test.shape[0], num_pixels).astype('float32')
    # normalize inputs from 0-255 to 0-1
    X_train = X_train / 255
    X_test = X_test / 255
    # one hot encode outputs
    y_train = np_utils.to_categorical(y_train)
    y_test = np_utils.to_categorical(y_test)
    num_classes = y_test.shape[1]

    # build the model
    model = baseline_model()

    #Partly train model
    dataset1_x = X_train[:3000]
    dataset1_y = y_train[:3000]
    model.fit(dataset1_x, dataset1_y, nb_epoch=10, batch_size=200, verbose=2)

    # Final evaluation of the model
    scores = model.evaluate(X_test, y_test, verbose=0)
    print("Baseline Error: %.2f%%" % (100-scores[1]*100))

    #Save partly trained model
    model.save('partly_trained.h5')
    del model

    #Reload model
    model = load_model('partly_trained.h5')

    #Continue training
    dataset2_x = X_train[3000:]
    dataset2_y = y_train[3000:]
    model.fit(dataset2_x, dataset2_y, nb_epoch=10, batch_size=200, verbose=2)
    scores = model.evaluate(X_test, y_test, verbose=0)
    print("Baseline Error: %.2f%%" % (100-scores[1]*100))

3
Ви перевіряли? Я не бачу причин, щоб не працювати.
маз

Зараз я бачу, що моя точність падає приблизно на 10 відсотків після завантаження моделі (лише в перші епохи). Якщо перезавантаження працює, це, звичайно, спричинено новими навчальними даними. Але я просто хочу переконатися, що це справді так.
Вільмар ван Оммерен

7
Ви зберігаєте свою модель безпосередньо за допомогою model.save або використовуєте контрольну точку моделі ( keras.io/callbacks/#example-model-checkpoints )? Якщо ви використовуєте model.save, чи існує ймовірність того, що ви зберігаєте останню модель (тобто останню епоху) замість найкращої (найменша помилка)? Чи можете ви надати фактичний код?
maz

Я зберігаю свою останню, не найкращу модель (до цього моменту я не знав, що це можливо). Я підготую код
Вілмар ван Оммерен,

3
Тож чи не могли б ви перезавантажити це і продовжити навчання на тих самих даних поїзда? Це повинно переконати вас, що перезавантаження - це нормально, якщо результати будуть порівнянними.
Marcin Możejko

Відповіді:


36

Фактично - model.saveзберігає всю інформацію, необхідну для перезапуску навчання у вашому випадку. Єдине, що можна зіпсувати перезавантаженням моделі, це стан вашого оптимізатора. Щоб це перевірити - спробуйте saveперезавантажити модель та навчіть її на тренувальних даних.


1
@Marcin: чи використовує керас save()найкращий результат (найменші втрати) моделі чи останній результат (останнє оновлення) моделі? подяка
Lion Lai

5
Останнє оновлення. Зворотний дзвінок контрольної точки моделі для збереження найкращого.
Холі

2
@Khaj Ви маєте на увазі цей keras.io/callbacks/#modelcheckpoint ? Здається, за замовчуванням воно зберігає останнє оновлення (не найкраще); найкращий зберігається лише в тому випадку, якщо save_best_only=Trueвстановлений явно.
flow2k

7

Проблема може полягати в тому, що ви використовуєте інший оптимізатор - або інші аргументи свого оптимізатора. Я просто мав таку ж проблему з користувацькою попередньо навченою моделлю, використовуючи

reduce_lr = ReduceLROnPlateau(monitor='loss', factor=lr_reduction_factor,
                              patience=patience, min_lr=min_lr, verbose=1)

для попередньо навченої моделі, згідно з якою початкова швидкість навчання починається з 0,0003, а під час попередньої підготовки вона зменшується до мінімальної швидкості навчання, яка становить 0,000003

Я просто скопіював цей рядок до сценарію, який використовує попередньо навчену модель і отримав дуже погану точність. Поки я не помітив, що останньою швидкістю навчання попередньо навченої моделі була мінімальна швидкість навчання, тобто 0,000003. І якщо я починаю з такої швидкості навчання, я отримую точно такі самі точні показники, як і вихід попередньо навченої моделі, - що має сенс, як, починаючи з швидкості навчання, яка в 100 разів більша за останню швидкість навчання, використана в попередньо навченій модель призведе до величезного перевищення GD і, отже, до значно зниженої точності.


5

Більшість наведених відповідей охоплювали важливі моменти. Якщо ви використовуєте недавній Tensorflow ( TF2.1або вище), тоді наступний приклад вам допоможе. Модельна частина коду з веб-сайту Tensorflow.

import tensorflow as tf
from tensorflow import keras
mnist = tf.keras.datasets.mnist

(x_train, y_train),(x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0

def create_model():
  model = tf.keras.models.Sequential([
    tf.keras.layers.Flatten(input_shape=(28, 28)),
    tf.keras.layers.Dense(512, activation=tf.nn.relu),  
    tf.keras.layers.Dropout(0.2),
    tf.keras.layers.Dense(10, activation=tf.nn.softmax)
    ])

  model.compile(optimizer='adam', loss='sparse_categorical_crossentropy',metrics=['accuracy'])
  return model

# Create a basic model instance
model=create_model()
model.fit(x_train, y_train, epochs = 10, validation_data = (x_test,y_test),verbose=1)

Збережіть модель у форматі * .tf. З мого досвіду, якщо у вас визначено будь-який custom_loss, формат * .h5 не збереже статус оптимізатора і, отже, не буде відповідати вашим цілям, якщо ви хочете перекваліфікувати модель з того місця, де ми залишили.

# saving the model in tensorflow format
model.save('./MyModel_tf',save_format='tf')


# loading the saved model
loaded_model = tf.keras.models.load_model('./MyModel_tf')

# retraining the model
loaded_model.fit(x_train, y_train, epochs = 10, validation_data = (x_test,y_test),verbose=1)

Цей підхід дозволить перезапустити навчання там, де ми залишились перед збереженням моделі. Як вже зазначалося іншими, якщо ви хочете зберегти вагу кращої моделі або ви хочете зберегти ваги моделі кожну епоху вам потрібно використовувати keras зворотні виклики функцій (ModelCheckpoint) з опціями , такими як save_weights_only=True, save_freq='epoch'і save_best_only.

Для отримання детальної інформації перегляньте тут та інший приклад тут .


1
приємно, це виглядає дуже перспективно - дякую за інформацію. у цьому прикладі мені здається, ніби ви перекваліфікуєте модель за тими ж даними, які використовувались для навчання. якщо так, то я міг би подумати, що правильним підходом буде завантаження нової підгрупи навчальних даних для перекваліфікації (з метою відображення нової інформації, що вводиться в процес)?
bibzzzz

1
@bibzzzz Погодься з вами. Дуже хороший коментар. Я хотів продемонструвати перекваліфікацію на тих самих даних, щоб поліпшити ефективність. Суть чітко демонструє покращення продуктивності там, де вона була зупинена перед збереженням моделі. Я б повністю погодився з вами перекваліфікувати різні дані і спробую пізніше. Дякую!
Вішнувардхан Джанапаті

відмінно - ви це дуже добре продемонстрували, дякую.
bibzzzz

2

Зверніть увагу, що у Keras іноді виникають проблеми із завантаженими моделями, як тут . Це може пояснити випадки, коли ви починаєте не з тієї самої навченої точності.


1

Все вищезазначене допомагає, ви повинні перейти з тієї ж швидкості навчання (), що і LR, коли модель та ваги були збережені. Встановіть його безпосередньо на оптимізаторі.

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


Чому так? Чи не можу я використовувати менший LR, ніж раніше?
lte__

Насправді, продовження навчання МОЖЕ привести вас до кращої моделі, якщо ви отримаєте більше даних. Отже, є сенс відновити модель для пошуку іншого локального мінімуму.
Корі Левінсон,

0

Можливо, ви також потрапляєте в Concept Drift, див. Чи слід перекваліфікувати модель, коли доступні нові спостереження . Існує також концепція катастрофічного забуття, яку обговорює купа наукових робіт. Ось один із емпіричних досліджень MNIST катастрофічного забуття

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.