Ответ 1
Я использую следующее:
with open('/trainHistoryDict', 'wb') as file_pi:
pickle.dump(history.history, file_pi)
Таким образом, я сохраняю историю как словарь в случае, если я хочу позже нанести ущерб или точность.
В Keras мы можем вернуть вывод model.fit
в историю следующим образом:
history = model.fit(X_train, y_train,
batch_size=batch_size,
nb_epoch=nb_epoch,
validation_data=(X_test, y_test))
Теперь, как сохранить атрибут истории объекта истории в файл для дальнейшего использования (например, нарисовать графики прибыли или убытка по эпохам)?
Я использую следующее:
with open('/trainHistoryDict', 'wb') as file_pi:
pickle.dump(history.history, file_pi)
Таким образом, я сохраняю историю как словарь в случае, если я хочу позже нанести ущерб или точность.
Историю model
можно сохранить в файл следующим образом
import json
hist = model.fit(X_train, y_train, epochs=5, batch_size=batch_size,validation_split=0.1)
with open('file.json', 'w') as f:
json.dump(hist.history, f)
Объекты A history
имеют поле history
- словарь, который содержит различные обучающие метрики, охватываемые каждой учебной эпохой. Так, например, history.history['loss'][99]
вернет потерю вашей модели в 100-ю эпоху обучения. Чтобы сохранить этот pickle
этот словарь или просто сохранить различные списки из этого словаря в соответствующий файл.
Так как history.history
является dict
, вы также можете преобразовать его в объект DataFrame
pandas
, который затем можно сохранить в соответствии с вашими потребностями.
Шаг за шагом:
import pandas as pd
# assuming you stored your model.fit results in a 'history' variable:
history = model.fit(x_train, y_train, epochs=10)
# convert the history.history dict to a pandas DataFrame:
hist_df = pd.DataFrame(history.history)
# save to json:
hist_json_file = 'history.json'
with open(hist_json_file, mode='w') as f:
hist_df.to_json(f)
# or save to csv:
hist_csv_file = 'history.csv'
with open(hist_csv_file, mode='w') as f:
hist_df.to_csv(f)
Я столкнулся с проблемой, заключающейся в том, что значения внутри списка в кератах не являются json-сериализуемыми. Поэтому я написал эти две удобные функции для моего использования.
import json,codecs
import numpy as np
def saveHist(path,history):
new_hist = {}
for key in list(history.history.keys()):
if type(history.history[key]) == np.ndarray:
new_hist[key] = history.history[key].tolist()
elif type(history.history[key]) == list:
if type(history.history[key][0]) == np.float64:
new_hist[key] = list(map(float, history.history[key]))
print(new_hist)
with codecs.open(path, 'w', encoding='utf-8') as file:
json.dump(new_hist, file, separators=(',', ':'), sort_keys=True, indent=4)
def loadHist(path):
with codecs.open(path, 'r', encoding='utf-8') as file:
n = json.loads(file.read())
return n
где saveHist просто нужно получить путь, куда должен быть сохранен файл json, и объект истории, возвращенный из метода keras fit
или fit_generator
.
Я уверен, что есть много способов сделать это, но я возился и придумал свою собственную версию.
Во-первых, пользовательский обратный вызов позволяет захватывать и обновлять историю в конце каждой эпохи. Там у меня также есть обратный вызов, чтобы сохранить модель. Оба из них удобны, потому что, если вы потерпите крах или остановитесь, вы можете продолжить обучение в последнюю завершенную эпоху.
class LossHistory(Callback):
# https://stackoverflow.com/a/53653154/852795
def on_epoch_end(self, epoch, logs = None):
new_history = {}
for k, v in logs.items(): # compile new history from logs
new_history[k] = [v] # convert values into lists
current_history = loadHist(history_filename) # load history from current training
current_history = appendHist(current_history, new_history) # append the logs
saveHist(history_filename, current_history) # save history from current training
model_checkpoint = ModelCheckpoint(model_filename, verbose = 0, period = 1)
history_checkpoint = LossHistory()
callbacks_list = [model_checkpoint, history_checkpoint]
Во-вторых, вот некоторые "вспомогательные" функции, выполняющие именно то, что они говорят. Все они вызываются из обратного вызова LossHistory()
.
# https://stackoverflow.com/a/54092401/852795
import json, codecs
def saveHist(path, history):
with codecs.open(path, 'w', encoding='utf-8') as f:
json.dump(history, f, separators=(',', ':'), sort_keys=True, indent=4)
def loadHist(path):
n = {} # set history to empty
if os.path.exists(path): # reload history if it exists
with codecs.open(path, 'r', encoding='utf-8') as f:
n = json.loads(f.read())
return n
def appendHist(h1, h2):
if h1 == {}:
return h2
else:
dest = {}
for key, value in h1.items():
dest[key] = value + h2[key]
return dest
После этого все, что вам нужно, это установить для history_filename
что-то вроде data/model-history.json
, а также установить для model_filesname
что-то вроде data/model.h5
. Последнее, что нужно сделать, чтобы не испортить свою историю в конце обучения, предполагая, что вы останавливаетесь и начинаете, а также придерживаетесь обратных вызовов, - это сделать следующее:
new_history = model.fit(X_train, y_train,
batch_size = batch_size,
nb_epoch = nb_epoch,
validation_data=(X_test, y_test),
callbacks=callbacks_list)
history = appendHist(history, new_history.history)
Когда бы вы ни захотели, history = loadHist(history_filename)
возвращает вашу историю.
Забавность исходит от json и списков, но я не смог заставить его работать, не преобразовав его путем итерации. Во всяком случае, я знаю, что это работает, потому что я провернул это в течение нескольких дней. Ответ pickled.dump
на fooobar.com/info/504140/... может быть лучше, но я не знаю, что это такое. Если я что-то здесь пропустил или вы не можете заставить его работать, дайте мне знать.