Related
With a 3D tensor of shape (number of filters, height, width), how can one reduce the number of filters with a reshape which keeps the original filters together as whole blocks?
Assume the new size has dimensions chosen such that a whole number of the original filters can fit side by side in one of the new filters. So an original size of (4, 2, 2) can be reshaped to (2, 2, 4).
A visual explanation of the side by side reshape where you see the standard reshape will alter the individual filter shapes:
I have tried various pytorch functions such as gather and select_index but not found a way to get to the end result in a general manner (i.e. works for different numbers of filters and different filter sizes).
I think it would be easier to rearrange the tensor values after performing the reshape but could not get a tensor of the pytorch reshaped form:
[[[1,2,3,4],
[5,6,7,8]],
[[9,10,11,12],
[13,14,15,16]]]
to:
[[[1,2,5,6],
[3,4,7,8]],
[[9,10,13,14],
[11,12,15,16]]]
for completeness, the original tensor before reshaping:
[[[1,2],
[3,4]],
[[5,6],
[7,8]],
[[9,10],
[11,12]],
[[13,14],
[15,16]]]
Another option is to construct a list of parts and concatenate them
x = torch.arange(4).reshape(4, 1, 1).repeat(1, 2, 2)
y = torch.cat([x[i::2] for i in range(2)], dim=2)
print('Before\n', x)
print('After\n', y)
which gives
Before
tensor([[[0, 0],
[0, 0]],
[[1, 1],
[1, 1]],
[[2, 2],
[2, 2]],
[[3, 3],
[3, 3]]])
After
tensor([[[0, 0, 1, 1],
[0, 0, 1, 1]],
[[2, 2, 3, 3],
[2, 2, 3, 3]]])
Or a little more generally we could write a function that takes groups of neighbors along a source dimension and concatenates them along a destination dimension
def group_neighbors(x, group_size, src_dim, dst_dim):
assert x.shape[src_dim] % group_size == 0
return torch.cat([x[[slice(None)] * (src_dim) + [slice(i, None, group_size)] + [slice(None)] * (len(x.shape) - (src_dim + 2))] for i in range(group_size)], dim=dst_dim)
x = torch.arange(4).reshape(4, 1, 1).repeat(1, 2, 2)
# read as "take neighbors in groups of 2 from dimension 0 and concatenate them in dimension 2"
y = group_neighbors(x, group_size=2, src_dim=0, dst_dim=2)
print('Before\n', x)
print('After\n', y)
You could do it by chunking tensor and then recombining.
def side_by_side_reshape(x):
n_pairs = x.shape[0] // 2
filter_size = x.shape[-1]
x = x.reshape((n_pairs, 2, filter_size, filter_size))
return torch.stack(list(map(lambda x: torch.hstack(x.unbind()), k)))
>> p = torch.arange(1, 91).reshape((10, 3, 3))
>> side_by_side_reshape(p)
tensor([[[ 1, 2, 3, 10, 11, 12],
[ 4, 5, 6, 13, 14, 15],
[ 7, 8, 9, 16, 17, 18]],
[[19, 20, 21, 28, 29, 30],
[22, 23, 24, 31, 32, 33],
[25, 26, 27, 34, 35, 36]],
[[37, 38, 39, 46, 47, 48],
[40, 41, 42, 49, 50, 51],
[43, 44, 45, 52, 53, 54]],
[[55, 56, 57, 64, 65, 66],
[58, 59, 60, 67, 68, 69],
[61, 62, 63, 70, 71, 72]],
[[73, 74, 75, 82, 83, 84],
[76, 77, 78, 85, 86, 87],
[79, 80, 81, 88, 89, 90]]])
but I know it's not ideal since there is map, list and unbind which disrupts memory. This is what I offer till I figure out how to do it via view only (so a real reshape)
I'm a total beginner, self-learner and I'm trying to solve the problem 5 from How to Think Like a Computer Scientist: Learning with Python 3. The problem looks like this:
xs = [12, 10, 32, 3, 66, 17, 42, 99, 20]
Write a loop that adds all the numbers from the list into a variable called total. You should set the total variable to have the value 0 before you start adding them up, and print the value in total after the loop has completed.
Here is what I tried to do:
for xs in [12, 10, 32, 3, 66, 17, 42, 99, 20]:
xs = [12, 10, 32, 3, 66, 17, 42, 99, 20]
total = 0
total = sum(xs)
print(total)
Should I use a for loop at all? Or should I use a sum function?
There is no need for a for loop here simply:
xs = [12, 10, 32, 3, 66, 17, 42, 99, 20]
total = sum(xs)
print(total)
If you really want to use a loop:
total = 0
xs = [12, 10, 32, 3, 66, 17, 42, 99, 20]
for i in xs:
total += i
print(total)
list = [1,2,,3,4,5,6,1,2,56,78,45,90,34]
range = ["0-25","25-50","50-75","75-100"]
I am coding in python. I want to sort a list of integers in range of numbers and store them in differrent lists.How can i do it?
I have specified my ranges in the the range list.
Create a dictionary with max-value of each bin as key. Iterate through your numbers and append them to the list that's the value of each bin-key:
l = [1,2,3,4,5,6,1,2,56,78,45,90,34]
# your range covers 25 a piece - and share start/endvalues.
# I presume [0-25[ ranges
def inRanges(data,maxValues):
"""Sorts elements of data into bins that have a max-value. Max-values are
given by the list maxValues which holds the exclusive upper bound of the bins."""
d = {k:[] for k in maxValues} # init all keys to empty lists
for n in data:
key = min(x for x in maxValues if x>n) # get key
d[key].append(n) # add number
return d
sortEm = inRanges(l,[25,50,75,100])
print(sortEm)
print([ x for x in sortEm.values()])
Output:
{25: [1, 2, 3, 4, 5, 6, 1, 2], 50: [25, 45, 34],
75: [56], 100: [78, 90]}
[[1, 2, 3, 4, 5, 6, 1, 2], [25, 45, 34], [56], [78, 90]]
Another stable bin approach for your special case (regular intervaled bins) would be to use a calculated key - this would get rid of the key-search in each step.
Stable search means the order of numbers in the list is the same as in the input data:
def inRegularIntervals(data, interval):
"""Sorts elements of data into bins of regular sizes.
The size of each bin is given by 'interval'."""
# init dict so keys are ordered - collection.defaultdict(list)
# would be faster - but this works for lists of a couple of
# thousand numbers if you have a quarter up to one second ...
# if random key order is ok, shorten this to d = {}
d = {k:[] for k in range(0, max(data), interval)}
for n in data:
key = n // interval # get key
key *= interval
d.setdefault(key, [])
d[key ].append(n) # add number
return d
Use on random data:
from random import choices
data = choices(range(100), k = 50)
data.append(135) # add a bigger value to see the gapped keys
binned = inRegularIntervals(data, 25)
print(binned)
Output (\n and spaces added):
{ 0: [19, 9, 1, 0, 15, 22, 4, 9, 12, 7, 12, 9, 16, 2, 7],
25: [25, 31, 37, 45, 30, 48, 44, 44, 31, 39, 27, 36],
50: [50, 50, 58, 60, 70, 69, 53, 53, 67, 59, 52, 64],
75: [86, 93, 78, 93, 99, 98, 95, 75, 88, 82, 79],
100: [],
125: [135], }
To sort the binned lists in place, use
for k in binned:
binned[k].sort()
to get:
{ 0: [0, 1, 2, 4, 7, 7, 9, 9, 9, 12, 12, 15, 16, 19, 22],
25: [25, 27, 30, 31, 31, 36, 37, 39, 44, 44, 45, 48],
50: [50, 50, 52, 53, 53, 58, 59, 60, 64, 67, 69, 70],
75: [75, 78, 79, 82, 86, 88, 93, 93, 95, 98, 99],
100: [],
125: [135]}
I am trying to program a Lotto simulator, where the code generates 6 random unique numbers out of 45 for about 1000 players where each player has a unique ID. I want to place it into an array that looks like this:
lotto[0...n-1][0...5]
Where [0...n-1] contains the players ID, and [0...5] their unique 6 game numbers.
So it should look something like this when printed
lotto[1][32, 34, 24, 13, 20, 8]
lotto[2][1, 27, 4, 41, 33, 17]
...
lotto[1000][6, 12, 39, 16, 45, 3]
What is the best way of doing something like this without actually merging the two arrays together?
As later on I want to use a merge-sort algorithm to then numerically order the game numbers for each player so it would look something like this without the players ID interfering with the game numbers.
lotto[1][8, 13, 20, 24, 32, 34]
lotto[2][1, 4, 17, 27, 33, 41]
So far I've got:
playerID = list(range(1, 1001))
playerNum = random.sample(range(1, 45), 6)
print(playerID + playerNum)
But that just prints and joins:
[1, 2, 3, ..., 1000, 32, 5, 19, 27, 6, 22]
Thanks for the help.
import random
n_players = 1000
lotto = [random.sample(range(1, 45), 6) for _ in range(n_players)]
OR
import random
n_players = 1000
tup = tuple(range(1, 45))
lotto = []
for _ in range(n_players):
lotto.append(random.sample(tup, 6))
I have a function I wrote in python that simple makes a horizontal list of int. I modified the print statement so that the list would print with commas, but the function adds one after the last int.
Any ideas as how to get rid of it?
num = list(range(20))
def count(x):
for i in range(len(x)):
# i+1 add in order to remove beginning zero.
print(i+1,end=',')
count(num)
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,
Try this:
num = list(range(20))
l = []
def count(x):
for i in range(len(x)):
l.append(i+1)
count(num)
print(l)
Outpout:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20]
You can also modify it to this:
def count(x):
for i in range(len(x)):
# i+1 add in order to remove beginning zero.
if i < len(x)-1:
print(i+1, end=',')
else:
print(i+1)
Output:
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20
Try this:
num = list(range(20))
def count(x):
for i in range(len(x)-1):
print(i+1,end=',')
print(len(x))
count(num)
Add each number to a string and then print the string minus the last character:
num = list(range(20))
def count(x):
s = ""
for i in range(len(x)):
# i+1 add in order to remove beginning zero.
s += str(i+1) + ","
print(s[:-1])
count(num)
Output:
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20
A better function name would be display, and the function you want is str.join():
def display(list_data):
print(', '.join(list_data))
The thing to keep in mind is the pieces to join must be strings, so you may need to convert:
', '.join([str(i) for i in list_data])
Rather than creating a function, an output sequence can be processed with the range command:
num = range(1,21,1)
print num
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
Print without the braces:
num = range(1,21,1)
print str(num).strip('[]')
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20
User chooses start and ending numbers somewhere earlier in the code:
start = 56
end = 69
num = range(start, end + 1)
print str(num).strip('[]')
Output is:
56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69
User supplies start and stop interactivly:
start = raw_input('Choose start')
end = raw_input('Choose end')
num = range(start, end + 1)
print str(num).strip('[]')