I want to differentiate a vector with respect to another using TensorFlow. I am unable to write and visualize the output (just started my journey on TensorFlow)
I am attaching the code snippet I have tried.
import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
x = np.linspace(-np.pi, np.pi, 120)
y = np.sinh(x)
plt.plot(x,y)
plt.axhline(color="gray", zorder=-1)
plt.axvline(color="gray", zorder=-1)
plt.show()
X = tf.constant(x, dtype=tf.float32)
Y = tf.constant(y, dtype=tf.float32)
gradient = tf.gradients(Y, X)
init = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init)
I am unable to output the gradient. I also tried a placeholder for the gradients but cannot figure out how to go about.
Your Y doesn't depend on X. The way you have defined them they are just two independent tensors. This is probably what you want:
import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
x_data = np.linspace(-np.pi, np.pi, 120)
y_data = np.sinh(x_data)
plt.plot(x_data, y_data)
plt.axhline(color="gray", zorder=-1)
plt.axvline(color="gray", zorder=-1)
plt.show() # <-- shows image
x = tf.constant(x_data, dtype=tf.float32)
y = tf.math.sinh(x) # <-- `y` is a function of `x`
grads = tf.gradients(y, x)
# init = tf.global_variables_initializer() # <-- No need, you don't have variables here
with tf.Session() as sess:
print(sess.run(grads)) # <-- prints long array
Related
I want to constrain the updates by clipping the updated variables. I know the boundary of variables so i need to constrain it.
import tensorflow as tf
tf.compat.v1.enable_eager_execution()
import tensorflow_probability as tfp
import numpy as np
import matplotlib.pyplot as plt
def rosen(x):
"""The Rosenbrock function"""
return sum(100.0*(x[1:]-x[:-1]**2.0)**2.0 + (1-x[:-1])**2.0)
x0 = np.array([1.3, 0.7, 0.8, 1.9, 1.2])
"Trial #1"
x = tf.Variable(x0)
opt = tf.keras.optimizers.Adam(learning_rate=0.1)
ls = []
clip_min = [0,0,0,0,0]
clip_max = [2,2,2,2,2]
for _ in range(3000):
with tf.GradientTape() as tape:
tape.watch(x)
loss = rosen(x)
ls.append(loss.numpy())
grads = tape.gradient(loss, x)
opt.apply_gradients(zip([grads], [x]))
"This is the error !!!!!"
x = tf.clip_by_value(x, clip_value_min=clip_min,
clip_value_max=clip_max)
sol1 = x.numpy()
plt.plot(np.arange(len(ls)), ls)
It gives me this error:
AttributeError: 'tensorflow.python.framework.ops.EagerTensor' object has no attribute '_in_graph_mode'
How to solve this??
Why is GradientTape returning None when I use numpy math
I am trying to understand tensorflow GradientTape calculation for RL loss function. When I call a function using np.math the GradientTape returns None. If I use tf.math in the function it works fine. I have looked at tf-agents like ppo and sac and they are doing exactly(?) what I am trying to do (I have tried at last 50 other versions).
What's wrong in the code below? What am I missing?
window 10, python 3.6.8, tensorflow 2.0.0
ref:https://github.com/chagmgang/tf2.0_reinforcement_learning/blob/master/policy/ppo.py
import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
def my_loss1(x):
y=tf.sin(x)
y=tf.abs(y)
return y
def my_loss2(x):
y=np.sin(x)
y=np.abs(y)
return y
def main(ver):
x = np.linspace(0,10,25)
dsin_dx=np.cos(x)
xx = tf.constant(x)
with tf.GradientTape() as tape:
tape.watch(xx)
if ver==0:
# my_loss1 with tf math
loss1=my_loss1(xx)
if ver==1:
#my loss with numpy math
loss1=my_loss2(np.array(xx))
loss1 = tf.convert_to_tensor(loss1, dtype=tf.float64)
print(loss1)
loss=tf.reduce_sum(loss1)
print('loss=',loss)
grads = tape.gradient(loss, xx)
fig, ax = plt.subplots(2)
ax[0].plot(x,loss1,'r')
print('grads', grads)
if not grads is None:
ax[1].plot(x, grads)
ax[1].plot(x,dsin_dx)
plt.show()
if __name__ == '__main__':
main(ver=0) # This works ok
main(ver=1) # This returns grads = None
The problem is that the Gradient tape only records tensors. Numpy variables are not recorded why the gradient can't be calqulated in case ver=1. Loss1 in ver1 looks identical to loss1 in ver=0 but the dependentsy to xx is broken by numpy.
My ref. has this error when calculation get_gaes() and the calculation of the grads is incorrect.
Here is the simplest code that can reproduce the problem:
import numpy as np
import random
import tensorflow as tf
tf.set_random_seed(12345)
np.random.seed(12345)
random.seed(12345)
unusable1 = tf.constant(1e-3, tf.float32)
unusable2 = tf.constant(1e-3, tf.float32)
unusable3 = tf.constant(1e-3, tf.float32)
X = tf.placeholder(tf.float32, shape=[2, 3])
cell = tf.contrib.rnn.BasicRNNCell(5)
changed_data = tf.reduce_sum(cell(X, state = tf.zeros((2, 5)))[0])
with tf.Session() as sess:
tf.global_variables_initializer().run()
output = sess.run(changed_data, feed_dict={X: np.ones((2, 3))})
print(output) # = -1.46618
The result of the above code is -1.46618 on my machine.
However, if I comment out three unusable constant tensor declarations, the result becomes 1.76918!
import numpy as np
import random
import tensorflow as tf
tf.set_random_seed(12345)
np.random.seed(12345)
random.seed(12345)
# unusable1 = tf.constant(1e-3, tf.float32)
# unusable2 = tf.constant(1e-3, tf.float32)
# unusable3 = tf.constant(1e-3, tf.float32)
X = tf.placeholder(tf.float32, shape=[2, 3])
cell = tf.contrib.rnn.BasicRNNCell(5)
changed_data = tf.reduce_sum(cell(X, state = tf.zeros((2, 5)))[0])
with tf.Session() as sess:
tf.global_variables_initializer().run()
output = sess.run(changed_data, feed_dict={X: np.ones((2, 3))})
print(output) # = 1.76918
Actually, you can add/delete/modify constant tensor declarations as much as you like, the result varies quite different!
What's the problem?
The initializers for variables are getting different op-level seeds because seeding is based on (1) the graph-level seed, and (2) the op id if an op-level seed is not explicitly set (a deterministic function of the previously created ops in the current graph). This prevents every variable from getting exactly the same initialization when a graph-level seed has been set. See get_seed for the implementation.
I am trying to write some custom TensorFlow functions in python (using tf.py_func) where I want to calculate both the results and the gradients in python. I'm using the gradient_override_map trick (for example from from https://gist.github.com/harpone/3453185b41d8d985356cbe5e57d67342 and How to make a custom activation function with only Python in Tensorflow?).
However, while the function in the forward direction gets a numpy array as an input, the function for the gradient gets Tensors. This is a problem, depending on when the function gets called, because there may not be a default session, and/or there may not be a feed_dict with all the required values yet (for example, in a tf.train optimizer).
How do I do a py_func where both the forward and backward functions get (and return) numpy arrays?
Sample code:
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
def sin_func(x):
return np.sin(x)
def sin_grad_func(op, grad):
x = op.inputs[0].eval()
grad = grad.eval() # <--- this is what I'd like to avoid
output_grad = np.cos(x) * grad
return tf.convert_to_tensor(output_grad)
def py_func(func, inp, Tout, stateful=True, name=None, grad_func=None):
grad_name = 'PyFuncGrad_' + str(np.random.randint(0, 1E+8))
tf.RegisterGradient(grad_name)(grad_func)
g = tf.get_default_graph()
with g.gradient_override_map({"PyFunc": grad_name}):
return tf.py_func(func, inp, Tout, stateful=stateful, name=name)
with tf.Session() as sess:
np_x = np.linspace(0, np.pi, num=1000, dtype=np.float32)
x = tf.constant(np_x)
y = py_func(sin_func,
[x],
[tf.float32],
name='np_sin',
grad_func=sin_grad_func)
y = y[0]
gr = tf.gradients(y, [x])
tf.global_variables_initializer().run()
plt.plot(y.eval())
plt.plot(gr[0].eval())
If you want to include arbitrary Python code in your gradient function, the easiest solution is to create another tf.py_func() inside sin_grad_func():
def sin_grad_func_impl(x, grad):
return np.cos(x) * grad
def sin_grad_func(op, grad):
return tf.py_func(sin_grad_func_impl, [x, grad], grad.dtype)
Here is a sample:
import numpy as np
import tensorflow as tf
from tensorflow.python.ops import rnn, rnn_cell
if __name__ == '__main__':
embs = tf.Variable(np.random.random((40,5)),dtype=tf.float32)
X = np.array(np.array(range(1,25)).reshape(4, 6))
x0 = tf.placeholder(tf.int32, [None, None])
x1 = tf.nn.embedding_lookup(embs, x0)
lstm = tf.nn.rnn_cell.BasicLSTMCell(5,state_is_tuple=True)
outputs, states = tf.nn.dynamic_rnn(lstm, x1, dtype=tf.float32,time_major = True)
cost = tf.reduce_mean(outputs[:,-1,:])
optimizer = tf.train.AdagradOptimizer(learning_rate=0.12).minimize(cost)
with tf.Session() as sess:
sess.run(tf.initialize_all_variables())
result3, opt = sess.run([outputs, optimizer],{x0:X})
I use just one slice of outputs which is outputs[:,-1,:] to get a cost function. When I run the code, I got the result
F ./tensorflow/core/framework/tensor.h:581] Check failed: new_num_elements == NumElements() (0 vs. 20)
How to fix this? It's just a sample. I met this problem when I implement a hierarchical LSTM in which the representations of sentences computed by a LSTM is feed into another LSTM.
I confirmed that this is a bug in TensorFlow 0.10. Upgrading to TensorFlow 0.11 will fix the problem.