В этом минимальном примере я создаю небольшой случайный лес, сохраняю его в файл (rf_test.tsess
) и затем восстанавливаю его в новый график / сеанс.Я пытаюсь использовать names_to_saveables
для Saver.restore()
, чтобы отобразить сохраненные переменные в существующие переменные в другой области видимости переменных.
import numpy as np
import tensorflow as tf
from tensorflow.contrib.tensor_forest.python import tensor_forest
from tensorflow.python.ops import resources
from tensorflow.python.tools import inspect_checkpoint as chkp
np.random.seed(123)
n_max = 20000
batch_size = 100
x_max = 100
y_max = 20
X_train = np.reshape((x_max, y_max) * np.random.random_sample((n_max, 2)), [-1, 2])
Y_train = [(lambda x, y: 0 if y < x**0.5 else 1)(*xs) for xs in X_train]
Y_sample_s = slice(100, 1000)
Y_sample = []
g0 = tf.Graph()
with g0.as_default(), tf.Session().as_default() as sess:
base_label = 0
hparams = tensor_forest.ForestHParams(num_classes=2, num_features=2, num_trees=10, max_nodes=100).fill()
rf = tensor_forest.RandomForestGraphs(hparams)
init_vars = tf.group(tf.global_variables_initializer(), resources.initialize_resources(resources.shared_resources()))
sess.run(init_vars)
X = tf.placeholder(tf.float32, shape=[None, rf.params.num_features], name="X")
Y = tf.placeholder(tf.int8, shape=[None], name="Y")
train_op = rf.training_graph(X, Y)
loss_op = rf.training_loss(X, Y)
infer_op = tf.cast(tf.argmax(rf.inference_graph(X)[0], 1, output_type=tf.int32), tf.int8, name="infer_op")
correct_prediction = tf.equal(infer_op, Y, name="correct_prediction")
accuracy_op = tf.reduce_mean(tf.cast(correct_prediction, tf.float32), name="accuracy_op")
acc = 0.0
for i in range(n_max // batch_size):
s = slice(i * batch_size, (i + 1) * batch_size)
_, l = sess.run([train_op, loss_op], feed_dict={ X: X_train[s, :], Y: Y_train[s] })
acc = sess.run(accuracy_op, feed_dict={ X: X_train[s, :], Y: Y_train[s] })
print('Step %i, Loss: %f, Acc: %f' % (i, l, acc))
if acc > 0.8:
# exit early
break
for i in range(rf.params.num_trees):
n = "device_dummy_{}".format(i)
t = g0.get_tensor_by_name("{}:0".format(n))
print(t)
#print("size {}: {}".format(t.name, tf.size(t).eval()))
n = "stats-{}".format(i)
t = g0.get_tensor_by_name("{}:0".format(n))
print(t)
#print("size {}: {}".format(t.name, tf.size(t).eval()))
n = "tree-{}".format(i)
t = g0.get_tensor_by_name("{}:0".format(n))
print(t)
#print("size {}: {}".format(t.name, tf.size(t).eval()))
#for var in tf.global_variables():
# print("global variable: {}".format(var.name))
Y_sample = sess.run(infer_op, feed_dict={ X: X_train[Y_sample_s, :] })
s = tf.train.Saver()
s.save(sess, "rf_test.tfsess")
tf.reset_default_graph()
tf.get_default_graph().as_default()
assert len(tf.global_variables()) == 0
chkp.print_tensors_in_checkpoint_file("rf_test.tfsess", tensor_name="", all_tensors=True)
Y_sample_2 = []
with tf.Session().as_default() as sess:
vs = "myscope"
with tf.variable_scope(vs, reuse=tf.AUTO_REUSE):
hparams = tensor_forest.ForestHParams(num_classes=2, num_features=2, num_trees=10, max_nodes=100).fill()
rf = tensor_forest.RandomForestGraphs(hparams)
init_vars = tf.group(tf.global_variables_initializer(), resources.initialize_resources(resources.shared_resources()))
sess.run(init_vars)
X = tf.placeholder(tf.float32, shape=[None, rf.params.num_features], name="X")
Y = tf.placeholder(tf.int8, shape=[None], name="Y")
train_op = rf.training_graph(X, Y)
loss_op = rf.training_loss(X, Y)
infer_op = tf.cast(tf.argmax(rf.inference_graph(X)[0], 1, output_type=tf.int32), tf.int8, name="infer_op")
correct_prediction = tf.equal(infer_op, Y, name="correct_prediction")
accuracy_op = tf.reduce_mean(tf.cast(correct_prediction, tf.float32), name="accuracy_op")
print(tf.contrib.framework.list_variables("rf_test.tfsess"))
vars = tf.contrib.framework.list_variables("rf_test.tfsess")
var_map = {}
for var, shape in vars:
print(var)
suffix = "" if var.endswith(":0") else ":0"
t = tf.get_default_graph().get_tensor_by_name("{}/{}{}".format(vs, var, suffix))
var_map["{}".format(var)] = t
s = tf.train.Saver(var_map)
s.restore(sess, "rf_test.tfsess")
for var in tf.global_variables():
print("global variable: {}".format(var.name))
Y_sample_2 = sess.run(infer_op, feed_dict={ X: X_train[Y_sample_s, :] })
print()
print((Y_sample == Y_sample_2).all())
print()
print(X_train[Y_sample_s, :][:10])
print(Y_sample[:10])
print(Y_sample_2[:10])
К сожалению, вышеприведенная программа приводит к ошибке:
TypeError: names_to_saveables must be a dict mapping string names to Tensors/Variables. Not a variable: Tensor("myscope/stats-0:0", shape=(), dtype=resource, device=/device:CPU:0)
Интересно, что целевая переменная является тензором, как запрашивается в сообщении об ошибке.Однако я также заметил, что с тензорами, хранящимися в файле сеанса, происходит нечто странное.Существует три типа тензоров в графе случайных лесов:
Tensor("device_dummy_0:0", shape=(0,), dtype=float32_ref, device=/device:CPU:0)
Tensor("stats-0:0", shape=(), dtype=resource, device=/device:CPU:0)
Tensor("tree-0:0", shape=(), dtype=resource, device=/device:CPU:0)
Существует один из них (с инкрементным порядковым номером) для каждого дерева в лесу.Однако tf.contrib.framework.list_variables("rf_test.tfsess")
показывает мне
[('device_dummy_0', [0]), ('device_dummy_1', [0]), ('device_dummy_2', [0]), ('device_dummy_3', [0]), ('device_dummy_4', [0]), ('device_dummy_5', [0]), ('device_dummy_6', [0]), ('device_dummy_7', [0]), ('device_dummy_8', [0]), ('device_dummy_9', [0]), ('stats-0:0', []), ('stats-1:0', []), ('stats-2:0', []), ('stats-3:0', []), ('stats-4:0', []), ('stats-5:0', []), ('stats-6:0', []), ('stats-7:0', []), ('stats-8:0', []), ('stats-9:0', []), ('tree-0:0', []), ('tree-1:0', []), ('tree-2:0', []), ('tree-3:0', []), ('tree-4:0', []), ('tree-5:0', []), ('tree-6:0', []), ('tree-7:0', []), ('tree-8:0', []), ('tree-9:0', [])]
и показывает, что переменные device_dummy_#
не имеют :0
-суффикса, в то время как переменные stats-#
и tree-#
имеют :0
-суффикс,При отбрасывании суффикса в var_map
для всех переменных ошибка меняется на
ValueError: The name 'myscope/device_dummy_0' refers to an Operation, not a Tensor. Tensor names must be of the form "<op_name>:<output_index>".
, а при добавлении его для всех переменных ошибка составляет
ValueError: The name 'myscope/stats-0:0:0' looks a like a Tensor name, but is not a valid one. Tensor names must be of the form "<op_name>:<output_index>".
. Как может быть код вышесделал работу?