Is .contiguous().flatten() the same as .view(-1) in PyTorch? - pytorch

Are these exactly the same?
myTensor.contiguous().flatten()
myTensor.view(-1)
Will they return the same auto grad function etc?

No, they are not exactly the same.
myTensor.contiguous().flatten():
Here, contiguous() either returns a copy of myTensor stored in contiguous memory, or returns myTensor itself if it is already contiguous. Then, flatten() reshapes the tensor to a single dimension. However, the returned tensor could be the same object as myTensor, a view, or a copy, so the contiguity of the output is not guaranteed.
Relevant documentation:
It’s also worth mentioning a few ops with special behaviors:
reshape(), reshape_as() and flatten() can return either a view or new tensor, user code shouldn’t rely on whether it’s view or not.
contiguous() returns itself if input tensor is already contiguous, otherwise it returns a new contiguous tensor by copying data.
myTensor.view(-1):
Here, view() returns a tensor with the same data as myTensor, and will only work if myTensor is already contiguous. The result may not be contiguous depending on the shape of myTensor.

Some illustration:
xxx = torch.tensor([[1], [2], [3]])
xxx = xxx.expand(3, 4)
print ( xxx )
print ( xxx.contiguous().flatten() )
print ( xxx.view(-1) )
tensor([[1, 1, 1, 1],
[2, 2, 2, 2],
[3, 3, 3, 3]])
tensor([1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3])
---------------------------------------------------------------------------
RuntimeError Traceback (most recent call last)
<ipython-input-7-281fe94f55fb> in <module>
3 print ( xxx )
4 print ( xxx.contiguous().flatten() )
----> 5 print ( xxx.view(-1) )
RuntimeError: view size is not compatible with input tensor's size and stride (at least one dimension spans across two contiguous subspaces). Use .reshape(...) instead.

Related

What is the difference for the indexing between x[:] [1] and x [:,1]?

I have a hard time understanding the difference between these two kinds of indexing.
Let's say I have a nested nested list:
x = np.array([[[1,2],[5,6]],[[9,7],[12,23]]])
if I did
x[:][:][1] and x[:,:,1]
I would get
[[9 7][12 23]]
[[5 6][12 23]]
respectively.
To be honest, I have no clue as to how I would get these results. Could someone explain the steps to me as to how I would get these arrays ?
This has to do with python's slice syntax. Essentially, obj[a:b:c] is syntactic shorthand for obj.__getitem__(slice(a,b,c)).
x[:] simply returns a 'full slice' of x - that is, it returns an exact copy of x. Doing x[:][:][1] is no different from doing x[1].
Meanwhile, doing x[:,:,1] equates to:
x.__getitem__((slice(), slice(), 1))
that is, using a 3-tuple as an index. For an ordinary python list, this would fail, but Numpy accepts it gracefully. To see how Numpy does so, let's look a bit closer at this example:
>>> x = np.array([[[1,2],[5,6]],[[9,7],[12,23]]])
>>> x[1]
array([[ 9, 7],
[12, 23]])
>>> x[:,1]
array([[ 5, 6],
[12, 23]])
>>> x[:,:,1]
array([[ 2, 6],
[ 7, 23]])
>>> x[:,:,:,1]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: too many indices for array: array is 3-dimensional, but 4 were indexed
We can see a pattern.
When you give a Numpy array a tuple as an index, it maps each element of the tuple to a dimension, and then applies the subsequent elements of the tuple to each of those dimensions. In short:
x[1] just gets the element at index 1 from the first dimension of the array. This is the single element [[9, 7], [12, 23]]
x[:, 1] gets the element at index 1 from each element in the first dimension of the array. Which is to say, it gets the elements at index 1 from the second dimension of the array. This is two elements: [5, 6] and [12, 23]. Numpy groups them together in a list.
x[:, :, 1] follows the same pattern - it gets the elements at index 1 from the third dimension of the array. This time there are four unique elements: 2 and 6 from the first element in the second dimension, and, 7 and 23 from the second element in the second dimension. Numpy groups them by dimension in a nested list.
x[:, :, :, 1] fails, because the array only has three dimensions - there's no way to further subdivide any of the third dimension's elements.

Equivalent of np.multiply.at in Pytorch

Are there equivalent of np.multiply.at in Pytorch? I have two 4d arrays and one 2d index array:
base = torch.ones((2, 3, 5, 5))
to_multiply = torch.arange(120).view(2, 3, 4, 5)
index = torch.tensor([[0, 2, 4, 2], [0, 3, 3, 2]])
As shown in this question I asked earlier (in Numpy), the row index of the index array corresponds to the 1st dimension of base and to_multiply, and the value of the index array corresponds to the 3rd dimension of base. I want to take the slice from base according to the index and multiply with to_multiply, it can be achieved in Numpy as follows:
np.multiply.at(base1, (np.arange(2)[:,None,None],np.arange(3)[:,None],index[:,None,:]), to_multiply)
However, now when I want to translate this to PyTorch, I cannot find an equivalent of np.multiply.at in Pytorch, I can only find the "index_add_" method but there is no "index_multiply". And I want to avoid doing explicit for loop.
So how can I achieve above in PyTorch? Thanks!

I am having trouble multiplying two matrices with numpy

I am trying to use numpy to multiply two matrices:
import numpy as np
A = np.array([[1, 3, 2], [4, 0, 1]])
B = np.array([[1, 0, 5], [3, 1, 2]])
I tested the process and ran the calculations manually, utilizing the formula for matrix multiplications. So, in this case, I would first multiply [1, 0, 5] x A, which resulted in [11, 9] and then multiply [3, 1, 2] x B, which resulted in [10, 14]. Finally, the product of this multiplication is [[11, 9], [10, 14]]
nevertheless, when I use numpy to multiply these matrices, I am getting an error:
ValueError: shapes (2,3) and (2,3) not aligned: 3 (dim 1) != 2 (dim 0)
Is there a way to do this with python, successfully?
Read the docs on matrix multiplication in numpy, specifically on behaviours.
The behavior depends on the arguments in the following way.
If both arguments are 2-D they are multiplied like conventional
matrices. If either argument is N-D, N > 2, it is treated as a stack
of matrices residing in the last two indexes and broadcast
accordingly. If the first argument is 1-D, it is promoted to a matrix
by prepending a 1 to its dimensions. After matrix multiplication the
prepended 1 is removed. If the second argument is 1-D, it is promoted
to a matrix by appending a 1 to its dimensions. After matrix
multiplication the appended 1 is removed.
to get your output, try transposing one before multiplying?
c=np.matmul(A,B.transpose())
array([[11, 10],
[ 9, 14]])

How to get the index of an numpy.ndarray

I would to print the images on index i but I get an error of only integer scalar arrays can be converted to a scalar index. How can I convert I to int for each iteration
I have tried replacing images[i] with images[n] it worked but not the result I want.
c = [1 1 1 0 1 2 2 3 4 1 3]
#c here is list of cluster labels obtained after Affinity propagation
num_clusters = len(set(c))
images = os.listdir(DIR_NAME)
for n in range(num_clusters):
print("\n --- Images from cluster #%d ---" % n)
for i in np.argwhere(c == n):
if i != -1:
print("Image %s" % images[i])
I expect the output to be the name of the image, but I instead get TypeError: only integer scalar arrays can be converted to a scalar index that is because i is of type numpy.ndarray
Look at the doc of np.argwhere, it does not return a list of integers, but a list of lists
x = array([[0, 1, 2], [3, 4, 5]])
np.argwhere(x>1)
>>> array([[0, 2], [1, 0], [1, 1], [1, 2]])
y = np.array([0, 1, 2, 3, 4, 6, 7])
np.argwhere(y>3)
>>> array([[4], [5], [6]])
so without knowing what your c looks like, I assume your i will be of the form np.array([[3]]) instead of an integer, and therefore your code fails. Print i for testing and extract (e.g. i[0][0] and a test that it is non-empty) the desired index first before you do i != -1.
Meta
It is best practise to post a minimal reconstructable example, i.e. other people should be able to copy-paste the code and run it. Moreover, if you post at least a couple lines of the traceback (instead of just the error), we would be able to tell where exactly the error is happening.

Numpy array indexing with two dimensions

I have one numpy array with two dimensions, for the example let's say :
a = np.array([[1,2,3,4,5],[4,6,5,8,9]])
I tried to do a = a[a[0]>2] but i got an error. I would like to obtain:
array([[3, 4, 5],
[5, 8, 9]])
Is it possible ? thanks !
Evaluate the options step by step:
In [75]: a = np.array([[1,2,3,4,5],[4,6,5,8,9]])
first row, a 1d array
In [76]: a[0]
Out[76]: array([1, 2, 3, 4, 5])
where that first row is >2, a 1d boolean array of same size
In [77]: a[0]>2
Out[77]: array([False, False, True, True, True])
Using that direct, produces an error:
In [78]: a[a[0]>2]
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-78-631a57b67cdb> in <module>()
----> 1 a[a[0]>2]
IndexError: boolean index did not match indexed array along dimension 0; dimension is 2 but corresponding boolean dimension is 5
First dimension of a is 2, but the boolean index (mask) has size 2 (2nd dim)
So we need to apply it to the 2nd dimension. 2d indexing syntax: x[i, j], x[:, j] to select all rows, but subset of columns:
In [79]: a[:,a[0]>2]
Out[79]:
array([[3, 4, 5],
[5, 8, 9]])

Resources