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)
Related
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.
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)>
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)>
There is a minimal example of an RNN in the Skflow documentation. The input data is a matrix with shape (4,5). Why is the data split according to the following function for input?:
def input_fn(X):
return tf.split(1, 5, X)
This function returns a list of 5 arrays with shape 4,1
[array([[ 2.],
[ 2.],
[ 3.],
[ 2.]], dtype=float32), array([[ 1.],
[ 2.],
[ 3.],
[ 4.]], dtype=float32), array([[ 2.],
[ 3.],
[ 1.],
[ 5.]], dtype=float32), array([[ 2.],
[ 4.],
[ 2.],
[ 4.]], dtype=float32), array([[ 3.],
[ 5.],
[ 1.],
[ 1.]], dtype=f
and, what is the difference/impact on the RNN between the above function, or defining the function like this? As both input functions run
def input_fn(X):
return tf.split(1, 1, X)
Which returns the following:
[[[ 1., 3., 3., 2., 1.],
[ 2., 3., 4., 5., 6.]]
Presented here:
testRNN(self):
random.seed(42)
import numpy as np
data = np.array(list([[2, 1, 2, 2, 3],
[2, 2, 3, 4, 5],
[3, 3, 1, 2, 1],
[2, 4, 5, 4, 1]]), dtype=np.float32)
# labels for classification
labels = np.array(list([1, 0, 1, 0]), dtype=np.float32)
# targets for regression
targets = np.array(list([10, 16, 10, 16]), dtype=np.float32)
test_data = np.array(list([[1, 3, 3, 2, 1], [2, 3, 4, 5, 6]]))
def input_fn(X):
return tf.split(1, 5, X)
# Classification
classifier = skflow.TensorFlowRNNClassifier(
rnn_size=2, cell_type='lstm', n_classes=2, input_op_fn=input_fn)
classifier.fit(data, labels)
classifier.weights_
classifier.bias_
predictions = classifier.predict(test_data)
self.assertAllClose(predictions, np.array([1, 0]))
Would it be possible to use numpy/scipy to multiply matrices composed of polynomials?
Specifically I wish to multiply a 120 by 120 sparse matrix who's entries can look like a+7*b+c by itself.
Honestly, I haven't tried very hard to do this. I see that there is a polynomial module in numpy but I have no experience with it. I am just hoping that someone sees this and says "obviously it's possible, do this".
There is one relevant question asked before from what I've seen: Matrices whose entries are polynomials
I don't know about sparse, but numpy object arrays work fine.
In [1]: from numpy.polynomial import Polynomial as P
In [2]: a = np.array([[P([1,2]), P([3,4])]]*2)
In [3]: a
Out[3]:
array([[Polynomial([ 1., 2.], [-1, 1], [-1, 1]),
Polynomial([ 3., 4.], [-1, 1], [-1, 1])],
[Polynomial([ 1., 2.], [-1, 1], [-1, 1]),
Polynomial([ 3., 4.], [-1, 1], [-1, 1])]], dtype=object)
In [4]: np.dot(a, a)
Out[4]:
array([[Polynomial([ 4., 14., 12.], [-1., 1.], [-1., 1.]),
Polynomial([ 12., 34., 24.], [-1., 1.], [-1., 1.])],
[Polynomial([ 4., 14., 12.], [-1., 1.], [-1., 1.]),
Polynomial([ 12., 34., 24.], [-1., 1.], [-1., 1.])]], dtype=object)