gpt4 book ai didi

python - 制作一个可以接受各种形状参数的函数

转载 作者:太空狗 更新时间:2023-10-30 02:56:41 25 4
gpt4 key购买 nike

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] 这样接受参数 X ],[9,0]]])。在这里我的问题是如何让我的高斯函数接受任意形状的参数并返回每个点的 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]].

我注意到 scipy 函数“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,)。在这种情况下,维度变化的空间的意义是什么?

预先感谢您的帮助。

最佳答案

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

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 个输入的长度不同,因此无法创建二维数组。暂时远离这种类型的阵列。专注于更简单的数组。

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: Why is difference of a (2,1) array and a vertical matrix slice not a (2,1) array

Difference between single and double bracket Numpy array?

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

使用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 在 1st 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() 什么都不做。

泛化einsumdot更容易;我认为等同于:

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)

泛化到更高的暗淡:

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_axisapply_over_axescross 等)。

交互式 numpy session 是必不可少的;允许我尝试使用小样本阵列的想法。

关于python - 制作一个可以接受各种形状参数的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39715227/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com