How to scan through tensor not at dimension 0? - python

The tensorflow document states that tf.scan scans on the list of tensors unpacked from elems on dimension 0.
The simplest version of scan repeatedly applies the callable fn to a sequence of elements from first to last. The elements are made of the tensors unpacked from elems on dimension 0.
My question is:
How to scan on the list of tensors on other dimension instead of dimension 0?
For example,
I have a tensor, ref, defined as below.
>>> ref = tf.Variable(tf.ones([2,3,3],tf.int32))
....
>>> print(ref.eval())
[[[1 1 1]
[1 1 1]
[1 1 1]]
[[1 1 1]
[1 1 1]
[1 1 1]]]
I want to scan through the ref[1,0], ref[1,1], ref[1,2] and apply a function to each of the, ,say add 1.
That is to say, I want ref be after the operation
>>> print(ref.eval())
[[[1 1 1]
[1 1 1]
[1 1 1]]
[[2 2 2]
[2 2 2]
[2 2 2]]]
Can I use tf.scan to do that? If yes, how?
If not, any how to do in other way?
Thanks.

You can tf.transpose() your tensor before the tf.scan() and transpose back after.
Also, if you want the variable ref to contain the new value after the operation, you need to tf.assign() the value back.
Please note your desired example value is achieved just by applying a straight-up scan, with no transpose, however. Refer to this code (tested) (see another example with transpose at the bottom of answer):
import tensorflow as tf
ref = tf.Variable(tf.ones([2,3,3],tf.int32))
ref2 = tf.scan( lambda y, x: x + 1, ref )
with tf.Session() as sess:
sess.run( tf.global_variables_initializer() )
print ( sess.run( ref2 ) ) # ref2 is calculated
print ( "====================")
print ( sess.run( ref ) ) # the original ref is unchanged
print ( "====================")
sess.run( tf.assign( ref, ref2 ) ) # assign the value back to ref
print ( sess.run( ref ) )
outputs:
[[[1 1 1]
[1 1 1]
[1 1 1]]
[[2 2 2]
[2 2 2]
[2 2 2]]]
====================
[[[1 1 1]
[1 1 1]
[1 1 1]]
[[1 1 1]
[1 1 1]
[1 1 1]]]
====================
[[[1 1 1]
[1 1 1]
[1 1 1]]
[[2 2 2]
[2 2 2]
[2 2 2]]]
If you use tf.transpose(), you can achieve a scan along any dimension:
import tensorflow as tf
ref = tf.Variable(tf.ones([2,3,3],tf.int32))
ref2 = tf.transpose( tf.scan( lambda y, x: x + 1,
tf.transpose( ref, [ 1, 0, 2 ] ) ),
[ 1, 0, 2 ] )
with tf.Session() as sess:
sess.run( tf.global_variables_initializer() )
sess.run( tf.assign( ref, ref2 ) )
print ( sess.run( ref ) )
will output:
[[[1 1 1]
[2 2 2]
[2 2 2]]
[[1 1 1]
[2 2 2]
[2 2 2]]]

Related

add field to memmaped numpy record array

With normal memmapped numpy arrays, you can "add" a new column by opening the memmap file with an additional column in the shape.
k = np.memmap('input', dtype='int32', shape=(10, 2), mode='r+', order='F')
k[:] = 1
l = np.memmap('input', dtype='int32', shape=(10, 3), mode='r+', order='F')
print(k)
print(l)
[[1 1]
[1 1]
[1 1]
[1 1]
[1 1]
[1 1]
[1 1]
[1 1]
[1 1]
[1 1]]
[[1 1 0]
[1 1 0]
[1 1 0]
[1 1 0]
[1 1 0]
[1 1 0]
[1 1 0]
[1 1 0]
[1 1 0]
[1 1 0]]
Is it possible to make a similar move with record arrays? Seems possible with rows, but can't find a way to do so with a new field, if the dtype has heterogeneous types.

how does numpy reshape work with negative variable as second parameter

I am trying to play with negative variable as second parameter
a = np.array([[1,2,3], [4,5,6]])
print(np.reshape(a, (3,-1)) )
print("___________________________________")
print(np.reshape(a, (3,-2)) )
print("___________________________________")
print(np.reshape(a, (3,-3)) )
print("___________________________________")
print(np.reshape(a, (3,2)) )
All the four types of reshaping above basically gives the same result as the output.
[[1 2]
[3 4]
[5 6]]
___________________________________
[[1 2]
[3 4]
[5 6]]
___________________________________
[[1 2]
[3 4]
[5 6]]
___________________________________
[[1 2]
[3 4]
[5 6]]
I am just trying to understand what is the difference between the above? Can -1 and 2 be used interchangeably?
The parameters to reshape can contain one unknown dimension which represented by a negative number, the value is inferred from the length of the array and remaining dimensions.
https://docs.scipy.org/doc/numpy/reference/generated/numpy.reshape.html#numpy.reshape
for example
a = np.array([[1,2,3, 4], [5,6,7,8]])
print(np.reshape(a, (-2)) )
print("___________________________________")
print(np.reshape(a, (2, 2,-2)) )
print("___________________________________")
print(np.reshape(a, (2, -1,-2)) )
Output
[1 2 3 4 5 6 7 8]
___________________________________
[[[1 2]
[3 4]]
[[5 6]
[7 8]]]
___________________________________
...
ValueError: can only specify one unknown dimension
Reshaping with a negative number is no magic. As stated in the answer above the number after the negative sign does not really matter.
Here is a function demonstrating how reshaping is done. Note that this is purely demonstrative, not an actual implementation taken from source code or anything like that.
def computeNegativeDim(arr):
givenDims = list(arr.shape)
knownDims = [d for d in givenDims if d > 0]
val = 1
for k in knownDims:
val *= k
dimOfPreviouslyUnknown = arr.size / val
for g in givenDims:
if g < 0:
g = dimOfPreviouslyUnknown
newarr = arr.reshape(givenDims)
Or somewhere along the above.

Numpy swap the values of nested columns

Given the following data structure is there some way I can swap the first and last column such that each row is [3, 2, 1] (I don't wish to sort them) without looping through each row?
[[[1 2 3]
[1 2 3]
[1 2 3]
...
[1 2 3]
[1 2 3]
[1 2 3]]
[[1 2 3]
[1 2 3]
[1 2 3]
...
[1 2 3]
[1 2 3]
[1 2 3]]]

Difference between `tf.reshape(a, [m, n])` and `tf.transpose(tf.reshape(a, [n, m]))`?

Actually, I'm doing the homework "Art Generation with Neural Style Transfer" of deeplearning.ai on coursera. In the function compute_layer_style_cost(a_S, a_G):
a_S = tf.reshape(a_S, [n_H*n_W, n_C])
a_G = tf.reshape(a_G, [n_H*n_W, n_C])
GS = gram_matrix(tf.transpose(a_S))
GG = gram_matrix(tf.transpose(a_G))
Why does this code give the right answer, however, the following doesn't:
a_S = tf.reshape(a_S, [n_C, n_H*n_W])
a_G = tf.reshape(a_G, [n_C, n_H*n_W])
GS = gram_matrix(a_S)
GG = gram_matrix(a_G)
Here's a trivial example that shows the difference between these two expressions:
import tensorflow as tf
tf.InteractiveSession()
x = tf.range(0, 6)
a = tf.reshape(x, [3, 2])
b = tf.transpose(tf.reshape(x, [2, 3]))
print(x.eval())
print(a.eval())
print(b.eval())
The result:
[0 1 2 3 4 5]
[[0 1]
[2 3]
[4 5]]
[[0 3]
[1 4]
[2 5]]
As you can notice, a and b are different, though have the same shape. That's because the first reshaping "splits" x into [0 1], [2 3] and [4 5], while the second reshaping into [0 1 2] and [3 4 5].

python: Find subsets coordinate is in

I have a set of coordinates and try to find those subsets the coordinate is in.
import numpy as np
a=np.array([[[0,1,1],[1,1,1]],[[0,1,1],[2,1,1]],[[3,3,3],[2,2,2]]])
If I try things like:
print(np.argwhere(a==[[0,1,1]]))
print(a[[0,1,1]])
print(np.isin([0,1,1],a))
I get:
[[0 0 0]
[0 0 1]
[0 0 2]
[0 1 1]
[0 1 2]
[1 0 0]
[1 0 1]
[1 0 2]
[1 1 1]
[1 1 2]]
[[[0 1 1]
[1 1 1]]
[[0 1 1]
[2 1 1]]
[[0 1 1]
[2 1 1]]]
[ True True True]
But I expect something like:
[true,true,false]
EDIT
The best case would be If I get an array where only all other coordinates which are members of the founded subsets are in like:
out = [[1,1,1],[2,1,1]]
Use all(-1) to assert the array equal at the last axis and then any(1) to check if such condition exists at the second axis:
(a == [0,1,1]).all(-1).any(1)
# array([ True, True, False], dtype=bool)
On the update:
mask = (a == [0,1,1]).all(-1)
a[mask.any(1)[:,None] & ~mask]
#array([[1, 1, 1],
# [2, 1, 1]])
I got the results you're looking for by doing this:
[[0,1,1] in b for b in a]
I'll try to figure out why isin didnt work.

Categories