Uniform sampling with replacement non-randomly in PyTorch - pytorch

Given a bool tensor (mask) of shape 4x4:
x = torch.tensor([
[ True, True, False, True ],
[ False, False, False, True ],
[ False, True, True, True ],
[ False, True, True, False ],
])
I want to sample (7) accordingly with the following result which is of shape 4x7:
tensor([[0, 0, 0, 1, 1, 3, 3],
[3, 3, 3, 3, 3, 3, 3],
[1, 1, 1, 2, 2, 3, 3],
[1, 1, 1, 1, 2, 2, 2]])
The closest thing I could come is the following implementation:
def uniform_sampling(tensor, count = 1):
indices = torch.arange(0, tensor.shape[-1], device = tensor.device).expand(tensor.shape)
samples_count = tensor.long().sum(-1)
output = tensor.long() * (count // samples_count)[:, None]
remainder = count - output.sum(-1)
rem1 = torch.stack((remainder, tensor.sum(-1) - remainder), -1).flatten()
rem2 = torch.stack((torch.ones_like(remainder), torch.zeros_like(remainder)), -1).flatten()
remaining = rem2.repeat_interleave(rem1, 0)
output[tensor > 0] += remaining
samples = indices[tensor].repeat_interleave(output[tensor], -1).view(-1, count)
return samples
uniform_sampling(x, count = 7)
Are there any (maybe native) PyTorch functionalities that does the same but faster and more efficiently?

Related

Can I apply torch.isin() to each row in 2D tensor without loop?

I have two tensors.
tensor_1 = tensor([[10, 8, 7],
[ 4, 5, 9]])
target_tensor = tensor([[ 8, 8, 6, 11, 0],
[ 7, 2, 10, 4, 5]])
and torch.isin(tensor_1, target_tensor) returns
tensor([[ True, True, True],
[ True, True, False]])
I want to apply isin to each row and get result like below
tensor([[False, True, False],
[ True, True, False]])
I can do this using for loop, but I don't want to use loop.
tmp_result = torch.zeros_like(tensor_1, dtype=torch.bool)
for i in range(tensor_1.size(0)):
tmp_result[i] = torch.isin(tensor_1[i], target_tensor[i])
How can I apply torch.isin() to each row in 2D tensor using GPU without loop?

Any idea why python3 is not treating False as bool?

Any idea why python3 is not treating False as bool?
I want to move all the zeros to the end of the list.
def move_zeros(array):
for i in array:
if type(i) is not bool:
if i == 0:
array.append(int(i)) # catching non bool values that are zeros, adding at the end of the list
array.remove(i) # removing original
elif type(i) is bool:
pass #Here it catches False from the input, it should do nothing but somehow it is moved to the end of the list as zero in the output.
return array
print(move_zeros(["a", 0, 0, "b", None, "c", "d", 0, 1,
False, 0, 1, 0, 3, [], 0, 1, 9, 0, 0, {}, 0, 0, 9]))
Output:
['a', 'b', None, 'c', 'd', 1, 1, 3, [], 1, 9, {}, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
Try this slight modification to your code:
def move_zeros(array):
new_list = [] # Work a new list
for i in array:
print(f"I = {i}")
if type(i) is not bool:
if i == 0:
new_list.append(int(i))
else:
pass
return new_list
print(move_zeros(["a", 0, 0, "b", None, "c", "d", 0, 1,
False, 0, 1, 0, 3, [], 0, 1, 9, 0, 0, {}, 0, 0, 9]))

What is this operation in numpy called?

I've been going over the numpy docs looking for a specific operation. The words I would use for this are "overlay" or "mask" but the numpy concepts of those words don't seem to match mine.
I want to take two arrays, one dense and one sparse and combine them thusly:
[ 1, 2, 3, 4, 5 ]
X [ N, N, 10, N, 12 ]
= [ 1, 2, 10, 4, 12 ]
where X is the operation and N is None, or Null, -1, or some other special character.
How is this achieved in numpy/python3?
You can use np.where:
# pick special value
N = -1
dns = [ 1, 2, 3, 4, 5 ]
sprs = [ N, N, 10, N, 12 ]
# this is important otherwise the comparison below
# is not done element by element
sprs = np.array(sprs)
# tada!
np.where(sprs==N,dns,sprs)
# array([ 1, 2, 10, 4, 12])
When called with three arguments m,a,b where "mixes" a and b taking elements from a where m is True and from b where it is False.
You can "fill" the masked array, with np.ma.filled(..) [numpy-doc], for example:
>>> a
array([1, 2, 3, 4, 5])
>>> b
masked_array(data=[--, --, 10, --, 12],
mask=[ True, True, False, True, False],
fill_value=999999)
>>> b.filled(a)
array([ 1, 2, 10, 4, 12])
>>> np.ma.filled(b, a)
array([ 1, 2, 10, 4, 12])
Here we thus fill the masked values from b with the corresponding values of a.

Removing duplicates with no sets, no for loops, maintain order and update the original list

Ok, so I have to remove duplicates from a list and maintain order at the same time. However, there are certain conditions such as I'm not allowed to use set or for loops. Also when the function mustn't return a new list but update the original list. I have the following code, but it only works partially and yes I know I'm only checking once, but I'm not sure how to proceed further.
def clean_list(values):
i = len(values)-1
while i > 0:
if values[i] == values[i-1]:
values.pop(i)
i -= 1
return values
values = [1, 2, 0, 1, 4, 1, 1, 2, 2, 5, 4, 3, 1, 3, 3, 4, 2, 4, 3, 1, 3, 0, 3, 0, 0]
new_values = clean_list(values)
print(new_values)
Gives me the result:
[1, 2, 0, 1, 4, 1, 2, 5, 4, 3, 1, 3, 4, 2, 4, 3, 1, 3, 0, 3, 0]
Thanks
Try the following.
Using two while loops, the first will get your unique item, the second will then search through the rest of the list for any other matching items and remove them, maintaining order.
def clean_list(lst):
i = 0
while i < len(lst):
item = lst[i] # item to check
j = i + 1 # start next item along
while j < len(lst):
if item == lst[j]:
lst.pop(j)
else:
j += 1
i += 1
values = [1, 2, 0, 1, 4, 1, 1, 2, 2, 5, 4, 3, 1, 3, 3, 4, 2, 4, 3, 1, 3, 0, 3, 0, 0]
clean_list(values)
print(values)
# Output
[1, 2, 0, 4, 5, 3]
Update: Improved function to be faster as worst case the first one was O(n2)
def clean_list(lst):
seen = set()
i = 0
while i < len(lst):
item = lst[i]
if item in seen:
lst.pop(i)
else:
seen.add(item)
i += 1
values = [1, 2, 0, 1, 4, 1, 1, 2, 2, 5, 4, 3, 1, 3, 3, 4, 2, 4, 3, 1, 3, 0, 3, 0, 0]
clean_list(values)
print(values)
# Output
[1, 2, 0, 4, 5, 3]

Adding Pivoting to the following Gauss Elimination code

The program below uses gauss elimination to without pivoting. I would like to know how to add pivoting into this code to account for an array with a leading term of zero
from numpy import array,empty
A = array([[ 2, 1, 4, 1 ],
[ 3, 4,-1,-1 ],
[ 1, -4, 1, 5],
[2,-2,1,3]],float)
v = array([ -4,3,9,7 ], float)
N = len(v)
for m in range (N):
div = A[m,m]
A[m,:] /= div
v[m] /= div
for i in range(m+1,N):
mult = A[i,m]
A[i,:] -= mult*A[m,:]
v[i] -= mult*v[m]
x = empty(N,float)
for m in range(N-1,-1,-1):
x[m] = v[m]
for i in range(m+1,N):
x[m] -= A[m,i]*x[i]
the new array I would like it to solve is
A = array([[ 0, 1, 4, 1 ],
[ 3, 4,-1,-1 ],
[ 1, -4, 1, 5],
[2,-2,1,3]],float)

Resources