Broadcasting with ragged tensor - python

Define x as:
>>> import tensorflow as tf
>>> x = tf.constant([1, 2, 3])
Why does this normal tensor multiplication work fine with broacasting:
>>> tf.constant([[1, 2, 3], [4, 5, 6]]) * tf.expand_dims(x, axis=0)
<tf.Tensor: shape=(2, 3), dtype=int32, numpy=
array([[ 1, 4, 9],
[ 4, 10, 18]], dtype=int32)>
while this one with a ragged tensor does not?
>>> tf.ragged.constant([[1, 2, 3], [4, 5, 6]]) * tf.expand_dims(x, axis=0)
*** tensorflow.python.framework.errors_impl.InvalidArgumentError: Expected 'tf.Tensor(False, shape=(), dtype=bool)' to be true. Summarized data: b'Unable to broadcast: dimension size mismatch in dimension'
1
b'lengths='
3
b'dim_size='
3, 3
How can I get a 1-D tensor to broadcast over a 2-D ragged tensor? (I am using TensorFlow 2.1.)

The problem will be resolved if you add ragged_rank=0 to the Ragged Tensor, as shown below:
tf.ragged.constant([[1, 2, 3], [4, 5, 6]], ragged_rank=0) * tf.expand_dims(x, axis=0)
Complete working code is:
%tensorflow_version 2.x
import tensorflow as tf
x = tf.constant([1, 2, 3])
print(tf.ragged.constant([[1, 2, 3], [4, 5, 6]], ragged_rank=0) * tf.expand_dims(x, axis=0))
Output of the above code is:
tf.Tensor(
[[ 1 4 9]
[ 4 10 18]], shape=(2, 3), dtype=int32)
One more correction.
As per the definition of Broadcasting, Broadcasting is the process of **making** tensors with different shapes have compatible shapes for elementwise operations, there is no need to specify tf.expand_dims explicitly, Tensorflow will take care of it.
So, below code works and demonstrates the property of Broadcasting well:
%tensorflow_version 2.x
import tensorflow as tf
x = tf.constant([1, 2, 3])
print(tf.ragged.constant([[1, 2, 3], [4, 5, 6]], ragged_rank=0) * x)
Output of the above code is:
tf.Tensor(
[[ 1 4 9]
[ 4 10 18]], shape=(2, 3), dtype=int32)
For more information, please refer this link.
Hope this helps. Happy Learning!

Related

Tensorflow gives 0 results

I am learning Tensorflow from this github
https://colab.research.google.com/github/instillai/TensorFlow-Course/blob/master/codes/ipython/1-basics/tensors.ipynb#scrollTo=TKX2U0Imcm7d
Here is an easy tutorial
import numpy as np
import tensorflow as tf
x = tf.constant([[1, 1],
[1, 1]])
y = tf.constant([[2, 4],
[6, 8]])
# Add two tensors
print(tf.add(x, y), "\n")
# Add two tensors
print(tf.matmul(x, y), "\n")
What I expect is
tf.Tensor(
[[3 5]
[7 9]], shape=(2, 2), dtype=int32)
tf.Tensor(
[[ 8 12]
[ 8 12]], shape=(2, 2), dtype=int32)
However, the results are
Tensor("Add_3:0", shape=(2, 2), dtype=int32)
Tensor("MatMul_3:0", shape=(2, 2), dtype=int32)
It does not mean that the values of the tensors are zero. Add_3:0 and MatMul_3:0 are just names of the tensors and you can only use print in Eager Execution to see the values of the tensors. In Graph mode you should use tf.print and you should see the results:
import tensorflow as tf
x = tf.constant([[1, 1],
[1, 1]])
y = tf.constant([[2, 4],
[6, 8]])
print(tf.add(x, y), "\n")
print(tf.matmul(x, y), "\n")
# Graph mode
#tf.function
def calculate():
x = tf.constant([[1, 1],
[1, 1]])
y = tf.constant([[2, 4],
[6, 8]])
tf.print(tf.add(x, y), "\n")
tf.print(tf.matmul(x, y), "\n")
return x, y
_, _ = calculate()
tf.Tensor(
[[3 5]
[7 9]], shape=(2, 2), dtype=int32)
tf.Tensor(
[[ 8 12]
[ 8 12]], shape=(2, 2), dtype=int32)
[[3 5]
[7 9]]
[[8 12]
[8 12]]
Without tf.print, you will see the your output from the function calculate:
Tensor("Add:0", shape=(2, 2), dtype=int32)
Tensor("MatMul:0", shape=(2, 2), dtype=int32)
See this guide for more information.

Combine arbitrary shaped tensors

I'd like to combine two variable length tensors.
Since they don't match in shape I can't use tf.concat or tf.stack.
So I thought I'd flatten one and then append it to each element of the other - but I don't see how to do that.
For example,
a = [ [1,2], [3,4] ]
flat_b = [5, 6]
combine(a, flat_b) would be [ [ [1,5,6], [2,5,6] ],
[ [3,5,6], [4,5,6] ] ]
Is there a method like this?
Using tf.map_fn with tf.concat, Example code:
import tensorflow as tf
a = tf.constant([ [1,2], [3,4] ])
flat_b = [5, 6]
flat_a = tf.reshape(a, (tf.reduce_prod(a.shape).numpy(), ))[:, tf.newaxis]
print(flat_a)
c = tf.map_fn(fn=lambda t: tf.concat([t, flat_b], axis=0), elems=flat_a)
c = tf.reshape(c, (-1, a.shape[1], c.shape[1]))
print(c)
Outputs:
tf.Tensor(
[[1]
[2]
[3]
[4]], shape=(4, 1), dtype=int32)
tf.Tensor(
[[[1 5 6]
[2 5 6]]
[[3 5 6]
[4 5 6]]], shape=(2, 2, 3), dtype=int32)
Here's a somewhat simpler version of the previous answer. Rather than reshaping several times, I prefer to use tf.expand_dims and tf.stack. The latter adds a dimension so that's one less call to tf.reshape, which can be confusing.
import tensorflow as tf
a = tf.constant([[1,2], [3,4]])
b = [5, 6]
flat_a = tf.reshape(a, [-1])
c = tf.map_fn(lambda x: tf.concat([[x], b], axis=0), flat_a)
c = tf.stack(tf.split(c, num_or_size_splits=len(a)), axis=0)
<tf.Tensor: shape=(2, 2, 3), dtype=int32, numpy=
array([[[1, 5, 6],
[2, 5, 6]],
[[3, 5, 6],
[4, 5, 6]]])>
You could go through element-wise. In list form you would do something like out[i][j] = [a[i][j]]+flat_b starting from out being the same shape as a. This gets to the form you wanted. I'm not sure if there is this sort of element-wise concatenation in the tensorflow library.

Tensorflow difference between *pool2D and *pooling2D

I am learning this TensorFlow-2.x-Tutorials where it use layers.MaxPooling2D. The autocompletion also hint layers.MaxPool2D, so I search for the difference between them.
Refer to this api_docs, I find their entire name tf.compat.v1.layers.MaxPooling2D and tf.keras.layers.MaxPool2D, which have almost same arguments, can I just consider layers.MaxPooling2D = layers.MaxPool2D, but the former is to tf1.x, the latter is to tf2.x?
What's more, I also find tf.keras.layers.GlobalMaxPool1D(Global max pooling operation for 1D temporal data) and tf.keras.layers.GlobalAveragePooling1D(Global average pooling operation for temporal data), these two have exact the same arguments, why is the syntax of function name different?
I'm only going to answer your second question because someone found a duplicate for your first one.
MaxPooling2D takes the maximum value from a 2D array. Take for example this input:
import tensorflow as tf
x = tf.random.uniform(minval=0, maxval=10, dtype=tf.int32, shape=(3, 3, 3), seed=42)
<tf.Tensor: shape=(3, 3, 3), dtype=int32, numpy=
array([[[2, 4, 3],
[9, 1, 8],
[8, 3, 5]],
[[6, 6, 9],
[9, 6, 1],
[7, 5, 2]],
[[2, 0, 8],
[1, 6, 1],
[2, 3, 9]]])>
MaxPooling2D will take the average value of all of these three elements:
gmp = tf.keras.layers.GlobalMaxPooling2D()
gmp(x[..., None])
<tf.Tensor: shape=(3, 1), dtype=int32, numpy=
array([[9],
[9],
[9]])>
There's a 9 in every elements so the operation returns a 9 for all three. For GlobalAveragePooling2D, it's the exact same thing but with averaging.
gap = tf.keras.layers.GlobalAveragePooling2D()
gap(x[..., None])
<tf.Tensor: shape=(3, 1), dtype=int32, numpy=
array([[3],
[6],
[5]])>

Repeat_elements function to repeat columns of tensor

i've read documentation https://www.tensorflow.org/api_docs/python/tf/keras/backend/repeat_elements?hl=ID
>>> b = tf.constant([1, 2, 3])
>>> tf.keras.backend.repeat_elements(b, rep=2, axis=0)
<tf.Tensor: shape=(6,), dtype=int32,
numpy=array([1, 1, 2, 2, 3, 3], dtype=int32)>
the problem is the result is not what i expected
the result i really want is
<tf.Tensor: shape=(6,), dtype=int32,
numpy=array([1, 2, 3, 1, 2, 3], dtype=int32)>
how to do this ?
I think you are looking for tf.tile e.g.
import tensorflow as tf
a = tf.constant([1, 2, 3])
b = tf.tile(a, [2])
print(b)
will print
tf.Tensor([1 2 3 1 2 3], shape=(6,), dtype=int32)
(or if you really want to go down the tf.keras.backend route then the same thing but with tf.keras.backend.tile(a, [2]))

How to pick selected rows from a tensor, regardless of dimension?

I have a tensor (tensorflow.Tensor) A, and I would like to form a new tensor containing certain rows from A, that is, A[i,:,:,...,:] for selected values of i.
Problem is I don't know before-hand how many axes A has. So how can I write this operation?
This is exactly what tf.gather() is for. See the example code below:
x = tf.reshape(tf.constant([1, 2, 3, 4, 5, 6, 7, 8]), [2, 2, 2])
# This is using tf.gather() on a 3D tensor.
print(tf.gather(x, [1]))
The result is:
<tf.Tensor: shape=(1, 2, 2), dtype=int32, numpy=
array([[[5, 6],
[7, 8]]], dtype=int32)>
x = tf.reshape(tf.constant([1, 2, 3, 4, 5, 6, 7, 8]), [2, 4])
# This is using tf.gather() on a 2D tensor.
print(tf.gather(x, [1]))
The result is:
tf.Tensor([[5 6 7 8]], shape=(1, 4), dtype=int32)

Categories