次の方法でPythonで数学的積分を実行したい:
[1] scipy.optimize.fsolve を使用して暗黙の方程式を解き、被積分関数の最大位置を見つけます。
[2] 被積分関数の最大値をゼロにシフトし、scipy.integrate.quad を使用して -10 から 10 まで積分します。
被積分関数には 1 つの自由パラメーター xi があるため、numpy を使用して xi 値の範囲でこれを実行したいので、numpy.vectorize を使用します。
このアルゴリズムをベクトル化するには、次の 2 つの方法があります。
[A] [1] と [2] を別々にベクトル化し、vec_[1] の結果を vec_[2] に入力として与える
[B] [1] と [2] を同時に実行する関数をベクトル化する
[A] は [B] よりもはるかに高速であることに気付きました。コードは次のとおりです。
from scipy import optimize, integrate
import numpy as np
from math import exp, sqrt, pi
import time
def integral_with_fsolve(xi):
xc = optimize.fsolve(lambda x: x+1./(1+exp(-x))-xi,0.)
def integrand(x,xi):
return exp(-(x-xi+xc)**2)/(2.*sqrt(2.*pi))/(1.+exp(x+xc))
integral = integrate.quad(integrand,-10.,10.,args=(xi,),epsabs=0.)
return integral[0]
def integral(xi,xc):
def integrand(x,xi):
return exp(-(x-xi+xc)**2)/(2.*sqrt(2.*pi))/(1.+exp(x+xc))
integral = integrate.quad(integrand,-10.,10.,args=(xi,),epsabs=0.)
return integral[0]
def fsolve(xi):
return optimize.fsolve(lambda x: x+1./(1+exp(-x))-xi,0.)
vec_integral_with_fsolve = np.vectorize(integral_with_fsolve)
vec_integral = np.vectorize(integral)
vec_fsolve = np.vectorize(fsolve)
xi = np.linspace(0.,2.,1000)
t0=time.time()
something = vec_integral_with_fsolve(xi)
dur=(time.time()-t0)
speed = xi.size/dur
print('Integrate and fsolve vectorized in one: speed = {} ints/sec'.format(speed))
t0=time.time()
xc = vec_fsolve(xi)
something = vec_integral(xi,xc)
dur=(time.time()-t0)
speed = xi.size/dur
print('Integrate and fsolve vectorized seperately: speed = {} ints/sec'.format(speed))
出力は常に次のようになります
ベクトル化された積分と fsolve: 速度 = 298.151473998 ints/秒
個別にベクトル化された積分と fsolve: 速度 = 2136.75134429 ints/秒
これは実際の問題の単純化されたバージョンにすぎないため、なぜこのように動作するのかを知る必要があります。誰か説明してくれませんか?ありがとう!