Creating a function that can take arguments in various forms

Q1) Numpy functions can take arguments in various forms. For example, np.sum (V) can take one of the two below and return outputs with different forms.

x1= np.array( [1,3] ) #(1)
x2= np.array([[[1,2],[3,4]], [[5,6],[7,8]]]) #(2)

I make my own function, as shown below, which adds two values ​​to a 1D vector with a length of two and returns a real number.

def foo(V):
    return V[0]+V[1];

However, this foo function can only take one 1D vector and cannot take any other form. It can only take x1 as an argument, but not x2. If I want my function to work with either of the two variables above (x1 and x2) or with any other shapes with arrays of length 2 in their last dimension, how do I reconsider my foo function?


--------------------------- update ------------------- --- --------

My original function was a hard-coded negative Gaussian pdf function.

def nGauss(X, mu, cov):
    # multivariate negative gaussian.    
    # mu is a vector and cov is a covariance matrix.

    k = X.shape[0];
    dev = X-mu
    p1 = np.power( np.power(np.pi * 2, k) , -0.5);
    p2 = np.power( np.linalg.det(cov)  , -0.5)
    p3 = np.exp( -0.5 * np.dot( np.dot(dev.transpose(), np.linalg.inv(cov)), dev));

    return -1.0 * p1 * p2 * p3;

Now its function can return only one pdf value. For example, it can only accept arguments such as np.array ([1,2]), but it cannot accept X arguments such as np.array ([[[1,2], [5,6]], [ [7.8], [9.0]]]). Here my question was how to make my Gaussian function accept arbitrary form arguments and return the pdf value of each point that supports the same structure, except for the last measurement, for example nGauss(np.array( [1,2] ), mu, cov)returns [0.000023] and nGauss(np.array([[[1,2], [5,6]], [[7,8],[9,0]]]), mu, cov)returns [[0.000023, 0000014], [0.000012, 0.000042]].

I notice that the scipy function "multivariate_normal.pdf" can do this.


Q2) It is also difficult for me to understand the underlying np array.

t1=np.array([[1,2,3], [4,5,6]])
t2=np.array([1,2,3])
t3=np.array([[1,2,3], [4,5,6],5])

t1 (2,3), ; 2 3 . t2 (3,), , , (3). "3"? , t3 (3,). , ?

.

+4
3

Q1 , , , . - . :

>>> a = np.arange(24).reshape((3, 4, 2))
>>> a
array([[[ 0,  1],
        [ 2,  3],
        [ 4,  5],
        [ 6,  7]],

       [[ 8,  9],
        [10, 11],
        [12, 13],
        [14, 15]],

       [[16, 17],
        [18, 19],
        [20, 21],
        [22, 23]]])
>>> a[..., 0]
array([[ 0,  2,  4,  6],
       [ 8, 10, 12, 14],
       [16, 18, 20, 22]])
>>> a[..., 1]
array([[ 1,  3,  5,  7],
       [ 9, 11, 13, 15],
       [17, 19, 21, 23]])
>>> a[..., 0] + a[..., 1]
array([[ 1,  5,  9, 13],
       [17, 21, 25, 29],
       [33, 37, 41, 45]])

1D:

>>> a = np.array([1, 2])
>>> a[..., 0] + a[..., 1]
3

, foo :

def foo(V):
    return V[..., 0] + V[..., 1]

nGauss np.apply_along_axis. , :

>>> np.apply_along_axis(nGauss, -1, x1, mu, cov)
+1

:

In [1]: def foo(V):
   ...:     return V[0]+V[1]
   ...: 
In [2]: foo(np.array([1,3]))
Out[2]: 4
In [3]: foo(np.array([[[1,2],[3,4]], [[5,6],[7,8]]]))
Out[3]: 
array([[ 6,  8],
       [10, 12]])

:

In [4]: np.array([[[1,2],[3,4]], [[5,6],[7,8]]])[0]
Out[4]: 
array([[1, 2],
       [3, 4]])
In [5]: np.array([[[1,2],[3,4]], [[5,6],[7,8]]])[1]
Out[5]: 
array([[5, 6],
       [7, 8]])

- , .

:

In [6]: t1=np.array([[1,2,3], [4,5,6]])
   ...: t2=np.array([1,2,3])
   ...: t3=np.array([[1,2,3], [4,5,6],5])
   ...: 
In [7]: t1.shape
Out[7]: (2, 3)
In [8]: t2.shape
Out[8]: (3,)
In [9]: t3.shape
Out[9]: (3,)

(3,) - 1 . .

In [11]: (3)
Out[11]: 3
In [12]: (3,)
Out[12]: (3,)

(3,) v (3,1) np.array([[1,2,3]]) v. np.array([1,2,3]).

t3 - dtype, 3 . 3 , 2d. . .

In [10]: t3
Out[10]: array([[1, 2, 3], [4, 5, 6], 5], dtype=object)
In [13]: t3[0]
Out[13]: [1, 2, 3]
In [14]: t3[2]
Out[14]: 5

Numpy: (2,1) (2,1)

Numpy?

=====================

nGauss:

In [53]: mu=np.array([0,0])
In [54]: cov=np.eye(2)
In [55]: xx=np.array([[[1,2], [5,6]], [[7,8],[9,0]]])
In [56]: np.apply_along_axis(nGauss, -1, xx, mu, cov)
Out[56]: 
array([[ -1.30642333e-02,  -9.03313360e-15],
       [ -4.61510838e-26,  -4.10103631e-19]])

apply_along_axis 1- 2- , xx[i,j,:] nGauss. , .

k = X.shape[0];  # I assume you want
k = X.shape[[1]   # the last dimension
dev = X-mu     # works as long as mu has k terms

:

p1 = np.power( np.power(np.pi * 2, k) , -0.5);

p2 = np.power( np.linalg.det(cov)  , -0.5)

, :

p3 = np.exp( -0.5 * np.dot( np.dot(dev.transpose(), np.linalg.inv(cov)), dev));

(2,) x dev 1d, dev.transpose() .

einsum dot; , :

p3 = np.einsum('j,j', np.einsum('i,ij', dev, np.linalg.inv(cov)), dev)
p3 = np.exp( -0.5 * p3)

p3 = np.einsum('i,ij,j', dev, np.linalg.inv(cov), dev)

dim:

p3 = np.einsum('...i,ij,...j', dev, np.linalg.inv(cov), dev)

,

def nGaussA(X, mu, cov):
    # multivariate negative gaussian.    
    # mu is a vector and cov is a covariance matrix.

    k = X.shape[-1];
    dev = X-mu
    p1 = np.power( np.power(np.pi * 2, k) , -0.5);
    p2 = np.power( np.linalg.det(cov)  , -0.5)
    p3 = np.einsum('...i,ij,...j', dev, np.linalg.inv(cov), dev)
    p3 = np.exp( -0.5 * p3)
    return -1.0 * p1 * p2 * p3;

:

In [85]: nGaussA(x,mu,cov)
Out[85]: -0.013064233284684921
In [86]: nGaussA(xx,mu,cov)
Out[86]: 
array([[ -1.30642333e-02,  -9.03313360e-15],
       [ -4.61510838e-26,  -4.10103631e-19]])

, - . , . x, . , numpy, . . numpy, , (, apply_along_axis, apply_over_axes, cross ..).

numpy ; .

+2

Q1 :

def foo(*args):

    result = []
    for v in args:
        result.append(v[0] + v[1])

    return result

, , , . kwargs **. :

https://docs.python.org/2/tutorial/controlflow.html#unpacking-argument-lists

+1
source

Source: https://habr.com/ru/post/1655905/


All Articles