复用 TensorFlow 模型
一、復用流程
????如果原始模型使用 TensorFlow 進行訓練,則可以簡單地將其恢復并在新任務上進行訓練:
????第一步:
????????[...] # construct the original model
????第二步:
????????with tf.Session() as sess:
? ? ????????saver.restore(sess, "./my_model_final.ckpt")
? ? ????????# continue training the model...
二、完整代碼
n_inputs = 28 * 28? # MNIST
n_hidden1 = 300
n_hidden2 = 50
n_hidden3 = 50
n_hidden4 = 50
n_outputs = 10
X = tf.placeholder(tf.float32, shape=(None, n_inputs), name="X")
y = tf.placeholder(tf.int64, shape=(None), name="y")
with tf.name_scope("dnn"):
? ? hidden1 = tf.layers.dense(X, n_hidden1, activation=tf.nn.relu, name="hidden1")
? ? hidden2 = tf.layers.dense(hidden1, n_hidden2, activation=tf.nn.relu, name="hidden2")
? ? hidden3 = tf.layers.dense(hidden2, n_hidden3, activation=tf.nn.relu, name="hidden3")
? ? hidden4 = tf.layers.dense(hidden3, n_hidden4, activation=tf.nn.relu, name="hidden4")
? ? hidden5 = tf.layers.dense(hidden4, n_hidden5, activation=tf.nn.relu, name="hidden5")
? ? logits = tf.layers.dense(hidden5, n_outputs, name="outputs")
with tf.name_scope("loss"):
? ? xentropy = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=y, logits=logits)
? ? loss = tf.reduce_mean(xentropy, name="loss")
with tf.name_scope("eval"):
? ? correct = tf.nn.in_top_k(logits, y, 1)
? ? accuracy = tf.reduce_mean(tf.cast(correct, tf.float32), name="accuracy")
learning_rate = 0.01
threshold = 1.0
optimizer = tf.train.GradientDescentOptimizer(learning_rate)
grads_and_vars = optimizer.compute_gradients(loss)
capped_gvs = [(tf.clip_by_value(grad, -threshold, threshold), var)
? ? ? ? ? ? ? for grad, var in grads_and_vars]
training_op = optimizer.apply_gradients(capped_gvs)
init = tf.global_variables_initializer()
saver = tf.train.Saver()
with tf.Session() as sess:
? ? saver.restore(sess, "./my_model_final.ckpt")
? ? for epoch in range(n_epochs):
? ? ? ? for iteration in range(mnist.train.num_examples // batch_size):
? ? ? ? ? ? X_batch, y_batch = mnist.train.next_batch(batch_size)
? ? ? ? ? ? sess.run(training_op, feed_dict={X: X_batch, y: y_batch})
? ? ? ? accuracy_val = accuracy.eval(feed_dict={X: mnist.test.images,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? y: mnist.test.labels})
? ? ? ? print(epoch, "Test accuracy:", accuracy_val)
? ? save_path = saver.save(sess, "./my_new_model_final.ckpt")
但是,一般情況下,您只需要重新使用原始模型的一部分(就像我們將要討論的那樣)。 一個簡單的解決方案是將Saver配置為僅恢復原始模型中的一部分變量。 例如,下面的代碼只恢復隱藏的層1,2和3:
n_inputs = 28 * 28? # MNIST
n_hidden1 = 300 # reused
n_hidden2 = 50? # reused
n_hidden3 = 50? # reused
n_hidden4 = 20? # new!
n_outputs = 10? # new!
X = tf.placeholder(tf.float32, shape=(None, n_inputs), name="X")
y = tf.placeholder(tf.int64, shape=(None), name="y")
with tf.name_scope("dnn"):
? ? hidden1 = tf.layers.dense(X, n_hidden1, activation=tf.nn.relu, name="hidden1")? ? ? ?# reused
? ? hidden2 = tf.layers.dense(hidden1, n_hidden2, activation=tf.nn.relu, name="hidden2") # reused
? ? hidden3 = tf.layers.dense(hidden2, n_hidden3, activation=tf.nn.relu, name="hidden3") # reused
? ? hidden4 = tf.layers.dense(hidden3, n_hidden4, activation=tf.nn.relu, name="hidden4") # new!
? ? logits = tf.layers.dense(hidden4, n_outputs, name="outputs")? ? ? ? ? ? ? ? ? ? ? ? ?# new!
with tf.name_scope("loss"):
? ? xentropy = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=y, logits=logits)
? ? loss = tf.reduce_mean(xentropy, name="loss")
with tf.name_scope("eval"):
? ? correct = tf.nn.in_top_k(logits, y, 1)
? ? accuracy = tf.reduce_mean(tf.cast(correct, tf.float32), name="accuracy")
with tf.name_scope("train"):
? ? optimizer = tf.train.GradientDescentOptimizer(learning_rate)
? ? training_op = optimizer.minimize(loss)
[...] # build new model with the same definition as before for hidden layers 1-3?
reuse_vars = tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?scope="hidden[123]") # regular expression
reuse_vars_dict = dict([(var.op.name, var) for var in reuse_vars])
restore_saver = tf.train.Saver(reuse_vars_dict) # to restore layers 1-3
init = tf.global_variables_initializer()
saver = tf.train.Saver()
with tf.Session() as sess:
? ? init.run()
? ? restore_saver.restore(sess, "./my_model_final.ckpt")
? ? for epoch in range(n_epochs):? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # not shown in the book
? ? ? ? for iteration in range(mnist.train.num_examples // batch_size): # not shown
? ? ? ? ? ? X_batch, y_batch = mnist.train.next_batch(batch_size)? ? ? # not shown
? ? ? ? ? ? sess.run(training_op, feed_dict={X: X_batch, y: y_batch})? # not shown
? ? ? ? accuracy_val = accuracy.eval(feed_dict={X: mnist.test.images,? # not shown
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? y: mnist.test.labels}) # not shown
? ? ? ? print(epoch, "Test accuracy:", accuracy_val)? ? ? ? ? ? ? ? ? ?# not shown
? ? save_path = saver.save(sess, "./my_new_model_final.ckpt")
首先我們建立新的模型,確保復制原始模型的隱藏層 1 到 3。我們還創建一個節點來初始化所有變量。 然后我們得到剛剛用trainable = True(這是默認值)創建的所有變量的列表,我們只保留那些范圍與正則表達式hidden [123]相匹配的變量(即,我們得到所有可訓練的隱藏層 1 到 3 中的變量)。 接下來,我們創建一個字典,將原始模型中每個變量的名稱映射到新模型中的名稱(通常需要保持完全相同的名稱)。 然后,我們創建一個Saver,它將只恢復這些變量,并且創建另一個Saver來保存整個新模型,而不僅僅是第 1 層到第 3 層。然后,我們開始一個會話并初始化模型中的所有變量,然后從原始模型的層 1 到 3中恢復變量值。最后,我們在新任務上訓練模型并保存。
任務越相似,您可以重復使用的層越多(從較低層開始)。 對于非常相似的任務,您可以嘗試保留所有隱藏的層,只替換輸出層
總結
以上是生活随笔為你收集整理的复用 TensorFlow 模型的全部內容,希望文章能夠幫你解決所遇到的問題。