Defining own pad in Tensorflow 2 - tensorflow

I am using a simple convolutional network, however, I need to use very specific paddings: I want to copy the nearest pixel value, something like this:
1 2 3
4 5 6
7 8 9
to
1 1 2 3 3
1 1 2 3 3
4 4 5 6 6
7 7 8 9 9
7 7 8 9 9
While I have no problem calculating the pad itself, I cannot use it in convolution. Is there a way to put these values into a tensorflow pad? Or I can modify the image, so it will contain the pad, but how can I set the convolution to handle the first and last rows and columns as padding?

You can simnply call tf.pad with symmetric mode before your call to conv2d, while specifying that the convolution should use the VALID padding mode:
>>> a = tf.reshape(tf.range(9),(3,3))
>>> a
<tf.Tensor: shape=(3, 3), dtype=float32, numpy=
array([[0., 1., 2.],
[3., 4., 5.],
[6., 7., 8.]], dtype=float32)>
>>> padded_a = tf.pad(a,[[1,1],[1,1]],"SYMMETRIC")
>>> padded_a
<tf.Tensor: shape=(5, 5), dtype=float32, numpy=
array([[0., 0., 1., 2., 2.],
[0., 0., 1., 2., 2.],
[3., 3., 4., 5., 5.],
[6., 6., 7., 8., 8.],
[6., 6., 7., 8., 8.]], dtype=float32)>
Now, if we create a simple 3x3 filter made of 1, we should have as result of the convolution the sum of the neighbouring elements (pad included), with the same shape as our original input:
>>> filters = tf.ones((3,3,1,1))
>>> conv_result = tf.nn.conv2d(padded_a[tf.newaxis,:,:,tf.newaxis], filters, padding="VALID", strides=1)
>>> tf.squeeze(conv_result) # just removing the batch and channel dimensions
<tf.Tensor: shape=(3, 3), dtype=float32, numpy=
array([[12., 18., 24.],
[30., 36., 42.],
[48., 54., 60.]], dtype=float32)>

Related

Transform sequential 2d array to time-windowed dataset

I have a 2d dataframe:
C1. C2. C3
0. 2. 3. 6
1. 8. 2. 1
2. 8. 6. 2
3. 4. 9. 0
4. 6. 7. 1
5. 2. 3. 0
I want it to be a 3d data with <num_windows, window_size, num_features>
So if window size is 5, the shape of the 3d data will be <2,5,3> and will be:
[[2,3,4],[8,2,1],[8,6,2],[4,9,0],[6,7,1]] , [[8,2,1],[8,6,2],[4,9,0],[6,7,1],[2,3,0]]
What is the best way to do it?
You can use sliding_window_view:
num_windows = 2
window_size = 5
num_features = 3
np.lib.stride_tricks.sliding_window_view(df, (window_size, num_features))[:num_windows,0,:,:]
gives a 3D array of shape (num_windows, window_size, num_features):
array([[[2., 3., 6.],
[8., 2., 1.],
[8., 6., 2.],
[4., 9., 0.],
[6., 7., 1.]],
[[8., 2., 1.],
[8., 6., 2.],
[4., 9., 0.],
[6., 7., 1.],
[2., 3., 0.]]])

Performing column & row operations in Tensorflow

Functions such as matrix multiplication perform column x row operations and then do a reduction operation. I want to do something similar, but I would like to replace the multiplication and addition operators with something else, such as max and min. I have something that works but it seems "ugly" at best.
# Setup
a = tf.reshape(tf.range(0.0, 8.0), [4, 2])
b = tf.reshape(tf.range(4.0, 12.0), [2, 4])
# Baseline
tf.matmul(a, b)
<tf.Tensor: shape=(4, 4), dtype=float32, numpy=
array([[ 8., 9., 10., 11.],
[ 32., 37., 42., 47.],
[ 56., 65., 74., 83.],
[ 80., 93., 106., 119.]], dtype=float32)>
# Can this part be done better?
a_b = tf.reshape(a, [4, 1, 2])
b_b = tf.reshape(tf.transpose(b), [1, 4, 2])
# The result is at least correct
tf.reduce_sum(a_b * b_b, -1)
<tf.Tensor: shape=(4, 4), dtype=float32, numpy=
array([[ 8., 9., 10., 11.],
[ 32., 37., 42., 47.],
[ 56., 65., 74., 83.],
[ 80., 93., 106., 119.]], dtype=float32)>
# And it can be extended to be generic
tf.reduce_min(tf.maximum(a_b, b_b), -1)
<tf.Tensor: shape=(4, 4), dtype=float32, numpy=
array([[4., 5., 6., 7.],
[4., 5., 6., 7.],
[4., 5., 6., 7.],
[6., 6., 6., 7.]], dtype=float32)>
As shown above, I have a workable solution, but I would expect a framework like tensorflow to have a more generic method to do this or at least a way to produce the intermediate tensor. The tf.meshgrid function seems to "almost" do what I want but the arguments are limited to rank 1 tensors.
Additionally, the above solution does not scale well. Some profiling indicates that the intermediate tensors are materialized, even in graph mode.

Selecting values from tensor based on an index tensor

I have two matrices. Matrix A is contains some values and matrix B contains indices. The shape of matrix A and B is (batch, values) and (batch, indices), respectively.
My goal is to select values from matrix A based on indices of matrix B along the batch dimension.
For example:
# Matrix A
<tf.Tensor: shape=(2, 5), dtype=float32, numpy=
array([[0., 1., 2., 3., 4.],
[5., 6., 7., 8., 9.]], dtype=float32)>
# Matrix B
<tf.Tensor: shape=(2, 2), dtype=int32, numpy=
array([[0, 1],
[1, 2]], dtype=int32)>
# Expected Result
<tf.Tensor: shape=(2, 2), dtype=float32, numpy=
array([[0., 1.],
[6., 7.]], dtype=int32)>
How can I achieve this in Tensorflow?
Many thanks in advance!
You can achieve this with the tf.gather function.
mat_a = tf.constant([[0., 1., 2., 3., 4.],
[5., 6., 7., 8., 9.]])
mat_b = tf.constant([[0, 1], [1, 2]])
out = tf.gather(mat_a, mat_b, batch_dims=1)
out.numpy()
array([[0., 1.],
[6., 7.]], dtype=float32)

Is this possible with tf.tensor_scatter_nd_add

A simple example of the following use of tf.tensor_scatter_nd_add is giving me problems.
B = tf.tensor_scatter_nd_add(A, indices, updates)
tensor A is (1,4,4)
A = [[[1. 1. 1. 1.],
[1. 1. 1. 1.],
[1. 1. 1. 1.],
[1. 1. 1. 1.]]]
the desired result is tensor B:
B = [[[1. 1. 1. 1.],
[1. 2. 3. 1.],
[1. 4. 5. 1.],
[1. 1. 1. 1.]]]
i.e. I want to add this smaller tensor to just the 4 inner elements of tensor A
updates = [[[1, 2],
[3, 4]]]
Tensorflow 2.1.0. I've tried a number of ways of constructing indices. The call to tensor_scatter_nd_add returns an error saying the inner dimensions don't match.
Do the updates tensor need to be the same shape as A?
Planaria,
Try passing indices and updates the following way: updates with shape (n), indices with shape (n,3) where n is number of changed items.
Indices should point to individual cells that you want to change:
A = tf.ones((1,4,4,), dtype=tf.dtypes.float32)
updates = tf.constant([1., 2., 3., 4])
indices = tf.constant([[0,1,1], [0,1,2], [0,2,1], [0,2,2]])
tf.tensor_scatter_nd_add(A, indices, updates)
<tf.Tensor: shape=(1, 4, 4), dtype=float32, numpy=
array([[[1., 1., 1., 1.],
[1., 2., 3., 1.],
[1., 4., 5., 1.],
[1., 1., 1., 1.]]], dtype=float32)>

numpy where condition output explained

Im trying to understand numpy where condition.
>>> import numpy as np
>>> x = np.arange(9.).reshape(3, 3)
>>> x
array([[ 0., 1., 2.],
[ 3., 4., 5.],
[ 6., 7., 8.]])
>>> np.where( x > 5 )
(array([2, 2, 2]), array([0, 1, 2]))
IN the above case, what does the output actually mean, array([0,1,2]) I actually see in the input what is array([2,2,2])
Th first array indicates the row number and the second array indicates the corresponding column number.
If the array is following:
array([[ 0., 1., 2.],
[ 3., 4., 5.],
[ 6., 7., 8.]])
Then the following
(array([2, 2, 2]), array([0, 1, 2]))
Can be interpreted as
array(2,0) => 6
array(2,1) => 7
array (2,2) => 8
You might also want to know where those values appear visually in your array. In such cases, you can return the array's value where the condition is True and a null value where they are false. In the example below, the value of x is returned at the position where x>5, otherwise assign -1.
x = np.arange(9.).reshape(3, 3)
np.where(x>5, x, -1)
array([[-1., -1., -1.],
[-1., -1., -1.],
[ 6., 7., 8.]])
Three elements found, located at (2,0),(2,1),(2,2)..
By the way, tryhelp(np.where()) will help you a lot.