Python/小动物:numpy.apply_沿着_axis传递了错误的kwargs(参数太多)

quhf5bfb  于 2023-03-12  发布在  Python
关注(0)|答案(2)|浏览(135)

我尝试做一个简单的模拟器随机微分方程(SDEs)的基础上伊藤过程。在这样做,我尝试做一个1D模拟器如下:

def sde_euler_1(t0: float, x0: float, T: float, M: int, a, b):
    t = np.zeros(shape=M+1)
    t[0] = t0
    x = np.zeros(shape=(M+1))
    x[0] = x0
    dt = T / M

    for j in range(M):
        t[j+1] = t[j] + dt
        dW = np.random.normal(loc=0, scale=1.0, size=1)
        x[j+1] = x[j] + a(t[j], x[j]) * dt + b(t[j], x[j]) * dW * np.sqrt(dt)

    return x

其中ab是如下所示的__main__-函数,指定它们是为了模拟几何布朗运动(GBM)。
然而,模拟SDE有许多不同的方法,并且经常有人想要重复模拟N次以执行蒙特卡罗积分(估计)。因此,我尝试创建一个函数,该函数使用numpy.apply_along_axis以执行此操作。它是这样定义的

def mc_sim(t0: float, x0: float, T: float, M: int, N: int, a, b, sde_method, seed: int = 0):
    if seed > 0:
        np.random.seed(seed=seed)
    x = np.zeros(shape=(M+1, N))
    x = np.apply_along_axis(func1d=sde_method, axis=0, arr=x,
                            t0=t0, x0=x0, T=T, M=M, a=a, b=b)

    return x

我的问题是,当我运行下面的代码(__main__-函数),然后我得到以下错误:
类型错误:sde_euler_1()获取了参数“t0”的多个值
在我看来,我传递了函数中使用的6个参数,但仍然得到了错误。

if __name__ == "__main__":    
    def a(t, x):
        return 0.07 * x

    def b(t, x):
        return 0.2 * x

    t0 = 0.0
    x0 = 100
    T = 5.0
    N = 10
    M = 250
    seed = 1

    t = np.linspace(start=t0, stop=T, num=M+1)
    y = mc_sim(t0=t0, x0=x0, T=T, M=M, N=N, a=a, b=b, sde_method=sde_euler_1, seed=seed)
    plt.plot(t, y)
    plt.show()

**EDIT:**我相信使用numpy.apply_along_axis应该可以得到一个解决方案,我仍然希望得到任何建议来修复上面提到的错误。但是,也可以在mc_sim中使用列表解析来调用函数:

def mc_sim(t0: float, x0: float, T: float, M: int, N: int, a, b, sde_method, seed: int = 0):
    if seed > 0:
        np.random.seed(seed=seed)
    x = np.zeros(shape=(M+1, N))
    x[:, :] = np.array([sde_euler_1(t0=t0, x0=x0, T=T, M=M, a=a, b=b) for i in range(N)]).T
    #x = np.apply_along_axis(sde_method, 0, x, t0=t0, x0=x0, T=T, M=M, a=a, b=b)

    return x

这个解决方案比使用sde_euler-simulator的矢量化版本要慢得多,但是我希望使用np.apply_along_axis比列表解析要快。

mfpqipee

mfpqipee1#

Python不是类型安全的,所以在函数中显式定义一个类型纯粹是为了参考,记住这一点,因为错误直接与t0有关,尝试将其定义为0而不是0.0。
看看这是否解决了您的问题,或提供了一个不同的错误。

o2gm4chl

o2gm4chl2#

正如我所说,apply不是一个性能工具,但我也怀疑您不了解它实际上是做什么的。
为了举例说明,我们定义一个简单的函数,注意打印出来的内容,帮助我们了解发生了什么。

def foo(to, a, b):
    print(to,a,b)
    return to*2

In [3]: x = np.arange(12).reshape(3,4)

In [10]: np.apply_along_axis(foo, 0, x, 'astring',[1,2,3])
[0 4 8] astring [1, 2, 3]
[1 5 9] astring [1, 2, 3]
[ 2  6 10] astring [1, 2, 3]
[ 3  7 11] astring [1, 2, 3]
Out[10]: 
array([[ 0,  2,  4,  6],
       [ 8, 10, 12, 14],
       [16, 18, 20, 22]])

等效列表理解:

In [11]: np.array([foo(x[:,i],'astring',[1,2,3]) for i in range(x.shape[1])])
[0 4 8] astring [1, 2, 3]
[1 5 9] astring [1, 2, 3]
[ 2  6 10] astring [1, 2, 3]
[ 3  7 11] astring [1, 2, 3]
Out[11]: 
array([[ 0,  8, 16],
       [ 2, 10, 18],
       [ 4, 12, 20],
       [ 6, 14, 22]])

两者都将x传递到foo,一次传递一列。
我定义了一个带有3个参数的函数。applyx的列作为第一个参数传递,并将另一个2原样传递。
我本来可以用np.apply_along_axis(foo, 0, x, a='astring',b=[1,2,3])的。
但是如果我尝试传递一个to,我会得到(显示FULL错误消息):

In [13]: np.apply_along_axis(foo, 0, x, to=x, a='astring',b=[1,2,3])
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[13], line 1
----> 1 np.apply_along_axis(foo, 0, x, to=x, a='astring',b=[1,2,3])

File <__array_function__ internals>:180, in apply_along_axis(*args, **kwargs)

File ~\miniconda3\lib\site-packages\numpy\lib\shape_base.py:379, in apply_along_axis(func1d, axis, arr, *args, **kwargs)
    375 except StopIteration as e:
    376     raise ValueError(
    377         'Cannot apply_along_axis when any iteration dimensions are 0'
    378     ) from None
--> 379 res = asanyarray(func1d(inarr_view[ind0], *args, **kwargs))
    381 # build a buffer for storing evaluations of func1d.
    382 # remove the requested axis, and add the new ones on the end.
    383 # laid out so that each write is contiguous.
    384 # for a tuple index inds, buff[inds] = func1d(inarr_view[inds])
    385 buff = zeros(inarr_view.shape[:-1] + res.shape, res.dtype)

TypeError: foo() got multiple values for argument 'to'

第一个自变量toapply提供作为其迭代的一部分;不是它能穿过的东西。
同样在np.array([sde_euler_1(t0=t0, x0=x0, T=T, M=M, a=a, b=b) for i in range(N)])中,你没有使用i迭代变量或者迭代任何东西,你只是运行sde_euler_1N次,这不是apply的目的。

相关问题