Supposing I have two square matrices A, B of the same size
A = torch.tensor([[1, 2], [3, 4]])
B = torch.tensor([[1, 1], [1, 1]])
And I want a resulting tensor that consists of the row-wise dot product, say
tensor([3, 7]) # i.e. (1*1 + 2*1, 3*1 + 4*1)
What is an efficient means of achieving this in PyTorch?
As you said you can use torch.bmm but you first need to broadcast your inputs:
>>> torch.bmm(A[..., None, :], B[..., None])
tensor([[[3]],
[[7]]])
Alternatively you can use torch.einsum:
>>> torch.einsum('ij,ij->i', A, B)
tensor([3, 7])
import torch
import numpy as np
def row_wise_product(A, B):
num_rows, num_cols = A.shape[0], A.shape[1]
prod = torch.bmm(A.view(num_rows, 1, num_cols), B.view(num_rows, num_cols, 1))
return prod
A = torch.tensor(np.array([[1, 2], [3, 4]]))
B = torch.tensor(np.array([[1, 1], [1, 1]]))
C = row_wise_product(A, B)
I have a tensor Aof sizetorch.Size([32, 32, 3, 3]) and I want to split it and extract a tensor B of size torch.Size([16, 16, 3, 3]) from it. The tensor can be 1d or 4d and split has to be according to the given new tensor dimensions. I have been able to generate the target dimensions but I'm unable to split and extract the values from the source tensor. I ave tried torch.narrow but it takes only 3 arguments and I need 4 in many cases. torch.split takes dim as an int due to which tensor is split along one dimension only. But I want to split it along multiple dimensions.
You have multiple options:
use .split multiple times
use .narrow multiple times
use slicing
e.g.:
t = torch.rand(32, 32, 3, 3)
t0, t1 = t.split((16, 16), 0)
print(t0.shape, t1.shape)
>>> torch.Size([16, 32, 3, 3]) torch.Size([16, 32, 3, 3])
t00, t01 = t0.split((16, 16), 1)
print(t00.shape, t01.shape)
>>> torch.Size([16, 16, 3, 3]) torch.Size([16, 16, 3, 3])
t00_alt, t01_alt = t[:16, :16, :, :], t[16:, 16:, :, :]
print(t00_alt.shape, t01_alt.shape)
>>> torch.Size([16, 16, 3, 3]) torch.Size([16, 16, 3, 3])
I have 2 tensors with dimension, A = [64,155,300] and B =[64,155,100]
when I add this 2 tensors ie. C= A+B,
I get this error ==> " RuntimeError: The size of tensor a (300) must match the size of tensor b (100) at non-singleton dimension 2 "
could anyone please help how should I add above tensors? any help will be appreciated!
As error says you can not add two tensor with mis-match shapes
but if you want you can repeat your third dim of B tensor so it can match with A
using torch.Tensor.repeat try A + B.repeat(1,1,3)
>>> A.shape
torch.Size([64, 155, 300])
>>> B.shape
torch.Size([64, 155, 100])
>>> B = B.repeat(1,1,3)
>>> B.shape
torch.Size([64, 155, 300])
>>> C = A + B
>>> C.shape
torch.Size([64, 155, 300])
I want to compare two array(4 floating point)and print mismatched items.
I used this code:
>>> from numpy.testing import assert_allclose as np_assert_allclose
>>> x=np.array([1,2,3])
>>> y=np.array([1,0,3])
>>> np_assert_allclose(x,y, rtol=1e-4)
AssertionError:
Not equal to tolerance rtol=0.0001, atol=0
(mismatch 33.33333333333333%)
x: array([1, 2, 3])
y: array([1, 0, 3])
the problem by this code is with big array:
(mismatch 0.0015104228617559556%)
x: array([ 0.440088, 0.35994 , 0.308225, ..., 0.199546, 0.226758, 0.2312 ])
y: array([ 0.44009, 0.35994, 0.30822, ..., 0.19955, 0.22676, 0.2312 ])
I can not find what values are mismatched. how can see them ?
Just use
~np.isclose(x, y, rtol=1e-4) # array([False, True, False], dtype=bool)
e.g.
d = ~np.isclose(x, y, rtol=1e-4)
print(x[d]) # [2]
print(y[d]) # [0]
or, to get the indices
np.where(d) # (array([1]),)
For example, I have the following arrays:
x = [0, 1, 2, 3, 4.5, 5]
y = [2, 8, 3, 7, 8, 1]
I would like to be able to do the following given x:
>>> what_is_y_when_x_is(2)
(2, 3)
>>> what_is_y_when_x_is(3.1) # Perhaps set rules to round to nearest (or up or down)
(3, 7)
On the other hand, when given y:
>>> what_is_x_when_y_is(2)
(0, 2)
>>> what_is_x_when_y_is(max(y))
([1, 4.5], 8)
The circumstances of this problem
I could have plotted y versus x using a closed analytical function, which should be very easy by just calling foo_function(x). However, I'm running numerical simulations whose data plots do not have closed analytical solutions.
Attempted solution
I've tackled similar problems before and approached them roughly this way:
what_is_y_when_x_is(some_x)
Search the array x for some_x.
Get its index, i.
Pick up y[i].
Question
Is there a better way to do this? Perhaps a built-in numpy function or a better algorithm?
You should look at numpy.searchsorted and also numpy.interp. Both of those look like they might do the trick. Here is an example:
import numpy as np
x = np.array([0, 1, 2, 3, 4.5, 5])
y = np.array([2, 8, 3, 7, 8, 1])
# y should be sorted for both of these methods
order = y.argsort()
y = y[order]
x = x[order]
def what_is_x_when_y_is(input, x, y):
return x[y.searchsorted(input, 'left')]
def interp_x_from_y(input, x, y):
return np.interp(input, y, x)
print what_is_x_when_y_is(7, x, y)
# 3
print interp_x_from_y(1.5, x, y)
# 2.5
You could use the bisect module for this. This is pure python - no numpy here:
>>> x = [0, 1, 2, 3, 4.5, 5]
>>> y = [2, 8, 3, 7, 8, 1]
>>> x_lookup = sorted(zip(x, y))
>>> y_lookup = sorted(map(tuple, map(reversed, zip(x, y))))
>>>
>>> import bisect
>>> def pair_from_x(x):
... return x_lookup[min(bisect.bisect_left(x_lookup, (x,)), len(x_lookup)-1)]
...
>>> def pair_from_y(y):
... return tuple(reversed(y_lookup[min(bisect.bisect_left(y_lookup, (y,)), len(y_lookup)-1)]))
...
And some examples of using it:
>>> pair_from_x(0)
(0, 2)
>>> pair_from_x(-2)
(0, 2)
>>> pair_from_x(2)
(2, 3)
>>> pair_from_x(3)
(3, 7)
>>> pair_from_x(7)
(5, 1)
>>>
>>> pair_from_y(0)
(5, 1)
>>> pair_from_y(1)
(5, 1)
>>> pair_from_y(3)
(2, 3)
>>> pair_from_y(4)
(3, 7)
>>> pair_from_y(8)
(1, 8)
The way you described is, as far as I'm considered, a good way. I'm not sure if you are, but I think you could use the .index(...) method on your array:
>>> li
['I', 'hope', 'this', 'answer', 'helps', 'you']
>>> li.index("hope")
1
Other than that, you might want to consider one array op "Points" which have an x and a y, though I'm not sure if this is possible of course. That way you won't have to keep two arrays in sync (same number of elements).
I don't see any problem with your pipeline. You can write a snippet base on numpy.where to implement it efficiently. Note that you will have to pass your lists as numpy arrays first (this can be included in the function).
Below is an example of a function doing the job, with an option to round the target (I have included a which array argument, so everything can be done in just one function, whatever you want to search in x or y). Note that one of the output will be a numpy array, so modify it to convert it to anything you want (liste, tuple, etc ...).
import numpy as np
def pick(x_array, y_array, target, which_array='x', round=True):
# ensure that x and y are numpy arrays
x_array, y_array = np.array(x_array), np.array(y_array)
# optional: round to the nearest. True by default
if round==True:
target = np.round(target)
if which_array == 'x': # look for the target in x_array
return target, y_array[np.where(x_array == target)[0]]
if which_array == 'y': # look for the target in y_array
return x_array[np.where(y_array == target)[0]], target
Results given by your examples:
# >>> what_is_y_when_x_is(2)
pick(x, y, 2, 'x')
(2, array([3]))
# >>> what_is_y_when_x_is(3.1)
pick(x, y, 3.1, 'x')
3.0, array([7]))
# >>> what_is_y_when_x_is(2)
pick(x, y, 2, 'y')
(array([ 0.]), 2)
# >>> what_is_x_when_y_is(max(y))
pick(x, y, max(y), 'y')
(array([ 1. , 4.5]), 8)
Here is a revised version of code provided by # Bi Rico:
import numpy as np
x = np.array([0, 1, 2, 3, 4.5, 5])
y = np.array([2, 8, 3, 7, 8, 1])
# y should be sorted for both of these methods
order = np.argsort(y)
y = y[order]
x = x[order]
def what_is_x_when_y_is(input, x, y):
return x[y.searchsorted(input, 'left')]
print(what_is_x_when_y_is(7, x, y))
# 3
This worked for me:
def what_is_y_when_x_is(value, x, y, tolerance=1e-3):
return [(xi, yi) for (xi, yi) in zip(x, y) if abs(xi - value) <= tolerance]
Notice that rather than comparing for equality the code above performs a "close enough" equality test. The default tolerance is set up to 0.001 (you can use any other value). Here are some examples of use:
>>> x = [0, 1, 2, 3, 4.5, 5]
>>> y = [2, 8, 3, 7, 8, 1]
>>> what_is_y_when_x_is(0, x, y)
[(0, 2)]
>>> what_is_y_when_x_is(1, x, y, tolerance=.1)
[(1, 8)]
>>> what_is_y_when_x_is(2, x, y, tolerance=1)
[(1, 8), (2, 3), (3, 7)]
>>> what_is_y_when_x_is(4, x, y, tolerance=.5)
[(4.5, 8)]