Tensorflow: creating a matrix with variables as elements - python

In Tensorflow, I'm trying to create the following matrix:
A = [[a, 0], [0,b]]
Where a and b are the parameters I'm trying to solve for.
Here's what I have so far:
a = tf.Variable((1,), name="a", dtype = tf.float64)
b = tf.Variable((1,), name="b", dtype = tf.float64)
const = tf.constant(0,dtype = tf.float64, shape = (1,))
A0 = tf.transpose(tf.stack([a,const]))
A1 = tf.transpose(tf.stack([const,b]))
A = tf.stack([A0,A1])
However the shape of A ends up being (2,1,2) which is wrong (since A0 and B0 both have shapes (1,2))
Is there an easier way to create the matrix object A in Tensorflow, or does anyone know why the shape is getting messed up with what I'm doing?

Well you can create a single variable vector params = tf.Variable((2,), name="ab") and then multiply with the identity matrix tf.eye(2):
A = tf.matmul(tf.expand_dims(params,0), tf.eye(2))

tf.stack increases the rank of the tensor (creating a new axis) and combines them in the new axis. If you want to combine tensors along an existing axis, you should use tf.concat.
a = tf.Variable((1,), name="a", dtype = tf.float64)
b = tf.Variable((1,), name="b", dtype = tf.float64)
const = tf.constant(0,dtype = tf.float64, shape = (1,))
A0 = tf.stack([a, const], axis=1)
A1 = tf.stack([const, b], axis=1) # more clear than tf.transpose
A = tf.concat((A0, A1), axis=0)
A is now shape (2, 2).
To explain, each object is a rank-1 tensor with one element:
A = [1]
const = [0]
stacking gives:
tf.stack((A, const), axis=0) = [[1], [0]] # 2x1 matrix
concatenating gives:
tf.concat((A, const), axis=0) = [1, 0] # 2 vector

Related

TensorFlow - 3D tensor that gathers every Nth tensor from 2D tensor and strides 1

Suppose I have a 2D-Tensor T in [M, 1] e.g.
T = tf.expand_dims([A1,
B1,
C1,
A2,
B2,
C2], 1)
and I want to reshape it like so:
T_reshp = [[[A1], [A2]]
[[B1], [B2]]
[[C1], [C2]]]
I know M and N (the number of tensors in each group) in advance. Further, let t_reshp.shape[0] = M/N = P in the I have tried using tf.reshape
T_reshp = tf.reshape(T, [P, N, 1])
However, I end up with:
T_reshp = [[[A1], [B1]]
[[C1], [A2]]
[[B2], [C2]]]
Can I do this using some slicing or reshape operation?
You can reshape it to dimension [N,P,1] first then transpose the first and second axis:
tf.transpose(tf.reshape(T, [N, P, 1]), [1,0,2])
# ^^^^ switch the two dimensions here and then transpose
Example:
T = tf.expand_dims([1,2,3,4,5,6], 1)
sess = tf.Session()
T1 = tf.transpose(tf.reshape(T, [2,3,1]), [1,0,2])
sess.run(T1)
#array([[[1],
# [4]],
# [[2],
# [5]],
# [[3],
# [6]]], dtype=int32)

Extracting specific elements from a tensor in tensorflow

I'm using tensorflow on python
I have a data tensor of shape [?, 5, 37], and a idx tensor of shape [?, 5]
I'd like to extract elements from data and get an output of shape [?, 5] such that:
output[i][j] = data[i][j][idx[i, j]] for all i in range(?) and j in range(5)
It looks loke the tf.gather_nd() function is the closest to my needs, but I don't see how to use it it my case...
Thanks !
EDIT : I managed to do it with gather_nd as shown below, but is there a better option ? (it seems a bit heavy-handed)
nRows = tf.shape(length_label)[0] ==> ?
nCols = tf.constant(MAX_LENGTH_INPUT + 1, dtype=tf.int32) ==> 5
m1 = tf.reshape(tf.tile(tf.range(nCols), [nRows]),
shape=[nRows, nCols])
m2 = tf.transpose(tf.reshape(tf.tile(tf.range(nRows), [nCols]),
shape=[nCols, nRows]))
indices = tf.pack([m2, m1, idx], axis=-1)
# indices should be of shape [?, 5, 3] with indices[i,j]==[i,j,idx[i,j]]
output = tf.gather_nd(data, indices=indices)
I managed to do it with gather_nd as shown below
nRows = tf.shape(length_label)[0] # ==> ?
nCols = tf.constant(MAX_LENGTH_INPUT + 1, dtype=tf.int32) # ==> 5
m1 = tf.reshape(tf.tile(tf.range(nCols), [nRows]),
shape=[nRows, nCols])
m2 = tf.transpose(tf.reshape(tf.tile(tf.range(nRows), [nCols]),
shape=[nCols, nRows]))
indices = tf.pack([m2, m1, idx], axis=-1)
# indices should be of shape [?, 5, 3] with indices[i,j]==[i,j,idx[i,j]]
output = tf.gather_nd(data, indices=indices)

Can't broadcast input array from shape (3,1) into shape (3,)

import numpy as np
def qrhouse(A):
(m,n) = A.shape
R = A
V = np.zeros((m,n))
for k in range(0,min(m-1,n)):
x = R[k:m,k]
x.shape = (m-k,1)
v = x + np.sin(x[0])*np.linalg.norm(x.T)*np.eye(m-k,1)
V[k:m,k] = v
R[k:m,k:n] = R[k:m,k:n]-(2*v)*(np.transpose(v)*R[k:m,k:n])/(np.transpose(v)*v)
R = np.triu(R[0:n,0:n])
return V, R
A = np.array( [[1,1,2],[4,3,1],[1,6,6]] )
print qrhouse(A)
It's qr factorization code, but I don't know why error happens.
The value error happens in V[k:m,k] = v
value error :
could not broadcast input array from shape (3,1) into shape (3)
V[k:m,k] = v; v has shape (3,1), but the target is (3,). k:m is a 3 term slice; k is a scalar.
Try using v.ravel(). Or V[k:m,[k]].
But also understand why v has its shape.
Another solution that would work is V[k:m,k:k+1] = v.
k:k+1 is a 1 term slice, making the target shape (3,1).
This seems like a better solution since you do not have to modify the input array.
Other way to do it is by transpose:
V[k:m,k] = v.transpose()

Multi-dimensional gather in Tensorflow

The general solution to this question is being worked on in this github issue, but I was wondering if there are workarounds using tf.gather (or something else) to achieve array indexing using a multi-index. One solution I came up with was to broadcast multiply each index in the multi-idx with the cumulative product of the tensor shape, which produces indices suitable for indexing the flattened tensor:
import tensorflow as tf
import numpy as np
def __cumprod(l):
# Get the length and make a copy
ll = len(l)
l = [v for v in l]
# Reverse cumulative product
for i in range(ll-1):
l[ll-i-2] *= l[ll-i-1]
return l
def ravel_multi_index(tensor, multi_idx):
"""
Returns a tensor suitable for use as the index
on a gather operation on argument tensor.
"""
if not isinstance(tensor, (tf.Variable, tf.Tensor)):
raise TypeError('tensor should be a tf.Variable')
if not isinstance(multi_idx, list):
multi_idx = [multi_idx]
# Shape of the tensor in ints
shape = [i.value for i in tensor.get_shape()]
if len(shape) != len(multi_idx):
raise ValueError("Tensor rank is different "
"from the multi_idx length.")
# Work out the shape of each tensor in the multi_idx
idx_shape = [tuple(j.value for j in i.get_shape()) for i in multi_idx]
# Ensure that each multi_idx tensor is length 1
assert all(len(i) == 1 for i in idx_shape)
# Create a list of reshaped indices. New shape will be
# [1, 1, dim[0], 1] for the 3rd index in multi_idx
# for example.
reshaped_idx = [tf.reshape(idx, [1 if i !=j else dim[0]
for j in range(len(shape))])
for i, (idx, dim)
in enumerate(zip(multi_idx, idx_shape))]
# Figure out the base indices for each dimension
base = __cumprod(shape)
# Now multiply base indices by each reshaped index
# to produce the flat index
return (sum(b*s for b, s in zip(base[1:], reshaped_idx[:-1]))
+ reshaped_idx[-1])
# Shape and slice starts and sizes
shape = (Z, Y, X) = 4, 5, 6
Z0, Y0, X0 = 1, 1, 1
ZS, YS, XS = 3, 3, 4
# Numpy matrix and index
M = np.random.random(size=shape)
idx = [
np.arange(Z0, Z0+ZS).reshape(ZS,1,1),
np.arange(Y0, Y0+YS).reshape(1,YS,1),
np.arange(X0, X0+XS).reshape(1,1,XS),
]
# Tensorflow matrix and indices
TM = tf.Variable(M)
TF_flat_idx = ravel_multi_index(TM, [
tf.range(Z0, Z0+ZS),
tf.range(Y0, Y0+YS),
tf.range(X0, X0+XS)])
TF_data = tf.gather(tf.reshape(TM,[-1]), TF_flat_idx)
with tf.Session() as S:
S.run(tf.initialize_all_variables())
# Obtain data via flat indexing
data = S.run(TF_data)
# Check that it agrees with data obtained
# by numpy smart indexing
assert np.all(data == M[idx])
However, this only works on tensors of rank 3 due to this (current) limitation limiting broadcasts to tensors of rank 3.
At the moment I can only think of doing a chained gather, transpose, gather, transpose, gather, but this is unlikely to be efficient. e.g.
shape = (8, 9, 10)
A = tf.random_normal(shape)
data = tf.gather(tf.transpose(tf.gather(A, [1, 3]), [1,0,2]), ...)
Any ideas?
It sounds like you want gather_nd.

Numpy array and column extracted from a matrix, different shape

I'm trying to do an integration with numpy:
A = n.trapz(B,C)
but I have some issues with B and C shapes
B is a filled array inizialized with numpy zeros function
B=np.zeros((N,1))
C is a column extracted from a matrix, always inizialized with numpy:
C = D[:,0]
D = np.zeros((N,2))
the problem is that:
n.shape(B) # (N,1)
n.shape(C) # (N,)
how can I manage this?
Try
B = np.zeros(N)
np.trapz(B, C)
Also, you np.trapz accepts multi-dimensional arrays, so arrays of shape (N, 1) are ok; you just need to specify an axis to handle it properly.
B = np.zeros((N, 1))
C = D[:, 0]
np.trapz(B, C.reshape(N, 1), axis=1)

Categories

Resources