首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >创建一个可以接受各种形状的参数的函数

创建一个可以接受各种形状的参数的函数
EN

Stack Overflow用户
提问于 2016-09-27 02:45:46
回答 3查看 829关注 0票数 4

Q1) Numpy函数可以采用不同形状的参数。例如,np.sum(V)可以采取以下两种方式之一,并返回不同形状的输出。

代码语言:javascript
复制
x1= np.array( [1,3] ) #(1)
x2= np.array([[[1,2],[3,4]], [[5,6],[7,8]]]) #(2)

我正在做我自己的函数,如下所示,它在一个长度为2的一维向量中添加两个值,并返回实数。

代码语言:javascript
复制
def foo(V):
    return V[0]+V[1];

但是,这个foo函数只能接受一个一维矢量,不能采取任何其他形状。它只能将上面的x1作为一个参数,而不能将x2作为一个参数。如果我想让我的函数与上面的两个变量(x1和x2)中的任何一个一起工作,或者在最后一个维度中具有长度为2的数组的任何其他形状,我应该如何修改foo函数?

我最初的函数是一个硬编码的负高斯pdf函数。

代码语言:javascript
复制
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;

现在他的函数只能返回一个pdf值。例如,它只能接受像np.array(1,2)这样的参数,但不能像np.array([[1,2,5,6],[7,8,9,0])那样接受参数X。在这里,我的问题是如何使我的高斯函数接受任意形状的参数,并返回保持相同结构的每个点的pdf值,例如nGauss(np.array( [1,2] ), mu, cov)返回0.000023,nGauss(np.array([[[1,2], [5,6]], [[7,8],[9,0]]]), mu, cov)返回[ 0.000023,0000014,0.000012,0.000042]。

我注意到can函数'multivariate_normal.pdf‘可以做到这一点。

Q2)我也很难理解np的基本数组。

代码语言:javascript
复制
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,)。在这种情况下,维数不同的空空间的含义是否不同?

提前,谢谢你的帮助。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-09-27 03:22:29

对于Q1,我猜您希望添加数组的最内部维度,而不管数组有多少维度。最简单的方法是使用省略索引。下面是一个详细的例子:

代码语言:javascript
复制
>>> 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]])

这同样适用于一维数组:

代码语言:javascript
复制
>>> a = np.array([1, 2])
>>> a[..., 0] + a[..., 1]
3

因此,只需将foo定义为:

代码语言:javascript
复制
def foo(V):
    return V[..., 0] + V[..., 1]

对于nGauss函数,最简单的解决方案是使用np.apply_along_axis。例如,您可以这样称呼它:

代码语言:javascript
复制
>>> np.apply_along_axis(nGauss, -1, x1, mu, cov)
票数 1
EN

Stack Overflow用户

发布于 2016-09-27 03:24:47

您的函数适用于这两个数组:

代码语言:javascript
复制
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]])

这个答案就是这两个数组的总和:

代码语言:javascript
复制
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]])

如果你想要别的东西,你就得给我们看。

至于你的第二个问题:

代码语言:javascript
复制
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元素元组。比较这些表达式。

代码语言:javascript
复制
In [11]: (3)
Out[11]: 3
In [12]: (3,)
Out[12]: (3,)

最近有几个关于(3,) v (3,1)形状数组和np.array([[1,2,3]])np.array([1,2,3])的问题。

t3是一个对象dtype数组,包含3个元素。3输入是不同的长度,所以它不能创建一个2d数组。暂时远离这种类型的数组。关注更简单的数组。

代码语言:javascript
复制
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

代码语言:javascript
复制
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 dim上迭代,将每个xx[i,j,:]传递给nGauss。它不快,但相对容易应用。

代码语言:javascript
复制
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

这是一个标量:

代码语言:javascript
复制
p1 = np.power( np.power(np.pi * 2, k) , -0.5);

也是如此

代码语言:javascript
复制
p2 = np.power( np.linalg.det(cov)  , -0.5)

因此可以归结为对这个表达式的概括:

代码语言:javascript
复制
p3 = np.exp( -0.5 * np.dot( np.dot(dev.transpose(), np.linalg.inv(cov)), dev));

在简单的(2,) x情况下,dev是1d,而dev.transpose()什么也不做。

einsumdot更容易泛化;我认为它的等价性是:

代码语言:javascript
复制
p3 = np.einsum('j,j', np.einsum('i,ij', dev, np.linalg.inv(cov)), dev)
p3 = np.exp( -0.5 * p3)

它简化为

代码语言:javascript
复制
p3 = np.einsum('i,ij,j', dev, np.linalg.inv(cov), dev)

概括到较高的dim:

代码语言:javascript
复制
p3 = np.einsum('...i,ij,...j', dev, np.linalg.inv(cov), dev)

因此,在以下方面:

代码语言:javascript
复制
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;

匹配以前的值:

代码语言:javascript
复制
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_axisapply_over_axescross等)。

一个交互式的numpy会话是必不可少的;允许我用小样本数组来尝试一些想法。

票数 2
EN

Stack Overflow用户

发布于 2016-09-27 02:52:54

对于Q1,您可以打包和解压参数:

代码语言:javascript
复制
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
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39715227

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档