Problem in computing the gradient of a function - tensorflow

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

tensorflow constrain the optimized tensor

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

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.

Why adding unusable tensors will change the result of an RNN cell in tensorflow?

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.

TensorFlow: how to do python function with custom gradients without eval?

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)

How should I fix that after I use a slice of a tensor, tensorflow optimizer will break?

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.