how to efficiently insert element for a n dimension array - python

There is a simple example.
I have a 2d array
a=np.arange(4).reshape(2,2)+1
array([[1, 2],
[3, 4]])
and I wanna insert 0 (or any other value) in the beginning and end of the array, then it becomes
array([[ 0., 0., 0., 0.],
[ 0., 1., 2., 0.],
[ 0., 3., 4., 0.],
[ 0., 0., 0., 0.]])
I'm trying np.insert or np.concatenate, but I failed for >2 dimension. What is the fastest way to handle this kind of problem?

Use numpy.pad:
>>> np.pad(a, 1, 'constant')
array([[0, 0, 0, 0],
[0, 1, 2, 0],
[0, 3, 4, 0],
[0, 0, 0, 0]])

Related

just fill specific entrys of numpy array -> generating sparse matrix

I want to code a really big matrix with the following structure:
a = np.array([[1, 1, 1, 0, 0 ,0, 0, 0, 0],
[0, 0, 0, 1, 1, 1, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 1, 1, 1]])
Dimension of this array is (3,9) so basically the 1's depend on the dimension.
In my first row the first 3 entrys should be 1's, in my second row the entrys 3-5 should be 1's,
and so on...
How do I code this?
You can use the kronecker tensor product:
a = np.kron(np.eye(3),np.ones((1,3)))
# array([[1., 1., 1., 0., 0., 0., 0., 0., 0.],
# [0., 0., 0., 1., 1., 1., 0., 0., 0.],
# [0., 0., 0., 0., 0., 0., 1., 1., 1.]])

How to generate identity tensor with python?

I know about np.eye which generates identity matrix. I mean the identity matrix as
In linear algebra, the identity matrix, or sometimes ambiguously called a unit matrix, of size n is the n × n square matrix with ones on the main diagonal and zeros elsewhere.
And I know that we can create it in Numpy with np.identity(3).
But, I would like to know how can I have an identity Tensor in python.
I would like to use identity tensor in tensors multiplication. Like below:
where G = Er ×1 U1 ×2 U2 ...×M UM is a transformation tensor, and Er ∈
R r×r×...×r is an identity tensor (the diagonal elements are 1, and all other entries are 0). I need to have the code for generating the identity tensor.
Thank you in advance.
Something like this?
def nd_id(n, d):
out = np.zeros( (n,) * d )
out[ tuple([np.arange(n)] * d) ] = 1
return out
Testing
nd_id(3,3)
Out[]:
array([[[ 1., 0., 0.],
[ 0., 0., 0.],
[ 0., 0., 0.]],
[[ 0., 0., 0.],
[ 0., 1., 0.],
[ 0., 0., 0.]],
[[ 0., 0., 0.],
[ 0., 0., 0.],
[ 0., 0., 1.]]])
Instead of np.identity use tf.eye:
tf.eye(2)
# [[1., 0.],
# [0., 1.]]
It can be done with a function that returns one if all indices are equal, but it must be vectorized in order to be used in np.fromfunction
np.fromfunction(np.vectorize(lambda i,j,k: int(i==j==k)), (3,3,3))
Output:
array([[[1, 0, 0],
[0, 0, 0],
[0, 0, 0]],
[[0, 0, 0],
[0, 1, 0],
[0, 0, 0]],
[[0, 0, 0],
[0, 0, 0],
[0, 0, 1]]])

Pytorch, efficient way extend a tensor by its first and last element

I have a tensor in pytorch. I want to extend it on a specific dimension from the beginning and the end by k positions with the first and last elements of that dimension respectively.
Say I have the tensor with data [[0, 0, 0], [1, 1, 1], [2, 2, 2]]. Operation extend(dim, k) would change it in this way:
extend(0, 1): [[0, 0, 0], [0, 0, 0], [0, 0, 0], [1, 1, 1], [2, 2, 2], [2, 2, 2], [2, 2, 2]]
extend(1, 1): [0, 0, 0, 0, 0], [1, 1, 1, 1, 1], [2, 2, 2, 2, 2]]
What is an efficient way to do this (compliant with tensor.requires_grad=true)
You are looking for torch.nn.functional.pad, with mode='replicate'.
However, there are two things you need to pa attention to to get this to work:
1. pad does not work with 2D tensors. Thus, you need to add leading singleton dimensions before pad and squeezeing them afterwards.
2. The order of pad values pad expects is opposite to dim order.
import torch
from torch.nn inport functional
x = torch.tensor([[0, 0, 0],[1, 1, 1], [2, 2, 2]], dtype=torch.float)
# expand along dim=0 by k=2
f.pad(x[None,None,...], (0,0, 2, 2), mode='replicate').squeeze()
Out[]:
tensor([[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
[1., 1., 1.],
[2., 2., 2.],
[2., 2., 2.],
[2., 2., 2.]])
# expand along dim=1 by k=2
f.pad(x[None,None,...], (2, 2, 0 , 0), mode='replicate').squeeze()
Out[]:
tensor([[0., 0., 0., 0., 0., 0., 0.],
[1., 1., 1., 1., 1., 1., 1.],
[2., 2., 2., 2., 2., 2., 2.]])

transform a numpy array of dimensions nx1 into a numpy array of dimensions nx10 [duplicate]

This question already has answers here:
Convert array of indices to one-hot encoded array in NumPy
(22 answers)
Closed 7 years ago.
I have a numpy array, A of size nx1 where each value is a number between 0 and 9.
I would like to create a new array, B of size nx10 such that in B[i] we store a numpy array that contains zeros and a 1 in position A[i].
For example:
A array
[[9]
[2]
[4]
[1]
[8]]
B array
[[0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
[0, 0, 1, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 1, 0, 0, 0, 0, 0]
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 1, 0]]
Is there an elegant way of doing this with numpy?
Create a new empty array using numpy.zeros, its size is going to be (arr.size, arr.max()), now fill the items on those positions using multi-dimensional indexing:
>>> arr = np.array([[9], [2], [4], [1], [8]])
>>> arr_ = np.zeros((arr.size, arr.max()))
>>> arr_[np.arange(arr.size), arr[:,0]-1] = 1
>>> arr_
array([[ 0., 0., 0., 0., 0., 0., 0., 0., 1.],
[ 0., 1., 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 1., 0., 0., 0., 0., 0.],
[ 1., 0., 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0., 1., 0.]])
Something like this would do it:
A = [[9],[2],[4],[1],[8]]
B = [[1 if i == j[0] else 0 for i in range(10)] for j in A]
This is a list-based approach; you can simply use np.asarray on B to get the numpy matrix, or create a 10x10 matrix of zeros in numpy and fill 1s in the positions dictated by the A array.
The latter generalises to the case where A's elements might have more than one item.
You could do something like this, assuming an NP Nx1 array of X:
max_val = max(X)
length_arr = len(X)
new_arr = np.zeros((max_val,length_arr))
This will create the array of the right size that you want.
for i in range(len(X)):
new_arr[i][X[i]-1]=1
Should then assign the correct values in place?
Works fine in my test case.

Python function to expand image (NumPy array)

Say I have a greyscale image that is 3x3 and is represented by the numpy array below.
I want to increase the size and resolution of the image, similar to a resizing function in a normal picture editing software, but I don't want it to change any of the values of the pixels, just to expand them.
Is there a Python function that does the following conversion?
[0,0,0]
[0,1,0]
[0,0,0]
---->
[0,0,0,0,0,0]
[0,0,0,0,0,0]
[0,0,1,1,0,0]
[0,0,1,1,0,0]
[0,0,0,0,0,0]
[0,0,0,0,0,0]
You could use np.repeat along both axes of the 3x3 img array:
>>> img.repeat(2, axis=0).repeat(2, axis=1)
array([[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 1, 1, 0, 0],
[0, 0, 1, 1, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0]])
Another way is to calculate the Kronecker product of img and an array of the appropriate shape filled with ones:
>>> np.kron(img, np.ones((2,2)))
array([[ 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0.],
[ 0., 0., 1., 1., 0., 0.],
[ 0., 0., 1., 1., 0., 0.],
[ 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0.]])
Here's a link to the documentation for np.kron:
So in the example above, each value x in img is multiplied by a 2x2 array of ones to create a 2x2 array of x values. These new 2x2 arrays make up the returned array.
This multiplication might be slower than simply repeating, however.

Categories