Numpy -在网格上高效地计算函数(一维数组)

x3naxklr  于 2023-08-05  发布在  其他
关注(0)|答案(1)|浏览(84)

所以我有一个函数f(x),其中参数x是一个行数组,维度为k。该函数可以给定一个行数>1的数组,并被优化为对数组进行逐行操作,显然比迭代数组行并调用该函数要快得多。现在我想把这个函数应用到一个覆盖k维空间的网格上。假设k维= 3。然后,

N_DIV = 2
x0 = np.linspace(0,1,N_DIV)
x1 = np.linspace(0,1,N_DIV)
x2 = np.linspace(0,1,N_DIV)

字符串
我想计算所有组合的函数

x0  x1  x2
0   0   0
0   0   0.5
0   0.5 0
0   0.5 0.5


等等。
我想用np.meshgrid

xx, yy, zz = np.meshgrid(x0,x1,x2)


但接下来呢残酷的方法

prev_array=no.array([0,0,0])
for i in range(N_DIV):
    for j in range(N_DIV):
        for k in range(N_DIV):
            prev_array = np.vstack((prev_array, 
                                    np.array([xx[i,j,k],yy[i,j,k],zz[i,j,k]])))


不可能是正确的,请给我一些建议。我想在覆盖k维空间的网格上有效地计算函数f,谢谢 * 编辑
帖子Evaluate function on a grid of points被建议作为一个解决方案,但我看不出它如何回答我的问题。它们有两个标量变量的f(x,y),我看到了result = func(xaxis[:,None], yaxis[None,:])的想法。但是我的函数需要一个行向量作为输入,所以{x,y},因此上面的想法似乎不直接适用,至少对我来说,再次感谢

  • 背景-我正在努力实现 *

假设我有一个3变量的函数

def func(x,y,z):
    return x**3 - 3*y + z**2


我想把它画成(x,y)的函数,z是固定值。
我能做的

N_DIV = 30
x =np.linspace(0,5,N_DIV)
y =np.linspace(0,5,N_DIV)
z =np.linspace(0,5,N_DIV)
xx , yy, zz = np.meshgrid(x,y,z)
W = func(xx,yy,zz)
import matplotlib.pyplot as plt
# Plot the surface
fig, ax = plt.subplots(subplot_kw={"projection": "3d"})
surf = ax.plot_surface(xx[:,:,1],yy[:,:,1],W[:,:,1], cmap="Spectral",
                       linewidth=0)

plt.show()


worls罚款和重复的功能评估是快速的。但是,如果函数定义为

def func_vect(x):
    return x[0]**3 - 3*x[1] + x[2]**2


如何达到同样的效果?也就是说,创建一个输出结果的数组W,准备像以前一样使用它绘图?
蛮力方法是通过循环来创建它,但我也对以下内容感到困惑

def func2(x,y):
    return x**3 - 3*y 
xx2 , yy2 = np.meshgrid(x,y)
W2 = func2(xx2,yy2)
W2_loop = np.zeros((N_DIV, N_DIV))
for i in range(N_DIV):
    for j in range(N_DIV):
            W2_loop[i,j] = func2(x[j],y[i])
np.isclose(W2,W2_loop)


返回所有True,但我不知道如何使其在三维中工作,因为(* 第二个基本问题 *)

W_loop = np.zeros((N_DIV, N_DIV,N_DIV))
for i in range(N_DIV):
    for j in range(N_DIV):
        for k in range(N_DIV):
            W_loop[i,j,k] = func(x[k],y[j],z[i])


与上面创建的W不同。
谢啦,谢啦

nzkunb0c

nzkunb0c1#

首先,重复使用vstack非常糟糕。如果必须迭代地构建数组,请使用list和list.append。

In [134]: N_DIV = 2
     ...: x0 = np.linspace(0,1,N_DIV)
     ...: x1 = np.linspace(0,1,N_DIV)
     ...: x2 = np.linspace(0,1,N_DIV)

字符串
您的3个网格阵列:

In [136]: a,b,c = np.meshgrid(x0,x1,x2, indexing='ij')
In [137]: a,b,c
Out[137]: 
(array([[[0., 0.],
         [0., 0.]],
 
        [[1., 1.],
         [1., 1.]]]),
 array([[[0., 0.],
         [1., 1.]],
 
        [[0., 0.],
         [1., 1.]]]),
 array([[[0., 1.],
         [0., 1.]],
 
        [[0., 1.],
         [0., 1.]]]))


np.stack,像np.array一样,可以将它们组合在新的前导轴上。

In [138]: np.stack((a,b,c)).shape
Out[138]: (3, 2, 2, 2)


但是你想让3成为最后一个轴:

In [139]: np.stack((a,b,c),axis=-1).shape
Out[139]: (2, 2, 2, 3)


因此,让我们将其重塑为(n,3)数组:

In [140]: np.stack((a,b,c),axis=-1).reshape(-1,3)
Out[140]: 
array([[0., 0., 0.],
       [0., 0., 1.],
       [0., 1., 0.],
       [0., 1., 1.],
       [1., 0., 0.],
       [1., 0., 1.],
       [1., 1., 0.],
       [1., 1., 1.]])


另一个工具是

In [142]: from itertools import product

In [144]: list(product(x0,x1,x2))
Out[144]: 
[(0.0, 0.0, 0.0),
 (0.0, 0.0, 1.0),
 (0.0, 1.0, 0.0),
 (0.0, 1.0, 1.0),
 (1.0, 0.0, 0.0),
 (1.0, 0.0, 1.0),
 (1.0, 1.0, 0.0),
 (1.0, 1.0, 1.0)]


meshgrid的一个变体是mgrid

In [153]: idx = 1j*N_DIV
In [156]: np.mgrid[0:1:idx,0:1:idx,0:1:idx].reshape(3,-1).T
Out[156]: 
array([[0., 0., 0.],
       [0., 0., 1.],
       [0., 1., 0.],
       [0., 1., 1.],
       [1., 0., 0.],
       [1., 0., 1.],
       [1., 1., 0.],
       [1., 1., 1.]])


您是否考虑过利用broadcastingmeshgrid可以生成“稀疏”数组:

In [162]: a,b,c =np.meshgrid(x0,x1,x2,indexing='ij',sparse=True)
In [163]: a,b,c
Out[163]: 
(array([[[0.]],
 
        [[1.]]]),
 array([[[0.],
         [1.]]]),
 array([[[0., 1.]]]))


ix_可以产生相同的:

In [164]: a,b,c =np.ix_(x0,x1,x2)


它们可以与“常规”meshgrid数组完全相同的方式使用,例如将它们添加到(2,2,2)数组中:

In [165]: a*100+b*10+c
Out[165]: 
array([[[  0.,   1.],
        [ 10.,  11.]],

       [[100., 101.],
        [110., 111.]]])

编辑

您的最新示例,每个维度具有不同的尺寸:

In [222]: N_DIV = 30
     ...: x =np.linspace(0,5,N_DIV//2)
     ...: y =np.linspace(0,5,N_DIV)
     ...: z =np.linspace(0,5,N_DIV*2)
In [223]: a,b,c =np.ix_(x,y,z)
In [224]: V = a**3 - 3*b + c**2
In [225]: V.shape
Out[225]: (15, 30, 60)

相关问题