2017-03-08 833 views
24

我想知道是否可以保存部分訓練的Keras模型,並在加載模型後繼續訓練。加載訓練有素的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)) 
+2

你測試過了嗎?我認爲沒有理由不這樣做。 – maz

+0

我現在看到的是,加載模型後我的精度下降了大約10%(僅在第一個時代)。如果重新加載工作,這當然是由新的訓練數據造成的。但我只想確保事實確實如此。 –

+5

您是使用model.save直接保存模型還是使用模型檢查點(https://keras.io/callbacks/#example-model-checkpoints)?如果您使用的是model.save,您是否有機會保存最新的模型(即最後一個時代)而不是最好的模型(最低錯誤)?你能提供實際的代碼嗎? – maz

回答

9

其實 - model.save保存所有需要重新開始培訓的信息。可以通過重新加載模型破壞的唯一事情就是優化器狀態。檢查 - 嘗試save並重新加載模型並訓練訓練數據。

+0

@Marcin:當使用keras'save()'的時候,它會保存模型的最佳結果(最低損失)還是模型的最後結果(最新更新)?謝謝 –

+0

上次更新。模型檢查點回調是爲了保存最好的回調。 – Khaj

2

請注意,Keras有時會出現加載模型的問題,如here。 這可能會解釋您不是從相同的訓練準確度開始的情況。

-1

問題可能是您使用了不同的優化器 - 或者您的優化器使用了不同的參數。我剛和一個自定義的預訓練的模型同樣的問題,使用

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

爲預訓練的模型,從而使原有的學習率開始於0.0003,並在訓練前就被減少到min_learning率,這是0.000003

我剛剛將該行復制到使用預先訓練好的模型的腳本,並得到了非常糟糕的準確度。直到我注意到預訓練模型的最後學習率是最小學習率,即0.000003。如果我從這個學習速度開始,我可以得到與預訓練模型的輸出完全相同的準確度 - 這是合理的,因爲開始時的學習速率比預訓練中使用的最後學習速率大100倍模型將導致GD的巨大超調,因此精度大大降低。