【问题标题】:How can I create an n-dimensional grid in numpy to evaluate a function for arbitrary n?如何在 numpy 中创建一个 n 维网格来评估任意 n 的函数?
【发布时间】:2015-05-03 17:10:25
【问题描述】:

我正在尝试创建一个简单的数值积分函数来说明高维蒙特卡洛积分的好处。我想要这样的东西:

def quad_int(f, mins, maxs, numPoints=100):
    '''
    Use the naive (Riemann sum) method to numerically integrate f on a box 
    defined by the mins and maxs.

    INPUTS:
    f         - A function handle. Should accept a 1-D NumPy array 
        as input.
    mins      - A 1-D NumPy array of the minimum bounds on integration.
    maxs      - A 1-D NumPy array of the maximum bounds on integration.
    numPoints - An integer specifying the number of points to sample in 
        the Riemann-sum method. Defaults to 100.
    '''
    n = len(mins)

    # Create a grid of evenly spaced points to evaluate f on
    # Evaluate f at each point in the grid; sum all these values up
    dV = np.prod((maxs-mins/numPoints))
    # Multiply the sum by dV to get the approximate integral

我知道我的dV 会导致数值稳定性问题,但现在我遇到的问题是创建域。如果维数是固定的,那么像这样使用np.meshgrid 就很容易了:

# We don't want the last value since we are using left-hand Riemann sums
x = np.linspace(mins[0],maxs[0],numPoints)[:-1]
y = np.linspace(mins[1],maxs[1],numPoints)[:-1]
z = np.linspace(mins[2],maxs[2],numPoints)[:-1]

X, Y, Z = np.meshgrid(x,y,z)
tot = 0
for index, x in np.ndenumerate(X):
    tot += f(x, Y[index], Z[index])

是否有类似于np.meshgrid 的类似物可以对任意维度执行此操作,也许可以接受数组元组?还是有其他方法可以在更高维度上进行黎曼和?我曾想过递归地执行此操作,但无法弄清楚它是如何工作的。

【问题讨论】:

    标签: python arrays numpy numerical-integration


    【解决方案1】:

    您可以使用列表推导生成所有linspaces,然后将该列表与* 一起传递给meshgrid(将列表转换为参数元组)。

    XXX = np.meshgrid(*[np.linspace(i,j,numPoints)[:-1] for i,j in zip(mins,maxs)])
    

    XXX 现在是n 数组的列表(每个n 维度)。

    我正在使用直接的 Python 列表和参数操作。

    np.lib.index_tricks 具有其他可能有用的索引和网格生成函数和类。值得一读,看看事情是如何完成的。


    在索引未知维度的数组时,在各种 numpy 函数中使用的巧妙技巧是构造为所需索引的列表。它可以包括slice(None),您通常会看到:。然后将其转换为元组并使用它。

    In [606]: index=[2,3]
    In [607]: [slice(None)]+index
    Out[607]: [slice(None, None, None), 2, 3]
    In [609]: Y[tuple([slice(None)]+index)]
    Out[609]: array([ 0. ,  0.5,  1. ,  1.5])
    In [611]: Y[:,2,3]
    Out[611]: array([ 0. ,  0.5,  1. ,  1.5])
    

    他们在需要更改元素的地方使用列表。并不总是需要转换为元组

    index=[slice(None)]*3
    index[1]=0
    Y[index] # same as Y[:,0,:]
    

    【讨论】:

    • 谢谢,这对于创建域非常有用。切片数组时有没有办法解包元组?也就是说,给定来自np.ndenumerateindex,是否有一种简单的方法可以访问切片X[:,index[0],...,index[n-1]]? 现在我正在使用列表理解,但似乎应该有更快的方法。
    • 我添加了一些索引注释
    猜你喜欢
    • 1970-01-01
    • 2021-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多