'How can I change the values of a numpy array stored in a TensorFlow Variable Without Changing ANY other properties of the Tensor?

I want to change the weights of one layer of a neural net to a new set of known values. The current set of values is:

>>> import tensorflow as tf
...
>>> curr_layer.weights
<tf.Variable 'conv2d/kernel:0' shape=(4, 4, 1, 64) dtype=float32, numpy=
array([[[[ 0.02059445, -0.01320859, -0.00185177, ...,  0.02550568,
          -0.02180868,  0.00089696]], 
         ...

        [[-0.03411875, -0.00027762, -0.00894349, ...,  0.04085622,
           0.02792494, -0.02052956]]]], dtype=float32)>

For the sake of this example, I created a zero array with the same shape:

>>> silly = np.zeros([4,4,1,64])

However, when I use assign to transfer the values, the name of the graph node associated with the Tensor also changes:

>>> curr_layer.weights[0].assign(silly)
curr_layer.weights[0].assign(silly)
<tf.Variable 'UnreadVariable' shape=(4, 4, 1, 64) dtype=float32, numpy=
array([[[[0., 0., 0., ..., 0., 0., 0.]],
       ....
       [[0., 0., 0., ..., 0., 0., 0.]]]], dtype=float32)>

Where now 'conv2d/kernel:0' has become'Unread Variable'. How do I prevent this from happening? How do I change only the values associated with the tensor?



Solution 1:[1]

The name doesn't actually change:

a = tf.Variable(np.zeros((3, 4)), name='test')
a.name

prints test:0. And then

a.assign(np.zeros((3, 4)))
a.name

still prints test:0.

Solution 2:[2]

For a tf.Variable instance, the .assign method has a read_value argument that's True by default. If x is an arbitrary tf.Variable, then for a numpy array silly (of the same dimensions as x), you can do:

x.assign(silly, read_value=False)

This won't return anything, but it will change the tf.Variable instance, x in place.

For a toy example I adapted from the original post, doing the following:

silly = np.zeros([2,2])

x = tf.Variable([[1,0],[0,1]], dtype=tf.float32, name='test')

x.assign(silly, read_value=False)

x

resulted in:

<tf.Variable 'test:0' shape=(2, 2) dtype=float32, numpy=
array([[0., 0.],
       [0., 0.]], dtype=float32)>

Obviously not the same exact tensors involved in the original post, but the expected behavior is as desired.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 xdurch0
Solution 2 AndrewJaeyoung