#tensorflow #neural-network #tensor
#tensorflow #нейронная сеть #тензор
Вопрос:
Мне нужно предоставить «логиты» одного графика (g1) в качестве входных данных другого графика (g2). Затем мне нужно получить выходные данные уровня g2, когда входные данные являются «logits». После некоторых вычислений на выходных данных слоя я должен вернуть пользовательское значение потерь в g1.
Вот первый график:
g1 = tf.Graph()
with g.as_default():
X = tf.placeholder(dtype=tf.float32, shape=[...])
Y = tf.placeholder(dtype=tf.float32, shape=[...])
...
logits = tf.matmul(flatten, W2) b2
def custom_loss(logits):
# get layer output values of g2 on the input "logits"
# some calculations on layer outputs
return loss
mse = tf.reduce_mean(tf.squared_difference(logits, Y))
loss = mse custom_loss(logits)
step = tf.train.AdamOptimizer(learning_rate=1e-4).minimize(loss)
sess1 = tf.InteractiveSession(graph=g1)
tf.global_variables_initializer().run()
Вот второй график:
g2 = tf.Graph()
with g2.as_default():
X = tf.placeholder(dtype=tf.float32, shape=[...])
Y = tf.placeholder(dtype=tf.float32, shape=[...])
...
loss = ...
step = ...
sess2 = tf.InteractiveSession(graph=g2)
tf.global_variables_initializer().run()
Я не уверен, что это возможно сделать. Первая проблема в том, что сеансы работы с этими графами разные. Следовательно, я не мог ввести «логиты» в качестве входных данных g2 на графике g1.
Вторая проблема в том, что g2 принимает массив элементов («X»), но когда я передаю «logits» в g2, это не сработает, поскольку это тензор. Можно преобразовать его в массив numpy, используя сеанс, но как я могу использовать сеанс внутри графика? Я создаю сеанс после того, как я создал график.
Мне нужны ваши предложения для решения этих проблем. Заранее спасибо.
Ответ №1:
Рассмотрим следующий пример. У вас есть первый график следующим образом:
import tensorflow as tf
graph1 = tf.Graph()
with graph1.as_default():
x1 = tf.placeholder(tf.float32, shape=[None, 2])
y1 = tf.placeholder(tf.int32, shape=[None])
with tf.name_scope('network'):
logits1 = tf.layers.dense(x1, units=2)
train_vars1 = tf.trainable_variables()
И второй график:
graph2 = tf.Graph()
with graph2.as_default():
x2 = tf.placeholder(tf.float32, shape=[None, 2])
y2 = tf.placeholder(tf.int32, shape=[None])
with tf.name_scope('network'):
logits2 = tf.layers.dense(x2, units=2)
with tf.name_scope('loss'):
xentropy2 = tf.nn.sparse_softmax_cross_entropy_with_logits(
labels=y2, logits=logits2)
loss_fn2 = tf.reduce_mean(xentropy2)
with tf.name_scope('optimizer'):
optimizer2 = tf.train.GradientDescentOptimizer(0.01)
train_op2 = optimizer2.minimize(loss_fn2)
train_vars2 = tf.trainable_variables()
Теперь вы хотите передать выходные данные уровня logits первого графика в качестве входных данных во второй график. Мы делаем это, создавая два сеанса, инициализируя переменные, оценивая уровень logits первого графика, а затем отправляя вычисленное значение в качестве входных данных во второй график. Я собираюсь использовать набор данных toy blobs для иллюстрации:
from sklearn.datasets import make_blobs
x_train, y_train = make_blobs(n_samples=4,
n_features=2,
centers=[[1, 1], [-1, -1]],
cluster_std=0.5)
sess1 = tf.Session(graph=graph1)
sess2 = tf.Session(graph=graph2)
_ = sess1.run([v.initializer for v in train_vars1])
_ = sess2.run([v.initializer for v in train_vars2])
# feed the logits layer of graph1 as input to graph2
logits1_val = sess1.run(logits1, feed_dict={x1:x_train})
logits2_val = sess2.run(logits2, feed_dict={x2:logits1_val})
print(logits2_val)
# [[ 1.3904244 2.811252 ]
# [-0.39521402 -1.6812694 ]
# [-1.7728546 -4.522432 ]
# [ 0.6836863 3.2234416 ]]
Обратите внимание, что вычисленное значение логитов первого графика ( logits1_val
) уже является массивом numpy, поэтому вы можете использовать его как есть в качестве входных данных второго графика. То же самое, когда вы хотите выполнить шаг поезда для второго графика:
# train step for the second graph
logits1_val = sess1.run(logits1, feed_dict={x1:x_train})
loss_val2, _ = sess2.run([loss_fn2, train_op2], feed_dict={x2:logits1_val, y2:y_train})
print(loss_val2) # 0.8134985
ОБНОВИТЬ, если мы определим обе сети в одном графике:
import tensorflow as tf
from sklearn.datasets import make_blobs
x_train, y_train = make_blobs(n_samples=4,
n_features=2,
centers=[[1, 1], [-1, -1]],
cluster_std=0.5)
with tf.variable_scope('network_1'):
x = tf.placeholder(tf.float32, shape=[None, 2])
y = tf.placeholder(tf.int32, shape=[None])
with tf.name_scope('network'):
logits1 = tf.layers.dense(x, units=2)
with tf.variable_scope('network_2'):
with tf.name_scope('network'):
logits2 = tf.layers.dense(logits1, units=2) # <-- output of `network_1` is input to `network_2`
with tf.name_scope('custom_loss'):
# Define your custom loss here. I use cross-entropy
# for illustration
xentropy2 = tf.nn.sparse_softmax_cross_entropy_with_logits(
labels=y, logits=logits2)
custom_loss2 = tf.reduce_mean(xentropy2)
with tf.name_scope('optimizer'):
optimizer2 = tf.train.GradientDescentOptimizer(0.01)
var_list = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES,
scope='network_2')
train_op2 = optimizer2.minimize(custom_loss2, var_list=var_list)
with tf.variable_scope('network_1'):
# Take the `custom_loss2` from `network_2` and create a new custom loss
# for `network_1`
xentropy1 = tf.nn.sparse_softmax_cross_entropy_with_logits(
labels=y, logits=logits1)
custom_loss1 = tf.reduce_mean(xentropy1) custom_loss2 # <-- loss from `network_2`
optimizer1 = tf.train.AdamOptimizer(0.01)
var_list = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES,
scope='network_1')
train_op1 = optimizer1.minimize(custom_loss1, var_list=var_list)
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
# grad update step loss computation for first network
loss1, _ = sess.run([custom_loss1, train_op1], feed_dict={x:x_train, y:y_train})
print(loss1) # 0.44655064
# grad update step loss computation for second network
loss2, _ = sess.run([custom_loss2, train_op2], feed_dict={x:x_train, y:y_train})
print(loss2) # 0.3163877
Комментарии:
1. Спасибо за быстрый ответ @Vlad! Я понял, как передавать логиты graph1 в качестве входных данных graph2, например. Но мне нужно сделать это внутри графика, поскольку я добавлю возвращаемое значение к функции потерь. Например;
logits1_val = sess1.run(logits1, feed_dict={X1:logits2, Y1:np.zeros((1,10))})
. Это должно быть внутри графа2. Здесь проблема в том, что «feed_dict» не принимает «logits2» для «X1», потому что это не массив numpy. Я не могу оценить его как «sess2.run(logits2)», чтобы получить его значение массива внутри графика , поскольку sess2 еще не создан для graph2. Надеюсь, это поясняющее.2. Хорошо, я думаю, что знаю, как это написать. Я пропустил ту часть, которая вам нужна для возврата потерь со второго графика. Это слишком сложно сделать с двумя отдельными графиками, потому что будет сложно вычислить градиенты потерь по отношению к весам из обоих графиков (для этого потребуется вычисление градиента вручную). Это должны быть две отдельные сети на одном графике. Здесь немного поздно, поэтому я сформулирую свой ответ завтра.
3. Спасибо за ваш ответ @Vlad. Это действительно то, чего я хочу.