Creating 1D vectors over 3D tensors in pytorch - matrix

I have the following tensor with dimensions (2, 3, 2, 2) where the dimensions represent (batch_size, channels, height, width):
tensor([[[[ 1., 2.],
[ 3., 4.]],
[[ 5., 6.],
[ 7., 8.]],
[[ 9., 10.],
[11., 12.]]],
[[[13., 14.],
[15., 16.]],
[[17., 18.],
[19., 20.]],
[[21., 22.],
[23., 24.]]]])
I would like to convert this into the following tensor with dimensions (8, 3):
tensor([[ 1, 5, 9],
[ 2, 6, 10],
[ 3, 7, 11],
[ 4, 8, 12],
[13, 17, 21],
[14, 18, 22],
[15, 19, 23],
[16, 20, 24]])
Essentially I would like to create 1D vector over the elements of the matrices. I have tried many operations such as flatten and reshape, but I cannot figure out how to achieve this reshaping.

You can do it this way:
import torch
x = torch.Tensor(
[
[
[[1,2],[3,4]],
[[5,6],[7,8]],
[[9,10],[11,12]]],
[
[[13,14],[15,16]],
[[17,18],[19,20]],
[[21,22],[23,24]]]
]
)
result = x.swapaxes(0, 1).reshape(3, -1).T
print(result)
# > tensor([[ 1., 5., 9.],
# > [ 2., 6., 10.],
# > [ 3., 7., 11.],
# > [ 4., 8., 12.],
# > [13., 17., 21.],
# > [14., 18., 22.],
# > [15., 19., 23.],
# > [16., 20., 24.]])

You could achieve this with an axes permutation and a flattening the resulting tensor:
swap axis=1 (of size 3) with the last one: axis=-1, using torch.permute (torch.swapaxes is an alias),
flatten everything but the last axis i.e. from axis=0 to axis=-2 using torch.flatten.
This looks like:
>>> x.transpose(1, -1).flatten(0, -2)
tensor([[ 1., 5., 9.],
[ 3., 7., 11.],
[ 2., 6., 10.],
[ 4., 8., 12.],
[13., 17., 21.],
[15., 19., 23.],
[14., 18., 22.],
[16., 20., 24.]])

Related

I need to convert a 3 column array into a square matrix?

I am looking to convert my data to a square matrix:
Say your input is a list; you can then convert it to a list of lists (i.e., a proxy to a matrix) with list comprehension:
>>> x = [0, 5, 10, 5, 0, 2, 10, 2, 0]
>>> [x[3*k:3*k+3] for k in range(3)]
[[0, 5, 10], [5, 0, 2], [10, 2, 0]]
To help you parse the line: you are building a list by iterating over k from 0 to 2, where each element will be a slice of x that starts from index 3*k and ends at index 3*k+3. Thus, your list is [x[0:3], x[3:6], x[6:9]].
That said, it's much better to use numpy for all such needs. There, you would do:
>>> import numpy as np
>>> x = np.array([0, 5, 10, 5, 0, 2, 10, 2, 0])
>>> x.reshape(3, 3)
array([[ 0, 5, 10],
[ 5, 0, 2],
[10, 2, 0]])
The reshape() function converts your 1D array into the requested 2D matrix.

How to calculate output of Keras UpSampling2D Layer?

I don't understand how the output of the Upsampling2d layer in Keras is calculated.
Let's take an example:
img_input = Input((2,2, 1))
out = UpSampling2D(size=2, interpolation="bilinear")(img_input)
model = Model(img_input, out, name='test')
input = np.array([[100, 200], [6, 8]]).reshape(1, 2, 2, 1)
model.predict(input).reshape(4, 4)
The result of this is:
array([[100. , 150. , 200. , 200. ],
[ 53. , 78.5, 104. , 104. ],
[ 6. , 7. , 8. , 8. ],
[ 6. , 7. , 8. , 8. ]], dtype=float32)
For me bilinear interpolation would get s.th. different. Let's take the 150 in the first row. For me this should be actually 100*(2/3) + 200*(1/3) = 133.33. What is different in this layer?
Thanks!
Given your input array, these are the steps to apply the bilinear upsampling of size=2:
# input array
[[100, 200],
[ 6, 8]]
# double the size and fill with existing values spreading them evenly.
# Important! the edges of the array are not filled:
[[100, _, 200, _],
[ _, _, _, _],
[ 6, _, 8, _],
[ _, _, _, _]]
# Start filling the empty spaces sequentially by applying this rule:
# Empty spaces surrounded by one or more filled values are filled with the
# arithmetic average of these values.
# We would fill the entire array in two steps:
# 1. The first step would look like this:
[[100, 150, 200, 200],
[ 53, _, 104, _],
[ 6, 7, 8, 8],
[ 6, _, 8, _]]
# 2. The second step would look like this:
[[100, 150, 200, 200],
[ 53,78.5, 104, 104],
[ 6, 7, 8, 8],
[ 6, 7, 8, 8]]
If you would rather get [100, 133, 166, 200] in the first row (and the rest of the array filled accordingly), you should produce an upsampling of size=3 and then remove the edges (res[1:5, 1:5]):
img_input = Input((2,2, 1))
out = UpSampling2D(size=3, interpolation="bilinear")(img_input)
model = Model(img_input, out, name='test')
input = np.array([[100, 200], [6, 8]]).reshape(1, 2, 2, 1)
model.predict(input).reshape(6, 6)[1:5, 1:5]
>> array([[100. , 133.33334 , 166.66667 , 200. ],
[ 68.666664 , 91.111115 , 113.55555 , 136. ],
[ 37.333324 , 48.888878 , 60.444427 , 71.999985 ],
[ 6. , 6.666667 , 7.3333335, 8. ]],
dtype=float32)

Creating a slice of a matrix from a vector in Numpy

Provided that I have a matrix A of size 5 by 4, also a vector b of length 5 whose element indicates how many values I need in the corresponding row of matrix A. That means each value in b is upper-bounded by the size of second dimension of A. My problem is how to make a slice of a matrix given an vector, which is a complex-version of taking an integer-valued elements of a vector by writing vector[:n]
For example, this can be implemented with a loop over A's rows:
import numpy
A=numpy.arange(20).reshape((5,4))
b=numpy.array([0, 3, 3, 2, 3])
output=A[0, :b[0]]
for i in xrange(1, A.shape[0]):
output=numpy.concatenate((output, A[i, :b[i]]), axis=0)
# output is array([ 4, 5, 6, 8, 9, 10, 12, 13, 16, 17, 18])
The computation efficiency of this loop can be fairly low when dealing with a very large array. Furthermore, my purpose is to apply this in Theano eventually without a scan operation. I want to avoid using a loop to make a slice given an vector.
Another good setup for using NumPy broadcasting!
A[b[:,None] > np.arange(A.shape[1])]
Sample run
1) Inputs :
In [16]: A
Out[16]:
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15],
[16, 17, 18, 19]])
In [17]: b
Out[17]: array([0, 3, 3, 2, 3])
2) Use broadcasting to create mask for selection :
In [18]: b[:,None] > np.arange(A.shape[1])
Out[18]:
array([[False, False, False, False],
[ True, True, True, False],
[ True, True, True, False],
[ True, True, False, False],
[ True, True, True, False]], dtype=bool)
3) Finally use boolean-indexing for selecting elems off A :
In [19]: A[b[:,None] > np.arange(A.shape[1])]
Out[19]: array([ 4, 5, 6, 8, 9, 10, 12, 13, 16, 17, 18])
You could speed up the loop by collecting values in a list, and doing just one concatenate:
In [126]: [A[i,:j] for i,j in enumerate(b)]
Out[126]:
[array([], dtype=int32),
array([4, 5, 6]),
array([ 8, 9, 10]),
array([12, 13]),
array([16, 17, 18])]
In [127]: np.concatenate([A[i,:j] for i,j in enumerate(b)])
Out[127]: array([ 4, 5, 6, 8, 9, 10, 12, 13, 16, 17, 18])

How to sum two matrices?

how to write a method that accepts two square matrices (nxn two dimensional arrays), and return the sum of the two. Both matrices being passed into the method will be of size nxn (square), containing only integers.
How to sum two matrices:
Take each cell [n][m] from the first matrix, and add it with the [n][m] cell from the second matrix. This will be cell [n][m] in the solution matrix.
like:
|1 2 3|
|3 2 1|
|1 1 1|
+
|2 2 1|
|3 2 3|
|1 1 3|
=
|3 4 4|
|6 4 4|
|2 2 4|
matrix_addition( [ [1, 2, 3], [3, 2, 1,], [1, 1, 1] ], [ [2, 2, 1], [3, 2, 3], [1, 1, 3] ] )
returns [ [3, 4, 4], [6, 4, 4], [2, 2, 4] ]
Even though it is possible to define method to do so, it is much easier to use ruby build in Matrix library for this:
require 'matrix'
m1 = Matrix[ [1, 2, 3], [3, 2, 1], [1, 1, 1] ]
m2 = Matrix[ [2, 2, 1], [3, 2, 3], [1, 1, 3] ]
sum = m1 + m2
Yes, certainly, use the Matrix class methods, but here is a way using recursion that might be of interest.
Code
def sum_arrays(a1, a2)
t = a1.zip(a2)
t.map { |e1,e2| (e1.is_a? Array) ? sum_arrays(e1,e2) : e1+e2 }
end
Examples
a1 = [1,2,3]
a2 = [4,5,6]
sum_arrays(a1, a2)
#=> [5, 7, 9]
a1 = [[1,2,3], [4,5]]
a2 = [[6,7,8], [9,10]]
sum_arrays(a1, a2)
#=> [[7, 9, 11], [13, 15]]
a1 = [[[ 1, 2, 3], [ 4, 5]],
[[ 6, 7], [ 8, 9, 10]]]
a2 = [[[11, 12, 13], [14, 15]],
[[16, 17], [18, 19, 20]]]
sum_arrays(a1, a2)
#=> [[[12, 14, 16], [18, 20]],
# [[22, 24], [26, 28, 30]]]
Generalization
You could make greater use of this method by passing an operator.
Code
def op_arrays(a1, a2, op)
t = a1.zip(a2)
t.map { |e1,e2| (e1.is_a? Array) ? op_arrays(e1,e2,op) : e1.send(op,e2) }
end
Examples
a1 = [[1,2,3], [4,5]]
a2 = [[6,7,8], [9,10]]
op_arrays(a1, a2, '+') #=> [[7, 9, 11], [13, 15]]
op_arrays(a1, a2, '-') #=> [[-5, -5, -5], [-5, -5]]
op_arrays(a1, a2, '*') #=> [[6, 14, 24], [36, 50]]
You could alternatively pass the operator as a symbol:
op_arrays(a1, a2, :+)
#=> [[7, 9, 11], [13, 15]]
Have you used ruby Matrix class?
It has #+ operator (mimic method).

Populate array from vector

I would like to populate an 2 dimensional array, from a vector.
I think the best way to explain myself is to put some examples (with a array of [3,5] length).
When vector is: [1, 0]
[
[4, 3, 2, 1, 0],
[4, 3, 2, 1, 0],
[4, 3, 2, 1, 0]
]
When vector is: [-1, 0]
[
[0, 1, 2, 3, 4],
[0, 1, 2, 3, 4],
[0, 1, 2, 3, 4]
]
When vector is: [-2, 0]
[
[0, 0, 1, 1, 2],
[0, 0, 1, 1, 2],
[0, 0, 1, 1, 2]
]
When vector is: [1, 1]
[
[2, 2, 2, 1, 0],
[1, 1, 1, 1, 0],
[0, 0, 0, 0, 0]
]
When vector is: [0, 1]
[
[2, 2, 2, 2, 2],
[1, 1, 1, 1, 1],
[0, 0, 0, 0, 0]
]
Have you got any ideas, a good library or a plan?
Any comments are welcome. Thanks.
Note: I consulted Ruby "Matrix" and "Vector" classes, but I don't see any way to use it in my way...
Edit: In fact, each value is the number of cells (from the current cell to the last cell) according to the given vector.
If we take the example where the vector is [-2, 0], with the value *1* (at array[2, 3]):
array = [
[<0>, <0>, <1>, <1>, <2>],
[<0>, <0>, <1>, <1>, <2>],
[<0>, <0>, <1>, *1*, <2>]
]
... we could think such as:
The vector [-2, 0] means that -2 is
for cols and 0 is for rows. So if we
are in array[2, 3], we can move 1 time
on the left (left because 2 is
negative) with 2 length (because
-2.abs == 2). And we don't move on the top or bottom, because of 0 for
rows.
It's quite easy to achieve this:
require 'matrix'
def build(rows, cols, vector)
Matrix.build(rows, cols){|i, j| vector.inner_product([cols-j-1, rows-i-1]) }
end
build(3, 5, Vector[1, 0]) # => your first example
# ...
build(3, 5, Vector[0, 1]) # => your last example
You will need the latest Matrix library which introduces Matrix.build.
Note: I find your examples a bit odd, and the third one even stranger. Looks like we have to divide by the vector you give, unless it's 0? Anyways, just adapt the block to the formula you need.
ok i am a little confused but i am going to take a shot in the dark
What you want is to run through every point in the array and call a function that would calculate the value at that position
so we have
loop i
loop j
array[i,j]=Vectorfunction(i,j,vector);
next j
next i
function(i,j,vector)
Here i am guessing you somehow use the position in the array, and the slope of the line defined by the vector. What that is i can't extract from the data, but i am sure such a function exists.
Most likely this involves arccos to get the angle. and then return i*arcsin+j+arccos

Resources