PyTorch unfold vs as_stride - python-3.x

It seems PyTorch unfold and as_stride are doing the same thing but for the former, you cannot control the tensor output size.
import torch
import torch.nn as nn
x = torch.arange(0, 10)
x1 = x.unfold(0, 3, 1)
x2 = x.as_strided((8,3), (1,1))
print(f'x1 = {x1}')
print(f'x2 = {x2}')
output:
x1 = tensor([[0, 1, 2],
[1, 2, 3],
[2, 3, 4],
[3, 4, 5],
[4, 5, 6],
[5, 6, 7],
[6, 7, 8],
[7, 8, 9]])
x2 = tensor([[0, 1, 2],
[1, 2, 3],
[2, 3, 4],
[3, 4, 5],
[4, 5, 6],
[5, 6, 7],
[6, 7, 8],
[7, 8, 9]])
Then is there any situation that you should use unfold instead of as_stride and vice versa?

Related

Select on second dimension on a 3D pytorch tensor with an array of indexes

I am kind of new with numpy and torch and I am struggling to understand what to me seems the most basic operations.
For instance, given this tensor:
A = tensor([[[6, 3, 8, 3],
[1, 0, 9, 9]],
[[4, 9, 4, 1],
[8, 1, 3, 5]],
[[9, 7, 5, 6],
[3, 7, 8, 1]]])
And this other tensor:
B = tensor([1, 0, 1])
I would like to use B as indexes for A so that I get a 3 by 4 tensor that looks like this:
[[1, 0, 9, 9],
[4, 9, 4, 1],
[3, 7, 8, 1]]
Thanks!
Ok, my mistake was to assume this:
A[:, B]
is equal to this:
A[[0, 1, 2], B]
Or more generally the solution I wanted is:
A[range(B.shape[0]), B]
Alternatively, you can use torch.gather:
>>> indexer = B.view(-1, 1, 1).expand(-1, -1, 4)
tensor([[[1, 1, 1, 1]],
[[0, 0, 0, 0]],
[[1, 1, 1, 1]]])
>>> A.gather(1, indexer).view(len(B), -1)
tensor([[1, 0, 9, 9],
[4, 9, 4, 1],
[3, 7, 8, 1]])

Transponse a list of lists from 2nd element in python

list_of_lists = [[1, 2, 3, 4], [1, 5, 6, 7], [1, 8, 9, 10]]
I would like to get to:
transposed_list = [[1, 2, 5, 8], [1, 3, 6, 9], [1, 4, 7, 10]]
In other words, only transpose from the 2nd element in the list, keeping the first element in place.
Try:
list_of_lists = [[1, 2, 3, 4], [1, 5, 6, 7], [1, 8, 9, 10]]
out = [
[list_of_lists[i][0]] + list(l)
for i, l in enumerate(zip(*(l[1:] for l in list_of_lists)))
]
print(out)
Prints:
[[1, 2, 5, 8], [1, 3, 6, 9], [1, 4, 7, 10]]

print values from a list in vertical order for many lists

I'm having trouble printing data from a list vertically , the list is as shown below
[[1, 4, 5], [4, 6, 8], [8, 3, 10]]
I want to print the data into a new list as follows:
[[1, 4, 8], [4, 6, 3], [5, 8, 10]]
I'm having trouble doing it when the lists get longer, as it is a nested list
If the data is only numbers / integers, then you might want to use numpy for this. It will be faster too.
import numpy
givenList = [[1, 4, 5], [4, 6, 8], [8, 3, 10]]
toNumpy = numpy.array(givenList) #convert to numpy array
toNumpy = toNumpy.T #transpose
toList = toNumpy.tolist() #convert back to list
print(toList)
# output : [[1, 4, 8], [4, 6, 3], [5, 8, 10]]
I think you are looking for zip.
l = [[1, 4, 5], [4, 6, 8], [8, 3, 10]]
z = zip(*l)
print('\n'.join(map(str, z)))
# Output is:
# (1, 4, 8)
# (4, 6, 3)
# (5, 8, 10)
It does produce tuples instead of lists, but that is usually easily dealt with, and if you are just iterating over them, then it probably doesn't matter.
l = [[1, 4, 5], [4, 6, 8], [8, 3, 10]]
z = map(list, zip(*l))
print('\n'.join(map(str, z)))
Will give you the same result, but will print them out as lists.

How can I have a python function that effectively divide a list to all possible number of chunks?

I want to split a list (float or integer) according to the following conditions:
Splitting the list into all possible subsamples.
No duplication.
A unit sample cannot be a subsample.
I have what splits a list into equal sizes by giving the number of subsamples.
The code I have laid my hand on which worked but does not give me what I want
import numpy as np
x = [1,2,3,4,5,6,7,8,9,10]
l = np.array_split(x,3)
output
[[1, 2, 3, 4], [5, 6, 7], [8, 9, 10]]
I desire to have a list of subsample of all possibilities without duplication. that is, a combination of all unique possibilities when the list is split into 2, 3, 4, etc (no two or more subsamples will have the same element)).
I do not what to specify chunk number so that it will not be limited to such number.
Here is what I did manually
From the following series [1,2,3,4,5,6,7,8,9,10] I sliced it into all possible blocks as follows:
when splitting into 2
[1][2,3,4,5,6,7,8,9,10]
[1,2][3,4,5,6,7,8,9,10]
[1,2,3][4,5,6,7,8,9,10]
[1,2,3,4][5,6,7,8,9,10]
[1,2,3,4,5][6,7,8,9,10]
[1,2,3,4,5,6][7,8,9,10]
[1,2,3,4,5,6,7,8][9,10]
[1,2,3,4,5,6,7,8,9][10]
when splitting into 3
[1][2][3,4,5,6,7,8,9,10]
[1][2,3][4,5,6,7,8,9,10]
[1][2,3,4][5,6,7,8,9,10]
[1][2,3,4,5][6,7,8,9,10]
[1][2,3,4,5,6][7,8,9,10]
[1][2,3,4,5,6,7][8,9,10]
[1][2,3,4,5,6,7,8][9,10]
[1][2,3,4,5,6,7,8,9][10]
[1,2][3][4,5,6,7,8,9,10]
[1,2][3,4][5,6,7,8,9,10]
[1,2][3,4,5][6,7,8,9,10]
[1,2][3,4,5,6][7,8,9,10]
[1,2][3,4,5,6,7][8,9,10]
[1,2][3,4,5,6,7,8][9,10]
[1,2][3,4,5,6,7,8,9][10]
[1,2,3][4][5,6,7,8,9,10]
[1,2,3][4,5][6,7,8,9,10]
[1,2,3][4,5,6][7,8,9,10]
[1,2,3][4,5,6,7][8,9,10]
[1,2,3][4,5,6,7,8][9,10]
[1,2,3][4,5,6,7,8,9][10]
[1,2,3,4][5][6,7,8,9,10]
[1,2,3,4][5,6][7,8,9,10]
[1,2,3,4][5,6,7][8,9,10]
[1,2,3,4][5,6,7,8][9,10]
[1,2,3,4][5,6,7,8,9][10]
[1,2,3,4,5][6][7,8,9,10]
[1,2,3,4,5][6,7][8,9,10]
[1,2,3,4,5][6,7,8][9,10]
[1,2,3,4,5][6,7,8,9][10]
[1,2,3,4,5,6][7][8,9,10]
[1,2,3,4,5,6][7,8][9,10]
[1,2,3,4,5,6][7,8,9][10]
when splitting into 4
[1,2,3,4,5,6,7][8][9,10]
[1,2,3,4,5,6,7][8,9][10]
[1,2,3,4,5,6,7,8][9][10]
After all possible splitting into blocks, I removed all the single digit blocks and also removed all duplicated blocks.
[2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9]
[3,4,5,6,7,8,9,10]
[2,3]
[2,3,4]
[2,3,4,5]
[2,3,4,5,6]
[2,3,4,5,6,7]
[2,3,4,5,6,7,8]
[2,3,4,5,6,7,8,9]
[4,5,6,7,8,9,10]
[3,4]
[3,4,5]
[3,4,5,6]
[3,4,5,6,7]
[3,4,5,6,7,8]
[1,2][3,4,5,6,7,8,9]
[5,6,7,8,9,10]
[4,5]
[4,5,6]
[4,5,6,7]
[4,5,6,7,8]
[1,2,3][4,5,6,7,8,9]
[6,7,8,9,10]
[5,6]
[5,6,7]
[5,6,7,8]
[1,2,3,4][5,6,7,8,9]
[1,2,3,4,5][7,8,9,10]
[6,7]
[6,7,8]
[6,7,8,9]
[8,9,10]
[7,8]
[1,2,3,4,5,6][7,8,9]
[9,10]
[1,2,3,4,5,6,7][8,9]
[1,2,3,4,5,6,7,8]
Here, I gather all the possible chunks together.
This is what I desire as an output.
[[2,3,4,5,6,7,8,9,10], [1,2,3,4,5,6,7,8,9], [3,4,5,6,7,8,9,10], [2,3], [2,3,4], [2,3,4,5], [2,3,4,5,6], [2,3,4,5,6,7], [2,3,4,5,6,7,8], [2,3,4,5,6,7,8,9], [4,5,6,7,8,9,10],[3,4], [3,4,5], [3,4,5,6], [3,4,5,6,7], [3,4,5,6,7,8], [1,2], [3,4,5,6,7,8,9], [5,6,7,8,9,10], [4,5], [4,5,6], [4,5,6,7], [4,5,6,7,8], [1,2,3], [4,5,6,7,8,9], [6,7,8,9,10], [5,6], [5,6,7], [5,6,7,8], [1,2,3,4], [5,6,7,8,9], [1,2,3,4,5], [7,8,9,10], [6,7], [6,7,8], [6,7,8,9], [8,9,10], [7,8], [1,2,3,4,5,6], [7,8,9], [9,10], [1,2,3,4,5,6,7], [8,9], [1,2,3,4,5,6,7,8]]
It looks to me like the problem reduces to finding all substrings of length 2 or greater that leave at least one fragment of length 1. In other words, you won't have to enumerate every partition to find them.
def parts(thing):
result = []
for i in range(len(thing)):
for j in range(i + 1, len(thing) + 1):
if 1 < len(thing[i:j]) < len(thing):
result.append(thing[i:j])
return result
res = parts([*range(1,11)])
# res
# [[1, 2], [1, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5, 6],
# [1, 2, 3, 4, 5, 6, 7], [1, 2, 3, 4, 5, 6, 7, 8],
# [1, 2, 3, 4, 5, 6, 7, 8, 9], [2, 3], [2, 3, 4], [2, 3, 4, 5],
# [2, 3, 4, 5, 6], [2, 3, 4, 5, 6, 7], [2, 3, 4, 5, 6, 7, 8],
# [2, 3, 4, 5, 6, 7, 8, 9], [2, 3, 4, 5, 6, 7, 8, 9, 10], [3, 4], [3, 4, 5],
# [3, 4, 5, 6], [3, 4, 5, 6, 7], [3, 4, 5, 6, 7, 8], [3, 4, 5, 6, 7, 8, 9],
# [3, 4, 5, 6, 7, 8, 9, 10], [4, 5], [4, 5, 6], [4, 5, 6, 7], [4, 5, 6, 7, 8],
# [4, 5, 6, 7, 8, 9], [4, 5, 6, 7, 8, 9, 10], [5, 6], [5, 6, 7], [5, 6, 7, 8],
# [5, 6, 7, 8, 9], [5, 6, 7, 8, 9, 10], [6, 7], [6, 7, 8], [6, 7, 8, 9],
# [6, 7, 8, 9, 10], [7, 8], [7, 8, 9], [7, 8, 9, 10], [8, 9], [8, 9, 10],
# [9, 10]]

How to find a column in a ndarray

Say i have a array
x = array([[ 0, 1, 2, 5],
[ 3, 4, 5, 5],
[ 6, 7, 8, 5],
[ 9, 10, 11, 5]])
I need to find the position/index of [3, 4, 5, 5]. In this case, it should return 1.
Create an array y that has all rows equal to the one you are looking for. Then, do an elementwise comparison x == y and find the rows where you get all True.
import numpy as np
x1 = np.array([[0, 1, 2, 5], [3, 4, 5, 5],
[6, 7, 8, 5], [9, 10, 11, 5]])
y1 = np.array([[3, 4, 5, 5]] * 4)
print(np.where(np.all(x1 == y1, axis=1))[0]) # => [1]
This approach returns an array of the indices where the desired row appears.
y2 = np.array([[1, 1, 1, 1]] * 4)
print(np.where(np.all(x1 == y2, axis=1))[0]) # => []
x2 = np.array([[3, 4, 5, 5], [3, 4, 5, 5],
[6, 7, 8, 5], [9, 10, 11, 5]])
print(np.where(np.all(x2 == y1, axis=1))[0]) # => [0 1]

Resources