Tensorflow argmax along multiple dimensions - python

I'm newbie to tensorflow and I'm trying to get the index of the maximum value in a Tensor. Here is the code:
def select(input_layer):
shape = input_layer.get_shape().as_list()
rel = tf.nn.relu(input_layer)
print (rel)
redu = tf.reduce_sum(rel,3)
print (redu)
location2 = tf.argmax(redu, 1)
print (location2)
sess = tf.InteractiveSession()
I = tf.random_uniform([32, 3, 3, 5], minval = -541, maxval = 23, dtype = tf.float32)
matI, matO = sess.run([I, select(I, 3)])
print(matI, matO)
Here is the output:
Tensor("Relu:0", shape=(32, 3, 3, 5), dtype=float32)
Tensor("Sum:0", shape=(32, 3, 3), dtype=float32)
Tensor("ArgMax:0", shape=(32, 3), dtype=int64)
...
Because of dimension=1 in the argmax function the shape of Tensor("ArgMax:0") = (32,3). Is there any way to get a argmax output tensor size = (32,) without doing reshape before applying the argmax?

You problably don't want an output of size (32,) because when you argmax along several directions, you usually want to have the coordinates of the max for all the reduced dimensions. In your case, you would want to have an output of size (32,2).
You can do a two-dimensional argmax like this:
import numpy as np
import tensorflow as tf
x = np.zeros((10,9,8))
# pick a random position for each batch image that we set to 1
pos = np.stack([np.random.randint(9,size=10), np.random.randint(8,size=10)])
posext = np.concatenate([np.expand_dims([i for i in range(10)], axis=0), pos])
x[tuple(posext)] = 1
a = tf.argmax(tf.reshape(x, [10, -1]), axis=1)
pos2 = tf.stack([a // 8, tf.mod(a, 8)]) # recovered positions, one per batch image
sess = tf.InteractiveSession()
# check that the recovered positions are as expected
assert (pos == pos2.eval()).all(), "it did not work"

Related

ValueError: could not broadcast input array from shape (2,5,2) into shape (5,2)

A n-dimensional array which is initialised as
features=np.empty(shape=(100,5,2), dtype=float)
and I am trying to add 3D array into it as
features[i,:] = features_next
features_next has shape (2,5,2).
However, it shows error,
ValueError: could not broadcast input array from shape (2,5,2) into shape (5,2).
here is the piece of code :
features=np.empty(shape=((historical*2),5,2), dtype=float)
i = 0
while i < 50:
state = self.getDictState(state_index)
asks = state['asks']
bids = state['bids']
features_next = self.getNormalisedFeature(
bids=bids,
asks=asks,
state_index=state_index,
qty=qty,
price=price,
size=size,
normalize=normalize,
levels=levels
)
'''if i == 0:
features = np.array(features_next)
else:
features = np.vstack((features, features_next))'''
features[i,:] = features_next
state_index = (state_index - 1)
return features
Note : I am trying to replace commented 'if condition' with features[i,:] = features_next to make the code execution bit faster.
Its pretty simple, just one point to make features[i,:] has shape (5, 2) and feature_next has shape (2, 5, 2). I want to say that both are compatible shapes. But broadcasting is done on a smaller shape over a larger shape. SO there is error since you are doing revere. Also look up on broadcasting on numpy docs.
Next, this one I think will do
This does not directly solve your problem, but has some ideas about what you can try, like you can reshape your array before going in loop using features.shape = (50, 2, 5, 2).
import numpy as np
features=np.empty(shape=(100,5,2), dtype=float)
features_next = np.random.random((2, 5, 2))
features.shape = ((50, 2, 5, 2))
features[:] = features_next
features.shape = (100, 5, 2)

How to get the cross contract matrix from two 2-dim tensors in tensorflow?

import tensorflow as tf
with tf.Session() as sess:
with tf.variable_scope('masssdsms'):
a = tf.get_variable('a', [1000,24,128], dtype=tf.float32, initializer=tf.random_normal_initializer(stddev=0.1) )
b = tf.get_variable('b', [1000,15,128], dtype=tf.float32, initializer=tf.random_normal_initializer(stddev=0.1) )
I want to get a new tensor named c from a and b.
1000 is the batch size, and c's shape should be (1000,20, 10, 1). For every instance from a and b: ai and bi, they are both two dimensional tensors.
The new instance ci is the result of ai and bi and it has 20 * 10 = 200 elements, that every element is the dot product of ai and bi with 128 dimension respectively. So there are 200 dot products results in sum. The ci is more like a 2-D image.
How can I initialize this operation?
Modified:
When I take the codes in usage, the operation of dot product should be replaced with some other function like guassian distance, or cosine distance etc, which is contact notation in the graph.
So I need to a common method to do this.
Here is what I design, but I am not sure whether it is a efficient way to do this:
with tf.Session() as sess:
with tf.variable_scope('masssdsms'):
a = tf.get_variable('a', [1000,24,128], dtype=tf.float32, initializer=tf.random_normal_initializer(stddev=0.1) )
b = tf.get_variable('b', [1000,15,128], dtype=tf.float32, initializer=tf.random_normal_initializer(stddev=0.1) )
i = 999 # for i in range(1000):
ai = tf.slice(a,[i,0,0],[1,-1,-1]) # (1,24,128)
bi = tf.slice(b,[i,0,0],[1,-1,-1]) # (1,15,128)
ci = contact_func(ai,bi) # (1,24,15)
You can achieve that with clever application of broadcasting. Try this:
a = tf.ones([1000, 20, 128])
b = tf.ones([1000, 10, 128])
a = tf.expand_dims(a, axis=1) # [1000, 1, 20, 128]
b = tf.expand_dims(b, axis=2) # [1000, 10, 1, 128]
products = a * b # [1000, 10, 20, 128]
reduced = tf.reduce_sum(products, axis=-1) # [1000, 10, 20]
The products contains all pairwise multiplications of all items in a and b. And the reduced aggregates the sum over the last axis.
Doing a matmul of the matrix a with the transpose of the dimension-1 of b should give the desired result:
c = tf.matmul(a, tf.transpose(b, [0, 2, 1])) # [1000, 20, 10]
# to get (1000, 20, 10, 1) you do
tf.expand_dims(c, 3)
EDIT:
For the contact_func operation, you may need to manually do the broadcasting using tile operator. Here is the code for gaussian distance:
# use tile to repeat the rows
d = tf.reshape(tf.tile(a, [1, 1, b.shape[1]]), (-1,a.shape[1]*b.shape[1],a.shape[2]))
#[1000, 360, 128],
# repeat the columns
e = tf.tile(b, [1, a.shape[1], 1])
#[1000, 360, 128]
# exp(-d_i_j), where d_i_j is the eucludian distance of i, j
c = tf.reshape(tf.exp(tf.reduce_sum(d-e, 2)), (-1, a.shape[1], b.shape[1]))
#[1000, 24, 15]

Keras: how to access specific index for multiplication

I am building a function that multiplies input from one model branch in a particular way with inputs from another model branch, but accessing specific parts of the tensors isn't doing what I expect.
Minimal example: Imagine we get two tensors, one of which contains [1, 2] and the other [10, 20, 30] and one of the outputs should be [1] x [10, 20, 30] by taking the first value of the first tensor.
If I start by making variables like this:
import keras.backend as K
import numpy as np
from keras.layers import Multiply
x = K.variable(value=np.array([1,2]))
y = K.variable(value=np.array([[10,20,30]]))
Then I can access x[0] easily enough:
print(K.eval(x[0]))
gives: 1.0
But it seems like that same indexing doesn't work for Multiply, as this code:
z = Multiply()([x[0], y])
Generates:
IndexError: tuple index out of range
Thus the question: how can I access specific value indexes within a Multiply layer in keras (or how else can I do the equivalent)?
Just to show you an example of how one could achieve what you want. Let's assume that we have two inputs:
input_1 = Input(shape=(2,))
input_2 = Input(shape=(3,))
Now - let's define the following function:
def custom_multiply(list_):
x, y = list_[0], list_[1]
y = K.reshape(y, (-1, 1, 3)) # (1, 2, 3) -> ((1), (2), (3))
x = K.reshape(x, (-1, 2, 1)) # (1, 2) -> ((1, 2))
partial_result = K.batch_dot(x, y)
return K.reshape(partial_result, (-1, 6))
Now - output = custom_multiply([input_1, input_2]) should do what you've expected. Called on a pair [(1, 2), (3, 4, 5)] should return (3, 4, 5, 6, 8, 10).

How to control dimension broadcast in tensorflow?

I would like to center my set of rows with several means and get several sets of centered rows.
My data has shape of (4, 3) i.e. four 3D vectors:
data = tf.get_variable("myvar1", shape=[4, 3], dtype=tf.float64)
I have two centers (two 3D vectors):
mu = tf.get_variable("mu", initializer=tf.constant(np.arange(2*3).reshape(2, 3), dtype=tf.float64))
I would like to center data once per each mu. In numpy I would write loop:
data = np.arange(4 * 3).reshape(4, 3)
mu = np.arange(2*3).reshape(2, 3)
centered_data = np.empty((2, 4, 3))
for i_data in range(len(data)):
for i_mu in range(len(mu)):
centered = data[i_data] - mu[i_mu]
centered_data[i_mu, i_data, :] = centered
How to do the same in tensorflow?
Bulk method for numpy would also be appreciated!
Apparently I can insert singular dimension to provoke broadcasting:
data = tf.get_variable("myvar1", shape=[4, 3], dtype=tf.float64)
mu = tf.get_variable("mu", initializer=tf.constant(np.arange(2*3).reshape(2, 3), dtype=tf.float64))
centered_data = data - tf.expand_dims(mu, axis=1)
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
ans_value, centered_data_value, mu_value = sess.run([centered_data, data, mu], {data: np.arange(4 * 3).reshape(4, 3)})
print("centered_data_value: ", centered_data_value)
print("mu: ", mu_value)
print("ans: ", ans_value)
The same is in numpy:
mu = np.reshape(mu, (2, 1, 3))
centered_data = data - mu
You only need to use - or tf.substract it will do element wise operation then:
centered_data = tf.substract(data, mu)

tensorflow: slicing a tensor along the second dimension

I have a tensor X whose shape is (None, 56, 300, 1), and another tensor y whose shape is (None, 15), the first dimension of these tensors is batch_size, I wanna use y as index to get a tensor z, the shape of z is (None, 15, 300, 1). Is there any decent way to do this?
I write a simple code to test, for I found it's difficult for me because in practice I don't know the batch_size(first dimension of these tensors is None),
Here is my test code:
import numpy as np
import tensorflow as tf
# In this test code , batch_size is 4.
# params' shape is (4, 3, 2 ,1), in practice is (None, 56, 300, 1),
params = [
[[['a0'], ['b0']], [['d0'], ['e0']], [['f0'], ['g0']]],
[[['a1'], ['b1']], [['d1'], ['e1']], [['f1'], ['g1']]],
[[['a2'], ['b2']], [['d2'], ['e2']], [['f2'], ['g2']]],
[[['a3'], ['b3']], [['d3'], ['e3']], [['f3'], ['g3']]],
]
# ind's shape is (4, 2) (In practice is (None, 15)),
# so I wanna get output whose's shape is (4, 2, 2, 1), (In practice is (None, 15, 300, 1))
ind = [[1, 0], [0, 2], [2, 0], [2, 1]]
#ouput = [
# [[['d0'], ['e0']], [['a0'], ['b0']]],
# [[['a1'], ['b1']], [['f1'], ['g1']]],
# [[['f2'], ['g2']], [['a2'], ['b2']]],
# [[['f3'], ['g3']], [['d3'], ['e3']]]
#]
with tf.variable_scope('gather') as scope:
tf_par = tf.constant(params)
tf_ind = tf.constant(ind)
res = tf.gather_nd(tf_par, tf_ind)
with tf.Session() as sess:
init = tf.global_variables_initializer()
print sess.run(res)
print res
To slice x along the second dimension with ind, that is, to slice
tensor x of shape (d0, d1, d2,...), d0 being possibly None,
with a tensor of indices ind of shape (d0, n1),
to obtain a tensor y of shape (d0, n1, d2, ...),
you could use tf.gather_nd along with tf.shape to get the shape at run time:
ind_shape = tf.shape(ind)
ndind = tf.stack([tf.tile(tf.range(ind_shape[0])[:, None], [1, ind_shape[1]]),
ind], axis=-1)
y = tf.gather_nd(x, ndind)
For results you suppose, you should use:
ind = [[0, 1], [0, 0], [1, 0], [1, 2], [2, 2], [2, 0], [3, 2], [3, 1]]
Update
You can use this code for get what you want, with current input:
with tf.variable_scope('gather') as scope:
tf_par = tf.constant(params)
tf_ind = tf.constant(ind)
tf_par_shape = tf.shape(tf_par)
tf_ind_shape = tf.shape(tf_ind)
tf_r = tf.div(tf.range(0, tf_ind_shape[0] * tf_ind_shape[1]), tf_ind_shape[1])
tf_r = tf.expand_dims(tf_r, 1)
tf_ind = tf.expand_dims(tf.reshape(tf_ind, shape = [-1]), 1)
tf_ind = tf.concat([tf_r, tf_ind], axis=1)
res = tf.gather_nd(tf_par, tf_ind)
res = tf.reshape(res, shape = (-1, tf_ind_shape[1], tf_par_shape[2], tf_par_shape[3]))

Categories