आपके द्वारा Tensorflow में एक मॉडल को प्रशिक्षित करने के बाद:
- आप प्रशिक्षित मॉडल को कैसे बचाते हैं?
- बाद में आप इस सहेजे गए मॉडल को कैसे पुनर्स्थापित करते हैं?
आपके द्वारा Tensorflow में एक मॉडल को प्रशिक्षित करने के बाद:
जवाबों:
संपूर्ण और उपयोगी ट्यूटोरियल -> https://www.tensorflow.org/guide/saved_model
करस ने मॉडल को बचाने के लिए विस्तृत गाइड -> 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
एपीआई का उपयोग करके एक स्टैंडअलोन कोड उदाहरण भी ।
अजगर 3; टेन्सफ्लो 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
: एक जीआरयू-आधारित द्विदिश आरएनएन जिसके बाद एक घने क्लासिफायरियर है। क्योंकि क्यों नहीं।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
और https://www.tensorflow.org/programmers_guide/meta_graph केtf.train.import_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: Variable varname मौजूद नहीं है, या 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})
यहाँ s के लिए डॉक्स हैं Variable
, जो बचत और पुनर्स्थापन को कवर करते हैं। और यहाँ हैं डॉक्स के लिए Saver
।
batch_x
होना चाहिए? बाइनरी? ऊबड़-खाबड़ सरणी?
undefined
। क्या आप मुझे बता सकते हैं कि इस कोड के लिए FLAGS की कौन सी परिभाषा है। @ रयानसेपसी
मेरा वातावरण: पायथन 3.6, टेंसरफ़्लो 1.3.0
हालांकि कई समाधान हैं, उनमें से ज्यादातर पर आधारित है tf.train.Saver
। जब हम लोड एक .ckpt
ने बचा लिया Saver
है, हम या तो tensorflow नेटवर्क को फिर से परिभाषित या कुछ अजीब और कड़ी मेहनत से याद नाम का उपयोग, जैसे करने के लिए है 'placehold_0:0'
, 'dense/Adam/Weight:0'
। यहां मैं उपयोग करने की सलाह देता हूं tf.saved_model
, नीचे दिए गए एक सबसे सरल उदाहरण से, आप टेनसॉरफ्लो मॉडल की सेवा करने से अधिक सीख सकते हैं :
मॉडल सहेजें:
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
मॉडल निर्देशिका और tensors के संख्यात्मक मूल्यों में, जैसे चौकी फाइलों में बचाया model.ckpt-1003418
।
मॉडल की परिभाषा का उपयोग करके बहाल किया जा सकता है tf.import_graph_def
, और वजन का उपयोग करके बहाल किया जाता है Saver
।
हालाँकि, Saver
मॉडल ग्राफ़ से जुड़ी चर की विशेष संग्रह होल्डिंग सूची का उपयोग करता है, और इस संग्रह को 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)
विभिन्न अजगर उदाहरण में चलाते समय, उपयोग करें
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)
ज्यादातर मामलों में, डिस्क का उपयोग करके सहेजना और पुनर्स्थापित 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
आप स्वयं ग्राफ़ संरचना को सहेज / पुनर्स्थापित भी कर सकते हैं ( विवरण के लिए मेटाग्राफ प्रलेखन देखें)। डिफ़ॉल्ट रूप से, 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]
) इनिशियल वैल्यू है। इसलिए हम जो भी मूल्य निर्धारित करना चाहते हैं (प्रारंभिक मूल्य के बजाय), हमें feed_dict
प्रारंभिक मूल्य को बदलने और बदलने की आवश्यकता है । हां, TensorFlow आपको प्लेसहोल्डर्स के लिए नहीं, बल्कि किसी भी सेशन के लिए वैल्यू फीड करने की सुविधा देता है, इसलिए यह ठीक काम करता है।
जैसा कि यारोस्लाव ने कहा, आप ग्राफ़ को आयात करके और ग्राफ़ को मैन्युअल रूप से चर बनाकर और फिर एक सेवर का उपयोग करके एक ग्राफ_डेफ़ और चेकपॉइंट से बहाल कर सकते हैं।
मैंने इसे अपने निजी उपयोग के लिए लागू किया है, इसलिए मैं हालांकि यहां कोड साझा करूंगा।
लिंक: 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 स्रोत के './tensorflow/python/tools' फ़ोल्डर में पाई जा सकती है।
मैपिंग को निर्दिष्ट करने के लिए, आप मेरे 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 का उपयोग करते हैं, तो आपको चीजों को बचाने / पुनर्स्थापित करने के लिए अतिरिक्त कोड जोड़ने की आवश्यकता नहीं है। मॉनिटर किए गए TrainingSession के कंस्ट्रक्टर के लिए बस एक चेकपॉइंट dir नाम पास करें, यह इनको संभालने के लिए सत्र हुक का उपयोग करेगा।
यहां सभी उत्तर महान हैं, लेकिन मैं दो बातें जोड़ना चाहता हूं।
सबसे पहले, @ 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)
लेकिन ग्राफ़ को पुनर्स्थापित करने के लिए, आपको file_name के लिए "./" को प्रस्तुत करने की आवश्यकता हो सकती है:
# 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 के विपरीत जो ऑब्जेक्ट-आधारित चौकियों को लिखते हैं और पढ़ते हैं, जो चर और नाम आधारित चौकियों को लिखते और पढ़ते हैं। ऑब्जेक्ट-आधारित चेकपॉइंटिंग नामित किनारों के साथ पायथन ऑब्जेक्ट्स (परत, ऑप्टिमाइज़र, वेरिएबल्स, आदि) के बीच निर्भरता के एक ग्राफ को बचाता है, और इस ग्राफ़ का उपयोग चेकपॉइंट को पुनर्स्थापित करते समय चर से मिलान करने के लिए किया जाता है। यह पायथन कार्यक्रम में बदलाव के लिए अधिक मजबूत हो सकता है, और उत्सुकता से निष्पादित करने पर चर के लिए पुनर्स्थापना-निर्माण का समर्थन करने में मदद करता है। पसंद करते हैं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('./')
, तो केवल नवीनतम चेक प्वाइंट का उपयोग किया जाएगा।
टेंसरफ्लो -2.0 के लिए
यह बहुत सरल है।
import tensorflow as tf
model.save("model_name")
model = tf.keras.models.load_model('model_name')
@ विष्णुवर्धन जनपति के उत्तर के बाद, यहाँ एक और तरीका है, कस्टम लेयर / मेट्रिक / लॉस के साथ मॉडल को पुनः लोड करने और पुनः लोड करने का एक और तरीका 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"})
टेनसफ़्लो 2.0 के नए संस्करण में, एक मॉडल को बचाने / लोड करने की प्रक्रिया बहुत आसान है। कार्स एपीआई के कार्यान्वयन के कारण, 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)
यहां एक साधारण MNIST डेटासेट क्लासिफायर के लिए Tensorflow 2.0 SavedModel प्रारूप (जो डॉक्स के अनुसार अनुशंसित प्रारूप है ) का उपयोग करके एक सरल उदाहरण है, बहुत अधिक फैंसी चल रही बिना केरस कार्यात्मक एपीआई का उपयोग कर:
# 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 क्योंकि मैंने एक भी नहीं देखा है, यहां तक कि इस सरल, कहीं भी।
@ टॉम का उत्तर एक सेव्डमॉडल उदाहरण है, लेकिन यह टेंसोफ़्लो 2.0 पर काम नहीं करेगा, क्योंकि दुर्भाग्य से कुछ टूटने वाले बदलाव हैं।
@ विष्णुवर्धन जनपति का जवाब TF 2.0 कहता है, लेकिन यह SavedModel प्रारूप के लिए नहीं है।