Let's say I have 2-dimensional tensor using tf.Variable
, [[10,9],[9,8]]
. So I can change it's value using index. In this case, I want to change 10 to 8, then I wrote this code, using assign function.
changeAbleTensor = tf.Variable([[10,9],[9,8]]);
changeAbleTensor[0][0].assign(10)
Code above, give me an error
AttributeError: 'tensorflow.python.framework.ops.EagerTensor' object has no attribute 'assign'
But, when I change my code from changeAbleTensor[0][0].assign(10)
to changeAbleTensor[0,0].assign(10)
the 10 is changed to 8 successfully.
I'm wondering about that behavior, cause when I check the type of variable that using [0][0]
and [0,0]
it shows the same type.
type(changeAbleTensor[0][0]), type(changeAbleTensor[0,0])
# result
# (tensorflow.python.framework.ops.EagerTensor,
# tensorflow.python.framework.ops.EagerTensor)
Can you tell me why we [0][0]
drive to error that said EagerTensor doesn't have assign attribute and on the other side [0,0]
has assign attribute even though both has the same type.
Thanks
CodePudding user response:
Just an assumption
Applying the slice operation on a tf.Variable
will return a Tensor
that inherits the method assign
of tf.Variable
. The problem is changeAbleTensor[0][0]
is first slicing a tf.Variable
and then slicing a tf.Tensor
and thus you appear to lose the context of the tf.Variable
. For example, when slicing once, both options have the same methods including assign
:
import tensorflow as tf
changeAbleTensor = tf.Variable([[1,9],[9,8]]);
print(dir(changeAbleTensor[0]))
print(dir(changeAbleTensor[0,0]))
['OVERLOADABLE_OPERATORS', '_USE_EQUALITY', '__abs__', '__add__', '__and__', '__array__', '__array_priority__', '__bool__', '__class__', '__complex__', '__copy__', '__deepcopy__', '__delattr__', '__dict__', '__dir__', '__div__', '__doc__', '__eq__', '__float__', '__floordiv__', '__format__', '__ge__', '__getattr__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__index__', '__init__', '__init_subclass__', '__int__', '__invert__', '__iter__', '__le__', '__len__', '__long__', '__lt__', '__matmul__', '__mod__', '__module__', '__mul__', '__ne__', '__neg__', '__new__', '__nonzero__', '__or__', '__pow__', '__radd__', '__rand__', '__rdiv__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rmatmul__', '__rmod__', '__rmul__', '__ror__', '__round__', '__rpow__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__tf_tracing_type__', '__truediv__', '__weakref__', '__xor__', '_add_consumer', '_as_node_def_input', '_as_tf_output', '_c_api_shape', '_copy', '_copy_nograd', '_copy_to_device', '_create_with_tf_output', '_datatype_enum', '_disallow_bool_casting', '_disallow_in_graph_mode', '_disallow_iteration', '_disallow_when_autograph_disabled', '_disallow_when_autograph_enabled', '_disallow_when_autograph_unavailable', '_handle_data', '_id', '_matmul', '_num_elements', '_numpy', '_numpy_internal', '_numpy_style_getitem', '_override_operator', '_prefer_custom_summarizer', '_rank', '_shape', '_shape_as_list', '_shape_tuple', '_summarize_value', '_tensor_shape', '_tf_api_names', '_tf_api_names_v1', '_with_index_add', '_with_index_max', '_with_index_min', '_with_index_update', 'assign', 'backing_device', 'consumers', 'cpu', 'device', 'dtype', 'eval', 'experimental_ref', 'get_shape', 'gpu', 'graph', 'is_packed', 'name', 'ndim', 'numpy', 'op', 'ref', 'set_shape', 'shape', 'value_index']
['OVERLOADABLE_OPERATORS', '_USE_EQUALITY', '__abs__', '__add__', '__and__', '__array__', '__array_priority__', '__bool__', '__class__', '__complex__', '__copy__', '__deepcopy__', '__delattr__', '__dict__', '__dir__', '__div__', '__doc__', '__eq__', '__float__', '__floordiv__', '__format__', '__ge__', '__getattr__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__index__', '__init__', '__init_subclass__', '__int__', '__invert__', '__iter__', '__le__', '__len__', '__long__', '__lt__', '__matmul__', '__mod__', '__module__', '__mul__', '__ne__', '__neg__', '__new__', '__nonzero__', '__or__', '__pow__', '__radd__', '__rand__', '__rdiv__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rmatmul__', '__rmod__', '__rmul__', '__ror__', '__round__', '__rpow__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__tf_tracing_type__', '__truediv__', '__weakref__', '__xor__', '_add_consumer', '_as_node_def_input', '_as_tf_output', '_c_api_shape', '_copy', '_copy_nograd', '_copy_to_device', '_create_with_tf_output', '_datatype_enum', '_disallow_bool_casting', '_disallow_in_graph_mode', '_disallow_iteration', '_disallow_when_autograph_disabled', '_disallow_when_autograph_enabled', '_disallow_when_autograph_unavailable', '_handle_data', '_id', '_matmul', '_num_elements', '_numpy', '_numpy_internal', '_numpy_style_getitem', '_override_operator', '_prefer_custom_summarizer', '_rank', '_shape', '_shape_as_list', '_shape_tuple', '_summarize_value', '_tensor_shape', '_tf_api_names', '_tf_api_names_v1', '_with_index_add', '_with_index_max', '_with_index_min', '_with_index_update', 'assign', 'backing_device', 'consumers', 'cpu', 'device', 'dtype', 'eval', 'experimental_ref', 'get_shape', 'gpu', 'graph', 'is_packed', 'name', 'ndim', 'numpy', 'op', 'ref', 'set_shape', 'shape', 'value_index']
whereas:
print(dir(changeAbleTensor[0][0]) == dir(changeAbleTensor[0,0]))
returns False
, since the assign
method is no longer there.