tenorflow - сохранение и восстановление операций

У меня есть простая цель - обучить модель тензорного потока, сохранив и восстановив ее позже, чтобы продолжить обучение или использовать некоторые функции / операции.

Вот простой пример модели

import tensorflow as tf
import numpy as np

BATCH_SIZE = 3
VECTOR_SIZE = 1
LEARNING_RATE = 0.1

x = tf.placeholder(tf.float32, [BATCH_SIZE, VECTOR_SIZE],
                   name='input_placeholder')
y = tf.placeholder(tf.float32, [BATCH_SIZE, VECTOR_SIZE],
                   name='labels_placeholder')

W = tf.get_variable('W', [VECTOR_SIZE, BATCH_SIZE])
b = tf.get_variable('b', [VECTOR_SIZE], initializer=tf.constant_initializer(0.0))

y_hat = tf.matmul(W, x) + b
predict = tf.matmul(W, x) + b
total_loss = tf.reduce_mean(y-y_hat)
train_step = tf.train.AdagradOptimizer(LEARNING_RATE).minimize(total_loss)
X = np.ones([BATCH_SIZE, VECTOR_SIZE])
Y = np.ones([BATCH_SIZE, VECTOR_SIZE])
all_saver = tf.train.Saver() 

sess= tf.Session()
sess.run(tf.global_variables_initializer())
sess.run([train_step], feed_dict = {x: X, y:Y}))
save_path =  r'C:\some_path\save\\'
all_saver.save(sess,save_path)

Теперь мы восстановим это здесь:

meta_path = r'C:\some_path\save\.meta'
new_all_saver = tf.train.import_meta_graph(meta_path)

graph = tf.get_default_graph()
all_ops = graph.get_operations()
for el in all_ops:
    print(el)

В восстановленной операции никто даже не мог найти predict или же train_step из оригинального кода. Нужно ли называть эти операции перед сохранением? Как я могу получить predict вернуться и запустить что-то вроде этого

sess=tf.Session()
sess.run([predict], feed_dict = {x:X})

PS Я прочитал много уроков по сохранению и восстановлению в tenorflow, но все еще плохо понимаю, как все это работает.

1 ответ

Решение

1) Ваши операции выполняются в восстановленной модели, но, поскольку вы не назвали их, они будут названы в соответствии с некоторыми правилами по умолчанию. Например, так как у вас есть:

predict = tf.matmul(W, x) + b

тогда операция, представляющая predict может выглядеть так:

name: "add"
op: "Add"
input: "MatMul"
input: "b/read"
attr {
  key: "T"
  value {
    type: DT_FLOAT
  }
}

В этом примере, который печатается, когда вы делаете for el in all_ops: и печатает результат, вы видите, что имя операции "добавить", которое было автоматически назначено; тип операции ("op") - "Добавить", что соответствует последней операции, выполненной в строке кода (это +); и входы "MatMul" и "b/read", соответствующие тому, что вы суммировали. Просто чтобы быть ясным, я не уверен, что только эта операция соответствует данной строке кода, так как другие надстройки с тем же типом входных данных присутствовали в печати, но это возможно.

Итак, подведем итоги до сих пор: ваши операции есть, и вы видите их при печати. Но почему вы не видите слово "предсказать"? Ну, потому что это не имя тензора или операции в Tensorflow Graph, это только имя переменной в вашем коде.

В дальнейшем, как вы могли бы получить доступ к этому "предсказанию"? Ответ через его имя, как указано на графике. В вышеприведенном случае имя предиката могло бы быть "добавить", если я прав в своем предположении, но давайте вместо этого назовем ваш "прогноз", чтобы вы могли легко контролировать, какая операция ему соответствует.

Чтобы назвать ваш "прогноз", давайте добавим следующую строку кода чуть ниже predict = tf.matmul(W, x) + b:

predict_named = tf.identity(predict, "here_i_put_a_name")

Эта строка создает новую операцию, которая получает в качестве входных данных операцию, определенную в "предикате", и выдает выходные данные, равные результату входных данных. Сама операция не делает много - просто повторяет значение - но с помощью этой операции я мог бы добавить к ней имя. Теперь, если вы будете искать в вашей печати, вы сможете найти:

name: "add_1"
op: "Add"
input: "MatMul_1"
input: "b/read"
attr {
  key: "T"
  value {
    type: DT_FLOAT
  }
}

name: "here_i_put_a_name"
op: "Identity"
input: "add_1"
attr {
  key: "T"
  value {
    type: DT_FLOAT
  }
}

Ницца! Теперь вы 1) можете получить доступ к своему "прогнозу", используя имя "here_i_put_a_name" и 2) мы можем просто подтвердить, что ваш "прогноз" на самом деле был операцией с именем "add_1" - просто проверьте над атрибутом "input" операции "here_i_put_a_name".

После этого давайте перейдем к операции "here_i_put_a_name" и сделаем несколько прогнозов. Сначала измените save_path и meta_path, поместив в конце возможное имя файла, например:

save_path =  r'C:\some_path\save\my_model_name'
meta_path = r'C:\some_path\save\my_model_name.meta'

Затем в конце кода восстановления добавьте:

with tf.Session(graph=graph) as sess:

    new_all_saver.restore(sess,save_path)
    my_prediction = sess.run(["here_i_put_a_name:0"], feed_dict={"input_placeholder:0": [[1],[2],[3]]})
    print(my_prediction)

С помощью этого блока вы создаете новый сеанс Tensorflow и используете график, хранящийся в вашей переменной "graph". Внутри этого контекста вы восстанавливаете сеанс из save_path в текущий сеанс. Затем вы выполняете прогноз, или, точнее, вы запускаете операцию "here_i_put_a_name" и получаете первый вывод этой операции (причина, по которой у нас после нее ":0"). Канал dict передает значение [[1],[2],[3]] тензору "input_placeholder:0" (опять же, ":0" показывает нам, что это тензор, а не операция).

После всего сказанного и с ответами на вопросы (надеюсь) у меня есть несколько комментариев:

1) По моему опыту, было бы неплохо использовать библиотеку tf.saved_model для того, чтобы сохранить и восстановить модули. Но это мое личное предложение.

2) Я ограничился ответом на ваши вопросы об именовании и вызове операций, поэтому я проигнорировал процедуры обучения и прогнозирования. Но я думаю, что вы имеете дело с проблемой, когда ставите переменную X с размером BATCH_SIZE.

3) Обратите внимание на разницу между "blabla" и "blabla:0". Первый - операция, а последний - тензор.

Другие вопросы по тегам