Memuat model Keras yang terlatih dan melanjutkan pelatihan


102

Saya ingin tahu apakah mungkin untuk menyimpan model Keras yang sebagian terlatih dan melanjutkan pelatihan setelah memuat model lagi.

Alasannya adalah saya akan memiliki lebih banyak data pelatihan di masa mendatang dan saya tidak ingin melatih ulang seluruh model lagi.

Fungsi yang saya gunakan adalah:

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

Edit 1: menambahkan contoh yang berfungsi penuh

Dengan dataset pertama setelah 10 epoch, hilangnya epoch terakhir adalah 0,0748 dan akurasi 0,9863.

Setelah menyimpan, menghapus, dan memuat ulang model, kerugian dan akurasi model yang dilatih pada dataset kedua masing-masing akan menjadi 0,1711 dan 0,9504.

Apakah ini disebabkan oleh data pelatihan baru atau model yang dilatih ulang sepenuhnya?

"""
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
Sudahkah Anda mengujinya? Saya tidak melihat alasan untuk itu tidak berhasil.
maz

Apa yang saya lihat sekarang adalah akurasi saya turun sekitar 10 persen setelah memuat model (hanya di epoch pertama). Jika pemuatan ulang berhasil, ini tentu saja disebabkan oleh data pelatihan baru. Tetapi saya hanya ingin memastikan bahwa memang benar demikian.
Wilmar van Ommeren

7
Apakah Anda menyimpan model Anda secara langsung dengan model.save atau apakah Anda menggunakan model checkpoint ( keras.io/callbacks/#example-model-checkpoints )? Jika Anda menggunakan model.save, apakah ada kemungkinan Anda menyimpan model terbaru (yaitu zaman terakhir) daripada yang terbaik (kesalahan terendah)? Bisakah Anda memberikan kode sebenarnya?
maz

Saya menyimpan model terbaru saya, bukan yang terbaik (sampai saat ini saya tidak tahu itu mungkin). Saya akan menyiapkan beberapa kode
Wilmar van Ommeren

3
Jadi tidak bisakah Anda memuatnya kembali dan melanjutkan pelatihan dengan data kereta yang sama? Ini akan meyakinkan Anda bahwa memuat ulang baik-baik saja jika hasilnya akan sebanding.
Marcin Możejko

Jawaban:


36

Sebenarnya - model.savemenyimpan semua informasi yang diperlukan untuk memulai kembali pelatihan dalam kasus Anda. Satu-satunya hal yang dapat dirusak oleh model reload adalah status pengoptimal Anda. Untuk memeriksanya - coba savemuat ulang model dan latih pada data pelatihan.


1
@Marcin: bila menggunakan keras save(), apakah itu menyimpan hasil terbaik (kerugian terendah) model atau hasil terakhir (update terakhir) model? terima kasih
Lion Lai

5
pembaharuan Terakhir. Callback model checkpoint adalah untuk menyimpan yang terbaik.
Holi

2
@Khaj Apakah Anda mengacu ini keras.io/callbacks/#modelcheckpoint ? Tampaknya secara default, ini menyimpan pembaruan terakhir (bukan yang terbaik); yang terbaik hanya disimpan jika save_best_only=Truedisetel secara eksplisit.
flow2k

9

Sebagian besar jawaban di atas mencakup poin-poin penting. Jika Anda menggunakan Tensorflow terbaru ( TF2.1atau lebih tinggi), maka contoh berikut akan membantu Anda. Bagian model kode berasal dari situs web 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)

Harap simpan model dalam format * .tf. Dari pengalaman saya, jika Anda memiliki custom_loss yang ditentukan, format * .h5 tidak akan menyimpan status pengoptimal dan karenanya tidak akan memenuhi tujuan Anda jika Anda ingin melatih ulang model dari tempat kami tinggalkan.

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

Pendekatan ini akan memulai kembali pelatihan yang kita tinggalkan sebelum menyimpan model. Seperti yang disebutkan oleh orang lain, jika Anda ingin menyimpan bobot model terbaik atau Anda ingin menyimpan bobot model setiap zaman Anda perlu menggunakan keras callback function (ModelCheckpoint) dengan pilihan seperti save_weights_only=True, save_freq='epoch', dan save_best_only.

Untuk lebih jelasnya, silakan cek di sini dan contoh lain di sini .


1
bagus, ini terlihat sangat menjanjikan - terima kasih atas infonya. dalam contoh ini, menurut saya Anda seolah-olah sedang melatih ulang model pada data yang sama yang digunakan untuk pelatihan. jika demikian, saya akan berpikir bahwa pendekatan yang benar akan memuat subset baru dari data pelatihan untuk dilatih kembali (untuk mencerminkan informasi baru yang diperkenalkan ke proses)?
bibzzzz

1
@bibzzzz Setuju dengan Anda. Komentar yang sangat bagus. Saya ingin mendemonstrasikan pelatihan ulang pada data yang sama untuk meningkatkan kinerja. Intinya jelas menunjukkan peningkatan kinerja saat dihentikan sebelum menyimpan model. Saya sepenuhnya setuju dengan Anda untuk melatih kembali data yang berbeda dan akan mencobanya nanti. Terima kasih!
Vishnuvardhan Janapati

1
luar biasa - Anda telah menunjukkan ini dengan sangat baik, terima kasih.
bibzzzz

8

Masalahnya mungkin Anda menggunakan pengoptimal yang berbeda - atau argumen yang berbeda untuk pengoptimal Anda. Saya baru saja mengalami masalah yang sama dengan model yang telah dilatih sebelumnya, menggunakan

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

untuk model yang dilatih sebelumnya, di mana kecepatan pembelajaran asli dimulai pada 0,0003 dan selama pra-pelatihan dikurangi menjadi tingkat pembelajaran_minimal, yaitu 0,000003

Saya baru saja menyalin baris itu ke skrip yang menggunakan model yang sudah dilatih sebelumnya dan mendapatkan akurasi yang sangat buruk. Sampai saya perhatikan bahwa kecepatan pembelajaran terakhir dari model yang dilatih sebelumnya adalah kecepatan pembelajaran minimum, yaitu 0,000003. Dan jika saya mulai dengan kecepatan pemelajaran tersebut, saya mendapatkan akurasi yang persis sama di awal sebagai keluaran dari model yang dilatih sebelumnya - yang masuk akal, karena memulai dengan kecepatan pemelajaran yang 100 kali lebih besar dari kecepatan pemelajaran terakhir yang digunakan dalam pra-pelatihan model akan menghasilkan GD yang sangat besar dan karenanya dalam akurasi yang sangat menurun.


2

Perhatikan bahwa Keras terkadang memiliki masalah dengan model yang dimuat, seperti di sini . Ini mungkin menjelaskan kasus di mana Anda tidak memulai dengan akurasi terlatih yang sama.


1

Semua di atas membantu, Anda harus melanjutkan dari kecepatan pemelajaran () yang sama dengan LR saat model dan bobot disimpan. Setel langsung di pengoptimal.

Perhatikan bahwa peningkatan dari sana tidak dijamin, karena model tersebut mungkin telah mencapai minimum lokal, yang mungkin bersifat global. Tidak ada gunanya melanjutkan model untuk mencari minimum lokal lainnya, kecuali Anda bermaksud untuk meningkatkan kecepatan pemelajaran dengan cara yang terkontrol dan mendorong model ke tingkat minimum yang mungkin lebih baik tidak jauh dari itu.


Mengapa demikian? Tidak bisakah saya menggunakan LR yang lebih kecil dari sebelumnya?
lte__

Sebenarnya, melanjutkan pelatihan DAPAT membawa Anda ke model yang lebih baik jika Anda menerima lebih banyak data. Jadi ada gunanya melanjutkan model untuk mencari minimum lokal lainnya.
Corey Levinson

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.