按照此处的示例[https://www.tensorflow.org/extend/adding_an_op],我创建了自己的运算符,我们将其命名为MyConv
。
现在,如果我做这样的事情:
# placeholders for inputs and labels
input = tf.placeholder(...)
label = tf.placeholder(...)
# MyConv operator on inputs... returns 1D tensor
conv_out = my_module.my_conv(input, ...)
# final classifier
output = tf.layers.dense(inputs=conv_out, units=10)
# eveything we need for backprop
probs = tf.losses.sparse_softmax_cross_entropy(logits=output, labels=label)
loss = tf.reduce_mean(probs)
adam_opt = tf.train.AdamOptimizer(learning_rate=0.01)
train_op = adam_opt.minimize(loss)
并通过简单的输入转发将模型运行N-1次,而使用反向传播器仅运行N次:
num_of_chunks = 100
init = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init)
for c in range(num_of_chunks):
single_input = np.array(...)
# for num_of_chunks-1 times, just push the single_input through the network
if c != num_of_chunks - 1:
result = sess.run([output], feed_dict={input:single_input})
# only the last time, do the backprop and run the optimizer
else:
result, loss_out, train_out = sess.run([output, loss, train_op], feed_dict={input:single_input, label:np.array(...)})
发生了一件有趣的事情。 TF sess.run()
方法将实例化MyConv
类的一个对象并使用num_of_chunks-1
次,但最后一次(当它执行此else
路径时)将创建一个新对象。类MyConv
的对象,并使用该新对象(已再次调用MyConv()构造函数)。看起来,仅仅是因为在else
路径中引入了反向传播,sess.run()
创建了MyConv
运算符的新对象,但这并不是我所期望的行为(我存储了一些信息作为私有类成员,我真的很想在运行会话时保留一个MyConv
对象)。
所以,问题是:您是否知道sess.run()方法为什么会因为我从“仅向前模式”切换到“正向和反向传播模式”而创建了运算符的新对象?
另外,一个音符。如果我删除此if-else
语句并让每个块都执行backprop,那么一切都很好,仅实例化和使用MyConv
的一个对象。