我尝试做一个简单的模拟器随机微分方程(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
其中a
和b
是如下所示的__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
比列表解析要快。
2条答案
按热度按时间mfpqipee1#
Python不是类型安全的,所以在函数中显式定义一个类型纯粹是为了参考,记住这一点,因为错误直接与
t0
有关,尝试将其定义为0而不是0.0。看看这是否解决了您的问题,或提供了一个不同的错误。
o2gm4chl2#
正如我所说,
apply
不是一个性能工具,但我也怀疑您不了解它实际上是做什么的。为了举例说明,我们定义一个简单的函数,注意打印出来的内容,帮助我们了解发生了什么。
等效列表理解:
两者都将
x
传递到foo
,一次传递一列。我定义了一个带有3个参数的函数。
apply
将x
的列作为第一个参数传递,并将另一个2原样传递。我本来可以用
np.apply_along_axis(foo, 0, x, a='astring',b=[1,2,3])
的。但是如果我尝试传递一个
to
,我会得到(显示FULL错误消息):第一个自变量
to
由apply
提供作为其迭代的一部分;不是它能穿过的东西。同样在
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_1
N
次,这不是apply
的目的。