Q1) Numpy函数可以采用不同形状的参数。例如,np.sum(V)可以采取以下两种方式之一,并返回不同形状的输出。
x1= np.array( [1,3] ) #(1)
x2= np.array([[[1,2],[3,4]], [[5,6],[7,8]]]) #(2)我正在做我自己的函数,如下所示,它在一个长度为2的一维向量中添加两个值,并返回实数。
def foo(V):
return V[0]+V[1];但是,这个foo函数只能接受一个一维矢量,不能采取任何其他形状。它只能将上面的x1作为一个参数,而不能将x2作为一个参数。如果我想让我的函数与上面的两个变量(x1和x2)中的任何一个一起工作,或者在最后一个维度中具有长度为2的数组的任何其他形状,我应该如何修改foo函数?
我最初的函数是一个硬编码的负高斯pdf函数。
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的基本数组。
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,)。在这种情况下,维数不同的空空间的含义是否不同?
提前,谢谢你的帮助。
发布于 2016-09-27 03:22:29
对于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]])这同样适用于一维数组:
>>> 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)发布于 2016-09-27 03:24:47
您的函数适用于这两个数组:
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]])诉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]: 5Numpy:为什么(2,1)数组和垂直矩阵片的差异不是(2,1)数组
=====================
与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 dim上迭代,将每个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会话是必不可少的;允许我用小样本数组来尝试一些想法。
发布于 2016-09-27 02:52:54
对于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
https://stackoverflow.com/questions/39715227
复制相似问题