Після того як ви тренуєте модель в Tensorflow:
- Як ви зберігаєте навчену модель?
- Як згодом відновити цю збережену модель?
Після того як ви тренуєте модель в Tensorflow:
Відповіді:
вичерпний і корисний підручник -> https://www.tensorflow.org/guide/saved_model
Детальний посібник Keras для збереження моделей -> https://www.tensorflow.org/guide/keras/save_and_serialize
З документів:
# Create some variables.
v1 = tf.get_variable("v1", shape=[3], initializer = tf.zeros_initializer)
v2 = tf.get_variable("v2", shape=[5], initializer = tf.zeros_initializer)
inc_v1 = v1.assign(v1+1)
dec_v2 = v2.assign(v2-1)
# Add an op to initialize the variables.
init_op = tf.global_variables_initializer()
# Add ops to save and restore all the variables.
saver = tf.train.Saver()
# Later, launch the model, initialize the variables, do some work, and save the
# variables to disk.
with tf.Session() as sess:
sess.run(init_op)
# Do some work with the model.
inc_v1.op.run()
dec_v2.op.run()
# Save the variables to disk.
save_path = saver.save(sess, "/tmp/model.ckpt")
print("Model saved in path: %s" % save_path)
tf.reset_default_graph()
# Create some variables.
v1 = tf.get_variable("v1", shape=[3])
v2 = tf.get_variable("v2", shape=[5])
# Add ops to save and restore all the variables.
saver = tf.train.Saver()
# Later, launch the model, use the saver to restore variables from disk, and
# do some work with the model.
with tf.Session() as sess:
# Restore variables from disk.
saver.restore(sess, "/tmp/model.ckpt")
print("Model restored.")
# Check the values of the variables
print("v1 : %s" % v1.eval())
print("v2 : %s" % v2.eval())
Це все ще бета-версія, тому я б радив поки що. Якщо ви все ще хочете спуститися цією дорогою, ось посібник із tf.saved_model
використання
simple_save
Багато хорошої відповіді, для повноти додамо свої 2 центи: simple_save . Також окремий приклад коду за допомогою tf.data.Dataset
API.
Пітон 3; Tensorflow 1.14
import tensorflow as tf
from tensorflow.saved_model import tag_constants
with tf.Graph().as_default():
with tf.Session() as sess:
...
# Saving
inputs = {
"batch_size_placeholder": batch_size_placeholder,
"features_placeholder": features_placeholder,
"labels_placeholder": labels_placeholder,
}
outputs = {"prediction": model_output}
tf.saved_model.simple_save(
sess, 'path/to/your/location/', inputs, outputs
)
Відновлення:
graph = tf.Graph()
with restored_graph.as_default():
with tf.Session() as sess:
tf.saved_model.loader.load(
sess,
[tag_constants.SERVING],
'path/to/your/location/',
)
batch_size_placeholder = graph.get_tensor_by_name('batch_size_placeholder:0')
features_placeholder = graph.get_tensor_by_name('features_placeholder:0')
labels_placeholder = graph.get_tensor_by_name('labels_placeholder:0')
prediction = restored_graph.get_tensor_by_name('dense/BiasAdd:0')
sess.run(prediction, feed_dict={
batch_size_placeholder: some_value,
features_placeholder: some_other_value,
labels_placeholder: another_value
})
Оригінальна публікація в блозі
Наступний код генерує випадкові дані заради демонстрації.
Dataset
і потім його Iterator
. Ми отримуємо згенерований ітератором тензор, званийinput_tensor
який входом до нашої моделі.input_tensor
: двонаправленої RNN на основі ГРУ з наступним щільним класифікатором. Бо чому б ні.softmax_cross_entropy_with_logits
, оптимізовані за допомогою Adam
. Після 2 епох (по 2 партії кожна) ми зберігаємо «навчену» модель за допомогою tf.saved_model.simple_save
. Якщо запустити код таким, який є, модель буде збережена у папці, що називається simple/
у вашій поточній робочій директорії.tf.saved_model.loader.load
. Ми захоплюємо заповнювачі та логіти, graph.get_tensor_by_name
а також Iterator
операцію ініціалізації graph.get_operation_by_name
.Код:
import os
import shutil
import numpy as np
import tensorflow as tf
from tensorflow.python.saved_model import tag_constants
def model(graph, input_tensor):
"""Create the model which consists of
a bidirectional rnn (GRU(10)) followed by a dense classifier
Args:
graph (tf.Graph): Tensors' graph
input_tensor (tf.Tensor): Tensor fed as input to the model
Returns:
tf.Tensor: the model's output layer Tensor
"""
cell = tf.nn.rnn_cell.GRUCell(10)
with graph.as_default():
((fw_outputs, bw_outputs), (fw_state, bw_state)) = tf.nn.bidirectional_dynamic_rnn(
cell_fw=cell,
cell_bw=cell,
inputs=input_tensor,
sequence_length=[10] * 32,
dtype=tf.float32,
swap_memory=True,
scope=None)
outputs = tf.concat((fw_outputs, bw_outputs), 2)
mean = tf.reduce_mean(outputs, axis=1)
dense = tf.layers.dense(mean, 5, activation=None)
return dense
def get_opt_op(graph, logits, labels_tensor):
"""Create optimization operation from model's logits and labels
Args:
graph (tf.Graph): Tensors' graph
logits (tf.Tensor): The model's output without activation
labels_tensor (tf.Tensor): Target labels
Returns:
tf.Operation: the operation performing a stem of Adam optimizer
"""
with graph.as_default():
with tf.variable_scope('loss'):
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(
logits=logits, labels=labels_tensor, name='xent'),
name="mean-xent"
)
with tf.variable_scope('optimizer'):
opt_op = tf.train.AdamOptimizer(1e-2).minimize(loss)
return opt_op
if __name__ == '__main__':
# Set random seed for reproducibility
# and create synthetic data
np.random.seed(0)
features = np.random.randn(64, 10, 30)
labels = np.eye(5)[np.random.randint(0, 5, (64,))]
graph1 = tf.Graph()
with graph1.as_default():
# Random seed for reproducibility
tf.set_random_seed(0)
# Placeholders
batch_size_ph = tf.placeholder(tf.int64, name='batch_size_ph')
features_data_ph = tf.placeholder(tf.float32, [None, None, 30], 'features_data_ph')
labels_data_ph = tf.placeholder(tf.int32, [None, 5], 'labels_data_ph')
# Dataset
dataset = tf.data.Dataset.from_tensor_slices((features_data_ph, labels_data_ph))
dataset = dataset.batch(batch_size_ph)
iterator = tf.data.Iterator.from_structure(dataset.output_types, dataset.output_shapes)
dataset_init_op = iterator.make_initializer(dataset, name='dataset_init')
input_tensor, labels_tensor = iterator.get_next()
# Model
logits = model(graph1, input_tensor)
# Optimization
opt_op = get_opt_op(graph1, logits, labels_tensor)
with tf.Session(graph=graph1) as sess:
# Initialize variables
tf.global_variables_initializer().run(session=sess)
for epoch in range(3):
batch = 0
# Initialize dataset (could feed epochs in Dataset.repeat(epochs))
sess.run(
dataset_init_op,
feed_dict={
features_data_ph: features,
labels_data_ph: labels,
batch_size_ph: 32
})
values = []
while True:
try:
if epoch < 2:
# Training
_, value = sess.run([opt_op, logits])
print('Epoch {}, batch {} | Sample value: {}'.format(epoch, batch, value[0]))
batch += 1
else:
# Final inference
values.append(sess.run(logits))
print('Epoch {}, batch {} | Final inference | Sample value: {}'.format(epoch, batch, values[-1][0]))
batch += 1
except tf.errors.OutOfRangeError:
break
# Save model state
print('\nSaving...')
cwd = os.getcwd()
path = os.path.join(cwd, 'simple')
shutil.rmtree(path, ignore_errors=True)
inputs_dict = {
"batch_size_ph": batch_size_ph,
"features_data_ph": features_data_ph,
"labels_data_ph": labels_data_ph
}
outputs_dict = {
"logits": logits
}
tf.saved_model.simple_save(
sess, path, inputs_dict, outputs_dict
)
print('Ok')
# Restoring
graph2 = tf.Graph()
with graph2.as_default():
with tf.Session(graph=graph2) as sess:
# Restore saved values
print('\nRestoring...')
tf.saved_model.loader.load(
sess,
[tag_constants.SERVING],
path
)
print('Ok')
# Get restored placeholders
labels_data_ph = graph2.get_tensor_by_name('labels_data_ph:0')
features_data_ph = graph2.get_tensor_by_name('features_data_ph:0')
batch_size_ph = graph2.get_tensor_by_name('batch_size_ph:0')
# Get restored model output
restored_logits = graph2.get_tensor_by_name('dense/BiasAdd:0')
# Get dataset initializing operation
dataset_init_op = graph2.get_operation_by_name('dataset_init')
# Initialize restored dataset
sess.run(
dataset_init_op,
feed_dict={
features_data_ph: features,
labels_data_ph: labels,
batch_size_ph: 32
}
)
# Compute inference for both batches in dataset
restored_values = []
for i in range(2):
restored_values.append(sess.run(restored_logits))
print('Restored values: ', restored_values[i][0])
# Check if original inference and restored inference are equal
valid = all((v == rv).all() for v, rv in zip(values, restored_values))
print('\nInferences match: ', valid)
Це надрукує:
$ python3 save_and_restore.py
Epoch 0, batch 0 | Sample value: [-0.13851789 -0.3087595 0.12804556 0.20013677 -0.08229901]
Epoch 0, batch 1 | Sample value: [-0.00555491 -0.04339041 -0.05111827 -0.2480045 -0.00107776]
Epoch 1, batch 0 | Sample value: [-0.19321944 -0.2104792 -0.00602257 0.07465433 0.11674127]
Epoch 1, batch 1 | Sample value: [-0.05275984 0.05981954 -0.15913513 -0.3244143 0.10673307]
Epoch 2, batch 0 | Final inference | Sample value: [-0.26331693 -0.13013336 -0.12553 -0.04276478 0.2933622 ]
Epoch 2, batch 1 | Final inference | Sample value: [-0.07730117 0.11119192 -0.20817074 -0.35660955 0.16990358]
Saving...
INFO:tensorflow:Assets added to graph.
INFO:tensorflow:No assets to write.
INFO:tensorflow:SavedModel written to: b'/some/path/simple/saved_model.pb'
Ok
Restoring...
INFO:tensorflow:Restoring parameters from b'/some/path/simple/variables/variables'
Ok
Restored values: [-0.26331693 -0.13013336 -0.12553 -0.04276478 0.2933622 ]
Restored values: [-0.07730117 0.11119192 -0.20817074 -0.35660955 0.16990358]
Inferences match: True
tf.contrib.layers
?
[n.name for n in graph2.as_graph_def().node]
. Як зазначається в документації, просте збереження спрямоване на спрощення взаємодії з подачею тензорфлоу, це суть аргументів; інші змінні все ж таки відновлюються, інакше висновок не відбудеться. Просто захопіть ваші змінні цікавлять, як я це робив у прикладі. Ознайомтеся з документацією
global_step
аргументу, якщо ви перестанете, то спробуйте знову почати тренуватись, він подумає, що ви один крок. Це як мінімум накрутить ваші візуалізації на
Я вдосконалюю свою відповідь, щоб додати більше деталей для збереження та відновлення моделей.
У (і після) версія Tensorflow 0,11 :
Збережіть модель:
import tensorflow as tf
#Prepare to feed input, i.e. feed_dict and placeholders
w1 = tf.placeholder("float", name="w1")
w2 = tf.placeholder("float", name="w2")
b1= tf.Variable(2.0,name="bias")
feed_dict ={w1:4,w2:8}
#Define a test operation that we will restore
w3 = tf.add(w1,w2)
w4 = tf.multiply(w3,b1,name="op_to_restore")
sess = tf.Session()
sess.run(tf.global_variables_initializer())
#Create a saver object which will save all the variables
saver = tf.train.Saver()
#Run the operation by feeding input
print sess.run(w4,feed_dict)
#Prints 24 which is sum of (w1+w2)*b1
#Now, save the graph
saver.save(sess, 'my_test_model',global_step=1000)
Відновіть модель:
import tensorflow as tf
sess=tf.Session()
#First let's load meta graph and restore weights
saver = tf.train.import_meta_graph('my_test_model-1000.meta')
saver.restore(sess,tf.train.latest_checkpoint('./'))
# Access saved Variables directly
print(sess.run('bias:0'))
# This will print 2, which is the value of bias that we saved
# Now, let's access and create placeholders variables and
# create feed-dict to feed new data
graph = tf.get_default_graph()
w1 = graph.get_tensor_by_name("w1:0")
w2 = graph.get_tensor_by_name("w2:0")
feed_dict ={w1:13.0,w2:17.0}
#Now, access the op that you want to run.
op_to_restore = graph.get_tensor_by_name("op_to_restore:0")
print sess.run(op_to_restore,feed_dict)
#This will print 60 which is calculated
Цей та деякі більш досконалі випадки використання тут були дуже добре пояснені.
Швидкий повний посібник із збереження та відновлення моделей Tensorflow
:0
їх до імен?
У (і після) TensorFlow версії 0.11.0RC1 ви можете зберегти та відновити свою модель безпосередньо, зателефонувавши tf.train.export_meta_graph
та tf.train.import_meta_graph
відповідно до https://www.tensorflow.org/programmers_guide/meta_graph .
w1 = tf.Variable(tf.truncated_normal(shape=[10]), name='w1')
w2 = tf.Variable(tf.truncated_normal(shape=[20]), name='w2')
tf.add_to_collection('vars', w1)
tf.add_to_collection('vars', w2)
saver = tf.train.Saver()
sess = tf.Session()
sess.run(tf.global_variables_initializer())
saver.save(sess, 'my-model')
# `save` method will call `export_meta_graph` implicitly.
# you will get saved graph files:my-model.meta
sess = tf.Session()
new_saver = tf.train.import_meta_graph('my-model.meta')
new_saver.restore(sess, tf.train.latest_checkpoint('./'))
all_vars = tf.get_collection('vars')
for v in all_vars:
v_ = sess.run(v)
print(v_)
<built-in function TF_Run> returned a result with an error set
tf.get_variable_scope().reuse_variables()
наступні var = tf.get_variable("varname")
. Це дає мені помилку: "ValueError: Ім'я змінної не існує або не було створено за допомогою tf.get_variable ()." Чому? Чи це не можливо?
Для версії TensorFlow <0,11.0RC1:
Збережені контрольні точки містять значення для Variable
s у вашій моделі, а не модель / графік, а це означає, що графік повинен бути однаковим при відновленні контрольної точки.
Ось приклад для лінійної регресії, де є навчальний цикл, який зберігає змінні контрольні точки, і розділ оцінювання, який буде відновити змінні, збережені в попередньому запуску, та обчислити прогнози. Звичайно, ви також можете відновити змінні та продовжити навчання, якщо хочете.
x = tf.placeholder(tf.float32)
y = tf.placeholder(tf.float32)
w = tf.Variable(tf.zeros([1, 1], dtype=tf.float32))
b = tf.Variable(tf.ones([1, 1], dtype=tf.float32))
y_hat = tf.add(b, tf.matmul(x, w))
...more setup for optimization and what not...
saver = tf.train.Saver() # defaults to saving all variables - in this case w and b
with tf.Session() as sess:
sess.run(tf.initialize_all_variables())
if FLAGS.train:
for i in xrange(FLAGS.training_steps):
...training loop...
if (i + 1) % FLAGS.checkpoint_steps == 0:
saver.save(sess, FLAGS.checkpoint_dir + 'model.ckpt',
global_step=i+1)
else:
# Here's where you're restoring the variables w and b.
# Note that the graph is exactly as it was when the variables were
# saved in a prior training run.
ckpt = tf.train.get_checkpoint_state(FLAGS.checkpoint_dir)
if ckpt and ckpt.model_checkpoint_path:
saver.restore(sess, ckpt.model_checkpoint_path)
else:
...no checkpoint found...
# Now you can run the model to get predictions
batch_x = ...load some data...
predictions = sess.run(y_hat, feed_dict={x: batch_x})
Ось документи для Variable
s, які охоплюють збереження та відновлення. Ось і документи для Saver
.
batch_x
потрібно бути? Бінарний? Масивний масив?
undefined
. Чи можете ви сказати мені, що є FLAGS для цього коду. @RyanSepassi
Моє середовище: Python 3.6, Tensorflow 1.3.0
Хоча рішень було багато, більшість з них базується на tf.train.Saver
. Коли ми завантажуємо .ckpt
врятовані Saver
, ми повинні або переглянути мережу tensorflow або використовувати будь - то дивне і з працею згадав ім'я, наприклад 'placehold_0:0'
, 'dense/Adam/Weight:0'
. Тут я рекомендую використовувати tf.saved_model
один найпростіший приклад, наведений нижче, ви можете дізнатися більше з обслуговування моделі TensorFlow :
Збережіть модель:
import tensorflow as tf
# define the tensorflow network and do some trains
x = tf.placeholder("float", name="x")
w = tf.Variable(2.0, name="w")
b = tf.Variable(0.0, name="bias")
h = tf.multiply(x, w)
y = tf.add(h, b, name="y")
sess = tf.Session()
sess.run(tf.global_variables_initializer())
# save the model
export_path = './savedmodel'
builder = tf.saved_model.builder.SavedModelBuilder(export_path)
tensor_info_x = tf.saved_model.utils.build_tensor_info(x)
tensor_info_y = tf.saved_model.utils.build_tensor_info(y)
prediction_signature = (
tf.saved_model.signature_def_utils.build_signature_def(
inputs={'x_input': tensor_info_x},
outputs={'y_output': tensor_info_y},
method_name=tf.saved_model.signature_constants.PREDICT_METHOD_NAME))
builder.add_meta_graph_and_variables(
sess, [tf.saved_model.tag_constants.SERVING],
signature_def_map={
tf.saved_model.signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY:
prediction_signature
},
)
builder.save()
Завантажте модель:
import tensorflow as tf
sess=tf.Session()
signature_key = tf.saved_model.signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY
input_key = 'x_input'
output_key = 'y_output'
export_path = './savedmodel'
meta_graph_def = tf.saved_model.loader.load(
sess,
[tf.saved_model.tag_constants.SERVING],
export_path)
signature = meta_graph_def.signature_def
x_tensor_name = signature[signature_key].inputs[input_key].name
y_tensor_name = signature[signature_key].outputs[output_key].name
x = sess.graph.get_tensor_by_name(x_tensor_name)
y = sess.graph.get_tensor_by_name(y_tensor_name)
y_out = sess.run(y, {x: 3.0})
Моделі є дві частини, визначення моделі, збережене Supervisor
як graph.pbtxt
у каталозі моделі, і числові значення тензорів, збережені у файли контрольних точок model.ckpt-1003418
.
Визначення моделі можна відновити за допомогою tf.import_graph_def
, а ваги відновити за допомогою Saver
.
Однак Saver
використовується спеціальний перелік змінних, що містить колекцію, що додається до моделі Graph, і ця колекція не ініціалізується за допомогою import_graph_def, тому ви не можете використовувати їх разом разом (це є на нашому дорожньому карті для виправлення). Поки що ви повинні використовувати підхід Раяна Сепассі - вручну побудувати графік з однаковими назвами вузлів і використовувати Saver
для завантаження ваг у нього.
(Або ви можете зламати його, використовуючи import_graph_def
, створюючи змінні вручну та використовуючи tf.add_to_collection(tf.GraphKeys.VARIABLES, variable)
для кожної змінної, а потім використовуючи Saver
)
Ви також можете скористатися цим простішим способом.
W1 = tf.Variable(tf.truncated_normal([6, 6, 1, K], stddev=0.1), name="W1")
B1 = tf.Variable(tf.constant(0.1, tf.float32, [K]), name="B1")
Similarly, W2, B2, W3, .....
Saver
та збережіть їїmodel_saver = tf.train.Saver()
# Train the model and save it in the end
model_saver.save(session, "saved_models/CNN_New.ckpt")
with tf.Session(graph=graph_cnn) as session:
model_saver.restore(session, "saved_models/CNN_New.ckpt")
print("Model restored.")
print('Initialized')
W1 = session.run(W1)
print(W1)
Під час роботи в різних екземплярах python використовуйте
with tf.Session() as sess:
# Restore latest checkpoint
saver.restore(sess, tf.train.latest_checkpoint('saved_model/.'))
# Initalize the variables
sess.run(tf.global_variables_initializer())
# Get default graph (supply your custom graph if you have one)
graph = tf.get_default_graph()
# It will give tensor object
W1 = graph.get_tensor_by_name('W1:0')
# To get the value (numpy array)
W1_value = session.run(W1)
У більшості випадків збереження та відновлення з диска за допомогою a tf.train.Saver
- це найкращий варіант:
... # build your model
saver = tf.train.Saver()
with tf.Session() as sess:
... # train the model
saver.save(sess, "/tmp/my_great_model")
with tf.Session() as sess:
saver.restore(sess, "/tmp/my_great_model")
... # use the model
Ви також можете зберегти / відновити структуру самої графіки ( детальну інформацію див. У документації щодо MetaGraph ). За замовчуванням Saver
структура графа зберігає у .meta
файл. Ви можете зателефонувати, import_meta_graph()
щоб відновити його. Він відновлює структуру графіка і повертає Saver
те, що ви можете використовувати для відновлення стану моделі:
saver = tf.train.import_meta_graph("/tmp/my_great_model.meta")
with tf.Session() as sess:
saver.restore(sess, "/tmp/my_great_model")
... # use the model
Однак бувають випадки, коли потрібно щось набагато швидше. Наприклад, якщо ви здійснюєте ранню зупинку, ви хочете зберегти контрольні точки кожного разу, коли модель покращується під час тренувань (як це вимірюється на наборі перевірки), то, якщо деякий час не буде прогресу, ви хочете повернутися до найкращої моделі. Якщо ви зберігаєте модель на диску кожен раз, коли вона вдосконалюється, це надзвичайно сповільнить тренування. Хитрість полягає в тому, щоб зберегти змінні стани в пам'яті , а потім просто відновити їх згодом:
... # build your model
# get a handle on the graph nodes we need to save/restore the model
graph = tf.get_default_graph()
gvars = graph.get_collection(tf.GraphKeys.GLOBAL_VARIABLES)
assign_ops = [graph.get_operation_by_name(v.op.name + "/Assign") for v in gvars]
init_values = [assign_op.inputs[1] for assign_op in assign_ops]
with tf.Session() as sess:
... # train the model
# when needed, save the model state to memory
gvars_state = sess.run(gvars)
# when needed, restore the model state
feed_dict = {init_value: val
for init_value, val in zip(init_values, gvars_state)}
sess.run(assign_ops, feed_dict=feed_dict)
Швидке пояснення: коли ви створюєте змінну X
, TensorFlow автоматично створює операцію призначення, X/Assign
щоб встановити початкове значення змінної. Замість того, щоб створювати заповнювачі та додаткові опції присвоєння (що просто зробить графік безладним), ми просто використовуємо ці наявні операційні можливості призначення. Перший вхід кожного оператора призначення - це посилання на змінну, яку слід ініціалізувати, а другий вхід ( assign_op.inputs[1]
) - початкове значення. Отже, щоб встановити будь-яке значення, яке ми хочемо (замість початкового значення), нам потрібно використовувати a feed_dict
і замінити початкове значення. Так, TensorFlow дозволяє подавати значення для будь-якої опції, а не лише для заповнювачів, тому це прекрасно працює.
Як сказав Ярослав, ви можете зламати відновлення з graph_def та контрольної точки, імпортуючи графік, створивши змінні вручну та використовуючи Saver.
Я реалізував це для особистого використання, тому хоч би поділився кодом тут.
Посилання: https://gist.github.com/nikitakit/6ef3b72be67b86cb7868
(Це, звичайно, хак, і немає гарантії, що збережені таким чином моделі залишаться читабельними у майбутніх версіях TensorFlow.)
Якщо це внутрішня збережена модель, ви просто вкажете реставратор для всіх змінних як
restorer = tf.train.Saver(tf.all_variables())
і використовувати його для відновлення змінних у поточному сеансі:
restorer.restore(self._sess, model_file)
Для зовнішньої моделі потрібно вказати відображення від назв змінних до імен змінних. Ви можете переглянути імена змінних моделей за допомогою команди
python /path/to/tensorflow/tensorflow/python/tools/inspect_checkpoint.py --file_name=/path/to/pretrained_model/model.ckpt
Сценарій inspect_checkpoint.py можна знайти в папці './tensorflow/python/tools' джерела Tensorflow.
Щоб визначити відображення, ви можете використовувати мій Tensorflow-Worklab , який містить набір класів та сценаріїв для підготовки та перевчання різних моделей. Він включає приклад перекваліфікації моделей ResNet, розміщених тут
all_variables()
тепер застаріло
Ось моє просте рішення для двох основних випадків, що відрізняються від того, чи потрібно ви завантажувати графік з файлу чи будувати його під час виконання.
Ця відповідь стосується Tensorflow 0,12+ (включаючи 1.0).
graph = ... # build the graph
saver = tf.train.Saver() # create the saver after the graph
with ... as sess: # your session object
saver.save(sess, 'my-model')
graph = ... # build the graph
saver = tf.train.Saver() # create the saver after the graph
with ... as sess: # your session object
saver.restore(sess, tf.train.latest_checkpoint('./'))
# now you can use the graph, continue training or whatever
Використовуючи цю техніку, переконайтеся, що всі ваші шари / змінні мають чітко встановлені унікальні імена. Інакше Tensorflow зробить самі імена унікальними, і вони таким чином будуть відрізнятися від імен, що зберігаються у файлі. Це не проблема в попередній техніці, оскільки імена "керуються" однаково при завантаженні та збереженні.
graph = ... # build the graph
for op in [ ... ]: # operators you want to use after restoring the model
tf.add_to_collection('ops_to_restore', op)
saver = tf.train.Saver() # create the saver after the graph
with ... as sess: # your session object
saver.save(sess, 'my-model')
with ... as sess: # your session object
saver = tf.train.import_meta_graph('my-model.meta')
saver.restore(sess, tf.train.latest_checkpoint('./'))
ops = tf.get_collection('ops_to_restore') # here are your operators in the same order in which you saved them to the collection
global_step
змінна та ковзні середні показники нормалізації партії - це невідповідні змінні, але обидва, безумовно, варто заощадити. Також слід чіткіше відрізняти побудову графіка від запуску сеансу, наприклад Saver(...).save()
, створювати нові вузли щоразу, коли ви запускаєте його. Напевно, не те, що ти хочеш. І є ще ...: /
Ви також можете ознайомитись із прикладами в TensorFlow / skflow , який пропонує save
та restore
методи, які допоможуть вам легко керувати своїми моделями. У ньому є параметри, за допомогою яких ви також можете контролювати, як часто ви хочете створювати резервну копію вашої моделі.
Якщо ви використовуєте tf.train.MonitoredTrainingSession як сеанс за замовчуванням, вам не потрібно додавати додатковий код для збереження / відновлення речей. Просто передайте ім'я dir контрольної точки конструктору MonitoredTrainingSession, він буде використовувати гачки сеансу для їх обробки.
Усі відповіді тут чудові, але я хочу додати дві речі.
По-перше, для детальнішої відповіді на @ user7505159 відповідь "./" може бути важливим, щоб додати до початку імені файлу, який ви відновлюєте.
Наприклад, ви можете зберегти графік без "./" у назві файла так:
# Some graph defined up here with specific names
saver = tf.train.Saver()
save_file = 'model.ckpt'
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
saver.save(sess, save_file)
Але щоб відновити графік, можливо, вам потрібно буде додати "./" до імені файла:
# Same graph defined up here
saver = tf.train.Saver()
save_file = './' + 'model.ckpt' # String addition used for emphasis
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
saver.restore(sess, save_file)
Вам не завжди знадобиться "./", але це може спричинити проблеми залежно від вашого оточення та версії TensorFlow.
Також хочеться зазначити, що sess.run(tf.global_variables_initializer())
може бути важливим перед відновленням сесії.
Якщо ви отримуєте помилку щодо неініціалізованих змінних під час спроби відновити збережений сеанс, обов’язково включіть його sess.run(tf.global_variables_initializer())
до saver.restore(sess, save_file)
рядка. Це може врятувати вам головний біль.
Згідно з новою версією Tensorflow, tf.train.Checkpoint
кращий спосіб збереження та відновлення моделі:
Checkpoint.save
іCheckpoint.restore
записувати та читати контрольно-пропускні пункти на основі об'єктів, на відміну від tf.train.Saver, який записує та зчитує контрольні точки на основі varia.name. Контрольна точка на основі об'єктів зберігає графік залежностей між об'єктами Python (Шари, Оптимізатори, Змінні тощо) з названими ребрами, і цей графік використовується для узгодження змінних при відновленні контрольної точки. Це може бути більш стійким до змін у програмі Python та допомагає підтримувати відновлення при створенні змінних при виконанні завзято. Віддаю перевагуtf.train.Checkpoint
більшtf.train.Saver
для нового коду .
Ось приклад:
import tensorflow as tf
import os
tf.enable_eager_execution()
checkpoint_directory = "/tmp/training_checkpoints"
checkpoint_prefix = os.path.join(checkpoint_directory, "ckpt")
checkpoint = tf.train.Checkpoint(optimizer=optimizer, model=model)
status = checkpoint.restore(tf.train.latest_checkpoint(checkpoint_directory))
for _ in range(num_training_steps):
optimizer.minimize( ... ) # Variables will be restored on creation.
status.assert_consumed() # Optional sanity checks.
checkpoint.save(file_prefix=checkpoint_prefix)
Для tensorflow 2.0 це так само просто
# Save the model model.save('path_to_my_model.h5')
Відновити:
new_model = tensorflow.keras.models.load_model('path_to_my_model.h5')
TF2.0
Я бачу чудові відповіді щодо збереження моделей за допомогою TF1.x. Я хочу надати ще декілька покажчиків на збереження tensorflow.keras
моделей, що трохи складніше, оскільки існує багато способів збереження моделі.
Тут я наводимо приклад збереження tensorflow.keras
моделі в model_path
папці під поточним каталогом. Це добре працює з останнім тензорфолом (TF2.0). Я оновлю цей опис, якщо найближчим часом будуть якісь зміни.
import tensorflow as tf
from tensorflow import keras
mnist = tf.keras.datasets.mnist
#import data
(x_train, y_train),(x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0
# create a model
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)
])
# compile the model
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=1)
loss, acc = model.evaluate(x_test, y_test,verbose=1)
print("Original model, accuracy: {:5.2f}%".format(100*acc))
# Save entire model to a HDF5 file
model.save('./model_path/my_model.h5')
# Recreate the exact same model, including weights and optimizer.
new_model = keras.models.load_model('./model_path/my_model.h5')
loss, acc = new_model.evaluate(x_test, y_test)
print("Restored model, accuracy: {:5.2f}%".format(100*acc))
Якщо ви зацікавлені в збереженні лише ваги моделі, а потім завантажте ваги, щоб відновити модель, тоді
model.fit(x_train, y_train, epochs=5)
loss, acc = model.evaluate(x_test, y_test,verbose=1)
print("Original model, accuracy: {:5.2f}%".format(100*acc))
# Save the weights
model.save_weights('./checkpoints/my_checkpoint')
# Restore the weights
model = create_model()
model.load_weights('./checkpoints/my_checkpoint')
loss,acc = model.evaluate(x_test, y_test)
print("Restored model, accuracy: {:5.2f}%".format(100*acc))
# include the epoch in the file name. (uses `str.format`)
checkpoint_path = "training_2/cp-{epoch:04d}.ckpt"
checkpoint_dir = os.path.dirname(checkpoint_path)
cp_callback = tf.keras.callbacks.ModelCheckpoint(
checkpoint_path, verbose=1, save_weights_only=True,
# Save weights, every 5-epochs.
period=5)
model = create_model()
model.save_weights(checkpoint_path.format(epoch=0))
model.fit(train_images, train_labels,
epochs = 50, callbacks = [cp_callback],
validation_data = (test_images,test_labels),
verbose=0)
latest = tf.train.latest_checkpoint(checkpoint_dir)
new_model = create_model()
new_model.load_weights(latest)
loss, acc = new_model.evaluate(test_images, test_labels)
print("Restored model, accuracy: {:5.2f}%".format(100*acc))
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
# Custom Loss1 (for example)
@tf.function()
def customLoss1(yTrue,yPred):
return tf.reduce_mean(yTrue-yPred)
# Custom Loss2 (for example)
@tf.function()
def customLoss2(yTrue, yPred):
return tf.reduce_mean(tf.square(tf.subtract(yTrue,yPred)))
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', customLoss1, customLoss2])
return model
# Create a basic model instance
model=create_model()
# Fit and evaluate model
model.fit(x_train, y_train, epochs=1)
loss, acc,loss1, loss2 = model.evaluate(x_test, y_test,verbose=1)
print("Original model, accuracy: {:5.2f}%".format(100*acc))
model.save("./model.h5")
new_model=tf.keras.models.load_model("./model.h5",custom_objects={'customLoss1':customLoss1,'customLoss2':customLoss2})
Коли у нас є власні опції, як у наступному випадку ( tf.tile
), нам потрібно створити функцію та обернути шаром лямбда. В іншому випадку модель не вдається зберегти.
import numpy as np
import tensorflow as tf
from tensorflow.keras.layers import Input, Lambda
from tensorflow.keras import Model
def my_fun(a):
out = tf.tile(a, (1, tf.shape(a)[0]))
return out
a = Input(shape=(10,))
#out = tf.tile(a, (1, tf.shape(a)[0]))
out = Lambda(lambda x : my_fun(x))(a)
model = Model(a, out)
x = np.zeros((50,10), dtype=np.float32)
print(model(x).numpy())
model.save('my_model.h5')
#load the model
new_model=tf.keras.models.load_model("my_model.h5")
Я думаю, я висвітлив декілька з багатьох способів збереження моделі tf.keras. Однак існує багато інших способів. Будь ласка, прокоментуйте нижче, якщо ви бачите, що ваш випадок використання не висвітлюється вище. Дякую!
Ви можете зберегти змінні в мережі за допомогою
saver = tf.train.Saver()
saver.save(sess, 'path of save/fileName.ckpt')
Щоб відновити мережу для повторного використання пізніше або в іншому сценарії, використовуйте:
saver = tf.train.Saver()
saver.restore(sess, tf.train.latest_checkpoint('path of save/')
sess.run(....)
Важливі моменти:
sess
повинні бути однаковими між першими та пізнішими прогонами (когерентна структура). saver.restore
потрібен шлях папки збережених файлів, а не окремий шлях до файлу. Де б ви не хотіли зберегти модель,
self.saver = tf.train.Saver()
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
...
self.saver.save(sess, filename)
Переконайтесь, що всі ваші tf.Variable
імена мають, тому що ви, можливо, захочете їх відновити пізніше, використовуючи їх імена. І де ви хочете передбачити,
saver = tf.train.import_meta_graph(filename)
name = 'name given when you saved the file'
with tf.Session() as sess:
saver.restore(sess, name)
print(sess.run('W1:0')) #example to retrieve by variable name
Переконайтеся, що заставка працює у відповідному сеансі. Пам’ятайте, що якщо ви використовуєте, використовується tf.train.latest_checkpoint('./')
лише остання контрольна точка.
Для tensorflow-2.0
це дуже просто.
import tensorflow as tf
model.save("model_name")
model = tf.keras.models.load_model('model_name')
Після відповіді @Vishnuvardhan Janapati, ось ще один спосіб збереження та перезавантаження моделі за допомогою спеціального шару / метрики / втрати під TensorFlow 2.0.0
import tensorflow as tf
from tensorflow.keras.layers import Layer
from tensorflow.keras.utils.generic_utils import get_custom_objects
# custom loss (for example)
def custom_loss(y_true,y_pred):
return tf.reduce_mean(y_true - y_pred)
get_custom_objects().update({'custom_loss': custom_loss})
# custom loss (for example)
class CustomLayer(Layer):
def __init__(self, ...):
...
# define custom layer and all necessary custom operations inside custom layer
get_custom_objects().update({'CustomLayer': CustomLayer})
Таким чином , після того , як ви виконали ці коди, і зберіг модель з tf.keras.models.save_model
або model.save
або ModelCheckpoint
зворотним викликом, ви можете повторно завантажити модель без точних об'єктів, так просто , як
new_model = tf.keras.models.load_model("./model.h5"})
У новій версії tensorflow 2.0 процес збереження / завантаження моделі набагато простіше. Через впровадження API Keras, API високого рівня для TensorFlow.
Щоб зберегти модель: Перевірте документацію для довідок: https://www.tensorflow.org/versions/r2.0/api_docs/python/tf/keras/models/save_model
tf.keras.models.save_model(model_name, filepath, save_format)
Щоб завантажити модель:
https://www.tensorflow.org/versions/r2.0/api_docs/python/tf/keras/models/load_model
model = tf.keras.models.load_model(filepath)
Ось простий приклад використання Tensorflow 2.0 SavedModel формату (який є рекомендованим форматом, в відповідно до Документами ) для простого MNIST набору даних класифікатора, використовуючи Keras функціонального API не дуже багато фантазії відбувається:
# Imports
import tensorflow as tf
from tensorflow.keras.layers import Input, Dense, Flatten
from tensorflow.keras.models import Model
import matplotlib.pyplot as plt
# Load data
mnist = tf.keras.datasets.mnist # 28 x 28
(x_train,y_train), (x_test, y_test) = mnist.load_data()
# Normalize pixels [0,255] -> [0,1]
x_train = tf.keras.utils.normalize(x_train,axis=1)
x_test = tf.keras.utils.normalize(x_test,axis=1)
# Create model
input = Input(shape=(28,28), dtype='float64', name='graph_input')
x = Flatten()(input)
x = Dense(128, activation='relu')(x)
x = Dense(128, activation='relu')(x)
output = Dense(10, activation='softmax', name='graph_output', dtype='float64')(x)
model = Model(inputs=input, outputs=output)
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
# Train
model.fit(x_train, y_train, epochs=3)
# Save model in SavedModel format (Tensorflow 2.0)
export_path = 'model'
tf.saved_model.save(model, export_path)
# ... possibly another python program
# Reload model
loaded_model = tf.keras.models.load_model(export_path)
# Get image sample for testing
index = 0
img = x_test[index] # I normalized the image on a previous step
# Predict using the signature definition (Tensorflow 2.0)
predict = loaded_model.signatures["serving_default"]
prediction = predict(tf.constant(img))
# Show results
print(np.argmax(prediction['graph_output'])) # prints the class number
plt.imshow(x_test[index], cmap=plt.cm.binary) # prints the image
Що таке serving_default
?
Це ім'я визначення підпису вибраного вами тега (у цьому випадку serve
вибрано тег за замовчуванням ). Також тут пояснюється, як знайти тег та підписи моделі за допомогою saved_model_cli
.
Відмова від відповідальності
Це лише основний приклад, якщо ви просто хочете його вставити та працювати, але аж ніяк не є повною відповіддю - можливо, я можу це оновити в майбутньому. Я просто хотів навести простий приклад, використовуючи SavedModel
в TF 2.0, тому що я його ще ніде не бачив.
@ Відповідь Тома - приклад SavedModel, але він не працюватиме на Tensorflow 2.0, тому що, на жаль, є деякі неполадки.
@ Відповідь Вишнувардхана Джанапаті говорить TF 2.0, але це не для формату SavedModel.