I have the following code:
self.sess = tf.Session()
_, self.cost = self.sess.run(
[self._train_op, self.loss],
feed_dict={self.s: batch_memory[:, :self.n_features],
self.q_target: q_target}
)
The order of execution as I understand it is:
self.cost=self.sess.run(
[self.loss],feed_dict={self.s: batch_memory[:, :self.n_features], self.q_target: q_target})
_=self.sess.run([self._train_op],feed_dict={self.loss:self.cost})
Is my understanding correct?
The order of execution is sequential. Graph will be created in the same order the operations are defined inside the session.
Simple example:
import tensorflow as tf
x = 4
y = 5
add_op = tf.add(x, y, name='Add')
mul_op = tf.multiply(x, y, name='Multiply')
pow_op = tf.pow(add_op, mul_op, name='Power')
useless_op = tf.multiply(x, add_op, name='Useless')
with tf.Session() as sess:
pow_out, useless_out = sess.run([pow_op, useless_op])
When fetch pow_op operation, it will first run the add_op and mul_op to get their output tensor and then run pow_op on them to compute the required output value. In other words useless_op will not be executed as it's output tensor is not used in executing the pow_op operation.
Related
For example, I assume I have something like:
run1 = tf.assign(y,x)
run2 = tf.assign(z,y)
sess.run(run2, feed_dict={x:a}
Will this call first run1, then run2, or do I need to explicitly call run1 first?
I'm having trouble with other code I have. Is this error related at all?
FailedPreconditionError: Attempting to use uninitialized value
Variable_11 [[node Variable_11/read (defined at
:20) ]]
To answer the title, not always the case, an example where it is true:
import tensorflow as tf
x = tf.placeholder(dtype=tf.float32, name="input_vector1")
y = tf.placeholder(dtype=tf.float32, name="input_vector2")
mul1 = tf.multiply(x, y)
mul2 = tf.multiply(mul1, x)
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
print(sess.run(mul2, feed_dict={x: 2, y: 3}))
The operators are all connected, x, and y are inputs provided in the sess.run, and I request mul2, therefore mul1 will first have to be calculated, which will happen automatically in the same sess.run.
Example where it is not the case:
import tensorflow as tf
x = tf.placeholder(dtype=tf.float32, name="input_vector1")
y = tf.placeholder(dtype=tf.float32, name="input_vector2")
mul1 = tf.multiply(x, y)
mul2 = tf.multiply(y, x)
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
print(sess.run(mul2, feed_dict={x: 2, y: 3}))
To calculate mul2, there is no need for mul1, so tensorflow wont be bothered with it.
To see which operators are connected you can do:
import tensorflow as tf
x = tf.placeholder(dtype=tf.float32, name="input_vector1")
y = tf.placeholder(dtype=tf.float32, name="input_vector2")
mul1 = tf.multiply(x, y)
mul2 = tf.multiply(mul1, x)
with tf.Session() as sess:
tf.summary.FileWriter("path/to/empty/folder", sess.graph)
This script will log a logfile to a folder, this logfile can then be read with
tensorboard --logdir=path/to/empty/folder
for more info about tensorboard I refer to the official guide
The error you have is because you did not run sess.run(tf.global_variables_initializer()), this initializes all variables
First of all, you should run below code in order to eliminate the error.
sess.run(tf.global_variables_initializer())
After, you should call run1 and run2 respectively to assign a to z. But if you want to assign a to z with run2, you should define run2 as follow:
run2 = tf.assign(z, run1)
With this code, when you try to call run2, run1 will run and the result of run1 will assign to z.
I've attempted converting a Python-side training loop to Tensorflow to (hypothetically) make the code run faster - not having to pass control over to cpu constantly. However, I can't manage using tf.while_loop.
Here's the code that works:
import numpy as np
import tensorflow as tf
from tqdm import tqdm
from sklearn.datasets import load_iris
from sklearn.preprocessing import RobustScaler
x, y = load_iris(True)
x = RobustScaler().fit_transform(x)
shape = (10, 10)
max_epochs = 1000
graph = tf.Graph()
sess = tf.Session(graph=graph)
x = x.astype(np.float64)
# Construct graph
with graph.as_default():
weights = tf.get_variable(
'weights', shape, initializer=tf.constant_initializer, dtype=tf.float64
)
curr_epoch = tf.placeholder(dtype=tf.int64, shape=())
with tf.name_scope('data'):
data = tf.data.Dataset.from_tensor_slices(x)
data = data.shuffle(buffer_size=10000)
data = data.repeat(max_epochs)
data = data.batch(1)
data = data.make_one_shot_iterator().get_next()
with tf.name_scope('update'):
update_op = make_update_op(weights)
init = tf.global_variables_initializer()
sess.run(init)
for i in tqdm(range(max_epochs)):
for _ in range(x.shape[0]):
sess.run(update_op, feed_dict={
curr_epoch: i
})
np_weights = sess.run(weights)
print(np_weights) # Correctly prints an array of 150's.
Now, if I create an update function to pass tf.while_loop, an error is thrown.
def make_update_op(w):
return w.assign(
w + 0.001
)
# In the code above:
update_op = tf.while_loop(lambda _: True, make_update_op, (weights,), maximum_iterations=x.shape[0])
# No inner loop:
for i in tqdm(range(max_epochs)):
sess.run(update_op, feed_dict={
curr_epoch: i
})
Line 22, in make_update_op
return w.assign(
AttributeError: 'Tensor' object has no attribute 'assign'
I don't quite understand what is happening even after reading the documentation. weights is a Variable after all. What could be done to correctly make the training loop?
The tensor that you're trying to assign a new value within a while loop is a result of a sequence of multiple operations-tensors (operation is node in the graph, while tensor is a directed edge). In particular, the while loop will produce:
Variable/Read-->while/Enter-->while/Merge-->while/Switch-->while/Identity
What you're trying to assign here is a tensor while/Identity.
tf.while_loop is usually used to iterate over the dimensions of a tensor (also over the None - the unknown dimension). You're trying to iterate over the variables that are fully defined. You don't need to create a tf.while_loop for that. Just create operations that update each variable and group these operations together:
update_ops = [w.assign(w + 0.001) for w in weights]
update_op = tf.group(update_ops)
Now, when you execute the update_op with tf.Session() interface it will update all variables.
Example:
import tensorflow as tf
v1 = tf.Variable(tf.ones((1, 2), dtype=tf.float32))
v2 = tf.Variable(2*tf.ones((1, 3), dtype=tf.float32))
update_ops = [w.assign(w + 0.001) for w in [v1, v2]]
update_op = tf.group(update_ops)
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
print('before update:')
print(v1.eval(), v2.eval())
print('after update:')
sess.run(update_op) # <-- update your variables
print(v1.eval(), v2.eval())
# before update:
# [[1. 1.]] [[2. 2. 2.]]
# after update:
# [[1.001 1.001]] [[2.001 2.001 2.001]]
Turns out, all that was missing was the fact that one cannot assign to a variable inside a loop as Vlad pointed out. Instead, one can return the new value of a variable.
def make_update_op(w):
return w + 0.001
new_w = tf.while_loop(lambda _: True, make_update_op, (weights,), maximum_iterations=x.shape[0])
update_op = weights.assign(new_w)
To use more variables one would need to return the same amount from the function and unpack them in Python, but the principle is the same.
def make_update_op(w, d):
return w + 0.001, d
new_w, _ = tf.while_loop(lambda *_: True, make_update_op, (weights, data), maximum_iterations=x.shape[0])
update_op = weights.assign(new_w)
I have created a function with TF operations that I invoke with tf.data.Dataset.map() to transform the input data to my model. Inside that function I create a tf.Variable and assign to it. When initializing the variables, TF complains that the variable's init operation is not an element of the graph, or that the variable does not belong to the same graph as the other variables. I would appreciate any help to solve this issue.
Here you can see some toy code to reproduce the issue (TF 1.12):
import tensorflow as tf
def fun(x):
f = tf.Variable(tf.ones((1,), dtype=tf.int64), name='test')
op = f.assign(x, name='test_assign')
with tf.control_dependencies([op]):
f = tf.identity(f)
return f
def generator():
while True:
yield [2]
ds = tf.data.Dataset.from_generator(generator,
output_shapes=tf.TensorShape([1,]), output_types=tf.int64)
ds = ds.map(fun)
iterator = ds.make_one_shot_iterator()
y = iterator.get_next()
sess = tf.Session()
sess.run(tf.global_variables_initializer())
for _ in range(5):
print(sess.run(y)
I am learning to use tensorflow library. Every time I try to use simplest (I guess) possible example of gradient-based learning I get the same error, which makes me stuck.
Here is the code:
import tensorflow as tf
x = tf.constant(1, dtype=tf.float32, name='X')
a = tf.Variable(1, dtype=tf.float32, name= 'A')
y = tf.constant(10, dtype=tf.float32, name='Y')
ey = tf.multiply(x, a)
los = (y - ey)**2
optim = tf.train.GradientDescentOptimizer(learning_rate=0.2)
sess = tf.Session()
sess.run(tf.global_variables_initializer())
for counter in range(100):
grd = sess.run(optim.compute_gradients(loss=los))
sess.run(optim.apply_gradients(grads_and_vars=grd))
On the last line, I get following error:
AttributeError: 'numpy.float32' object has no attribute 'op'.
Thank you in advance for any tips.
The input of apply_gradients must be a tensor not a numpy array. Because, it is not meant to be called at each step of the learning but just once when building your graph. In fact, it "creates" the "training step" in which variables are updated using the computed gradient
You should use that kind of code instead:
import tensorflow as tf
x = tf.constant(1, dtype=tf.float32, name='X')
a = tf.Variable(1, dtype=tf.float32, name= 'A')
y = tf.constant(10, dtype=tf.float32, name='Y')
ey = tf.multiply(x, a)
los = (y - ey)**2
optim = tf.train.GradientDescentOptimizer(learning_rate=0.2)
grads, vars = zip(*optimizer.compute_gradients(loss))
train_step = optim.apply_gradients(grads_and_vars=grads)
sess = tf.Session()
sess.run(tf.global_variables_initializer())
for counter in range(100):
grd = sess.run(train_step, feed_dict = {...})
The tensorflow converts tensor into numpy array when stored and evaluated using sess.run(). The apply_gradients method of GradientDescentOptimizer raises TypeError since it requires tensor as input as described here. This causing problem in the original code.
for counter in range(100):
grd = sess.run(optim.compute_gradients(loss=los))
sess.run(optim.apply_gradients(grads_and_vars=grd))
The solution to this problem is to define all the operations before starting session.
There may be cases where gradients need to be post-processed before updating weights. All such post-processing logic need to be defined before session begins.
Here is a simple example:
import tensorflow as tf
x = tf.constant(1, dtype=tf.float32, name='X')
a = tf.Variable(1, dtype=tf.float32, name= 'A')
y = tf.constant(10, dtype=tf.float32, name='Y')
ey = tf.multiply(x, a)
loss = (y - ey)**2
optim = tf.train.GradientDescentOptimizer(learning_rate=0.2)
grads = optim.compute_gradients(loss)
train_step = optim.apply_gradients(grads_and_vars=grads)
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
for counter in range(100):
sess.run(train_step)
When tensorflow's session is runned, i need to get the same value of y. How can i get y with same value, not rerun this graph?
import tensorflow as tf
import numpy as np
x = tf.Variable(0.0)
tf.set_random_seed(10)
x_plus1 = x+tf.random_normal([1], mean=0.0, stddev=0.01,dtype=tf.float32)
y = tf.Variable([1.0])
y += x_plus1
z = y + tf.random_normal([1], mean=0.0, stddev=0.01,dtype=tf.float32)
init = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init)
print(z.eval())
for i in range(5):
print(y.eval())
Here, i want to get y that contributes to z.
You can evaluate y and z simultaneously with sess.run(), that runs the needed parts of the graph only once, hence the value for y will be the one used for z.
with tf.Session() as sess:
sess.run(init)
z_value, y_value = sess.run([z, y])
print(z_value)
print(y_value)
Modify the with block as following, this way you only evaluate the graph once, before the for loop, then you can print it as many times as you like:
with tf.Session() as sess:
sess.run(init)
print(z.eval())
yy = y.eval()
for i in range(5):
print(yy)