I have a multi-inputs function, say:
def bla(a, b):
f = a + b
return f
When I do something like
import numpy as np
bla(np.asarray([0.2,0.4]), np.asarray([2,4]))
The result is:
array([ 2.2, 4.4])
However, I want bla to be applied to each possible pair of my inputs(bla(0.2, 2), bla(0.2, 4), bla(0.4, 2), bla(0.4, 4)) and obtain the final result as a 2-D matrix. In this example, I want the result to be:
array([[2.2, 4.2],
[2.4, 4.4]
])
How can I do this?
My original problem is that I have a function with three variables and one output, then I want to call the function by entering vectors for each variable so that I obtain a 3-D matrix as a result
Provided your function bla can accept arrays instead of scalars, you could use
meshgrid to prepare the inputs so that bla(A, B) returns the desired output:
import numpy as np
def bla(a, b):
f = a + b
return f
A, B = np.meshgrid([0.2,0.4], [2,4], sparse=True)
bla(A, B)
yields
array([[ 2.2, 2.4],
[ 4.2, 4.4]])
Not sure if you want to do this without modifying bla(), but for your example at least that's where the change must be:
def bla(a, b):
return np.asarray(a+n for n in b)
This operates on array a with each element of b, and builds an array with the results. Your example looks a little random (how did you get those .3 fractional parts?), but I'm guessing this is what you're trying to get at.
Related
Recently I came across some codes that look like this:
a = np.divide(np.subtract(b, c), np.add(d, e))
In which a, b, c, d, e are all np.ndarray. This code line looks harder-to-understand compared to
a = (b-c)/(d+e)
Is there any advantage of using np.add(), np.divide(), etc. compared to +, /, etc. ?
Thanks so much.
numpy.add docs says that
The + operator can be used as a shorthand for np.add on ndarrays.
Is there any advantage of using np.add(), np.divide(), etc. compared to +, /, etc. ?
np.add is first class citizien, so you might for example do
def myfunction(arr1, arr2, action):
return action(arr1,arr2)
and used it like
import numpy as np
a = np.array([1,2,3])
b = np.array([4,5,6])
total = myfunction(a,b,np.add)
rather than doing something like
def myfunction(arr1, arr2, action):
if action=="+":
return arr1 + arr2
elif action=="/":
return arr1 / arr2
...
Please also note that if arguments are not numpys array you might other result than using just +, e.g.
import numpy as np
a = [1,2,3]
b = [4,5,6]
print(a+b) # [1, 2, 3, 4, 5, 6]
print(np.add(a,b)) # [5 7 9]
Let's say I have a 2-d tensor:
x = torch.Tensor([[1, 2], [3, 4]])
Is there an efficient way to apply one function to the first 'row' [1, 2] and apply a second different function to the second row [3, 4]? (Doesn't have to be a row, could be across any dimension)
At the moment, I use the following code: Say I have my two functions, f and g, for example,
def f(z):
return 2 * z
def g(z):
return 0.5 * z
Then, to apply them to seperate rows I would do:
torch.cat([f(x[0]).unsqueeze(0), g(x[1]).unsqueeze(0)], dim = 0)
which gives the desired tensor [[2, 4], [1.5, 2]].
Obviously, in this 2-d example this solution is fine, but it seems a bit clunky. Is there a better way of doing this? Particularly in higher dimensions or when there are a large number of elements in the chosen dimension
A handy tip is to slice instead of selecting to avoid the unsqueeze step. Indeed, notice how x[:1] keeps the indexed dimension compared to x[0].
This way you can perform the desired operation in a slightly shorter form:
>>> torch.vstack((f(x[:1]), g(x[1:])))
Optionally you can use vstack to not have to provide dim=0 to torch.stack.
Alternatively, you can use a helper function that will apply both f and g:
>>> fn = lambda a,b: (f(a), g(b))
And split the tensor inline with torch.Tensor.split:
>>> torch.vstack(fn(*x.split(1)))
I am trying to compute many dot products efficiently. This post gets really close to what I am trying to do, but I can't quite get it to work. I have a large list of matrices (a), and a list of vectors (b). I want to do a series of dot product operations between them. This is what works now:
import numpy as np
a # shape (15000,4,4)
b # shape (15000,4)
out = np.empty((15000,4))
for i in range(15000):
out[i] = np.dot(a[i],b[i])
All my attempts to adapt np.tensordot or np.einsum from the linked post have failed to give me what I want. If anyone sees how to do this I would really appreciate it.
Einstein summation works just fine:
>>> a = np.random.randn(100, 4, 4)
>>> b = np.random.randn(100, 4)
>>> foo = np.einsum('ijk,ik->ij', a, b)
>>> bar = np.zeros_like(foo)
>>> for i, (ai, bi) in enumerate(zip(a, b)):
bar[i] = np.dot(ai, bi)
>>> np.allclose(foo, bar)
True
To explain the summation a bit, note that you're contracting the last axis of b. So you can think about doing each inner product as if by np.einsum('jk,k->j', a[0], b[0]). But we're doing one for each element of a and b, thus the inclusion of the first axis, which is not contracted. Hence, ijk,ik->ij.
I wonder if you can define a function to act on all elements of a 1-D numpy array simultaneously, so that you don't have to loop over the array. Similar to the way you can, for example, square all elements of an array without looping. An example of what I'm after is to replace this code:
A = np.array([ [1,4,2], [5,1,8], [2,9,5], [3,6,6] ])
B = []
for i in A:
B.append( i[0] + i[1] - i[2] )
B = array(B)
print B
Output:
>>> array([3, -2, 6, 3])
With something like:
A = np.array([ [1,4,2], [5,1,8], [2,9,5], [3,6,6] ])
def F(Z):
return Z[0] + Z[1] - Z[2]
print F(A)
So that the output is something like:
>>> array( [ [3] , [-2], [6], [3] ] )
I know the 2nd code won't produce what I'm after, but I'm just trying to give an idea of what I'm talking about. Thanks!
EDIT:
I used the function above just as a simple example. The real function I'd like to use is something like this:
from numpy import linalg as LA
def F(Z):
#Z is an array of matrices
return LA.eigh(Z)[0]
So I have an array of 3x3 matrices, and I'd like an output array of their eigenvalues. And I'm wondering if it's possible to do this in some numpythonic way, so as not to have to loop over the array.
Try:
np.apply_along_axis(F, 1, A)
I want to repeatedly sum over varying dimensions of a numpy ndarray eg.
#what I've got
sumOverDims = [6 4 2 1]
ndarray = any n-dimensional numpy array
#what I want to do
ndarray.sum(6).sum(4).sum(2).sum(1)
how can I do this without an ugly loop?
Numpy's sum accepts a tuple for the axis argument:
ndarray.sum(axis=(1,2,4,6))
In general, a thing like
X.f(e0).f(e1).f(e2).…
can be rephrased as
reduce(lambda a, b: a.f(b), [ e0, e1, e2, … ], X)
or (if you dislike lambdas):
def f_(a, b): return a.f(b)
reduce(f_, [ e0, e1, e2, … ], X)
But I'm a bit in doubt if this really makes it more readable and effectively clearer (and thus more Pythonic) than using an iterative loop:
result = X
for e in [ e0, e1, e2, … ]:
result = result.f(e)
return result
I guess it boils down to a matter of taste and what you are more used to.
You could use reduce. An example with only two dimensions:
>>> A = numpy.array([[1,2,3],[4,5,6],[7,8,9]])
>>> reduce(numpy.sum, [1], A)
array([ 6, 15, 24])
>>> reduce(numpy.sum, [1, 0], A)
45
The argument to reduce is numpy's sum function, a list with the dimensions to sum over, and the numpy array A as the initial element to reduce. The function gets as parameter the (partially summed) numpy array and the dimension to sum next.