Langevin方程式と確率微分方程式
はじめに
Langevin方程式という方程式があります。例えばこんなのです。
ただし、
を満たすような確率変数です。この方程式は、水の中の粒子の運動を表しており、
ただし、
さて、微分方程式を解くとは、微分している変数について積分し、原始関数を求めることです。しかし、この方程式には
積分とは
そもそも積分とはなんだったでしょうか?いま、ある関数
です。この意味は、関数
つまり、
ただし、
ここで、分割は等間隔でなくてもかまいません。
さらに言えば、今は区間
さて、確率微分方程式を積分するためには、確率変数を積分する必要があります。例えば
という微分方程式において、初期条件
を計算する必要があります。これを定義するためには、積分区間を分割し、
みたいなものを考えたくなります。しかし、右辺には確率変数があるため、この和がどういうものかは自明ではありません。一般にはこれはWiener過程として「定義」してしまいますが、これを離散的なランダムウォークからの極限として導いてみましょう。
ランダムウォークと連続極限
以下の確率微分方程式を考えます。
ただし
となります。この右辺はよくわからないので、左辺を考えてみましょう。連続時間・空間だと難しいので、まずは離散時間、離散空間を考えます。毎回コインを投げ、表なら右に、裏なら左に一歩進むランダムウォークを考えます。後で連続極限を取るために、一歩の長さを
です。ただし
を満たします。連続版の確率変数
に従います。この分布の1次と2次のモーメントはすぐにわかります。
さて、
すなわち、ランダムウォークでは平均自乗変位はステップ数に比例します。
さて、試行回数が大きい時、二項分布は同じ期待値、分散を持つ正規分布で良く近似できます。期待値
さて、ランダムウォークにおいて、平均自乗変位
となります[2]。つまり、時刻
離散的なランダムウォークを表す式はこうでした。
0ステップ目から
また、右辺を積分と同一視することで、連続版の
ここで、
さて、
これが欲しかったものでした。ここから、例えば以下のLangevin方程式を数値積分できるようになります。
時間刻みを
ただし、numpy.random.normal(0, h**0.5)
で得ることができます。この積分スキームをEuler-Maruyama法と呼びます。ちょっと試してみましょう。
import numpy as np
from matplotlib import pyplot as plt
from numba import jit
AVE = 1000
N = 100000
NA = N//AVE
h = 0.01
@jit
def additive_euler_maruyama(N):
v = 0
data = []
for _ in range(N):
v += - v * h + np.random.normal(0,np.sqrt(2.0*h))
data.append(x)
return data
additive_euler_maruyama
は、先程の式をそのまま実装したものです。これでdata
に時系列が帰ってくるので、その定常分布を調べてみましょう。
時系列から分布関数を作る関数dist
はこんな感じになります。ソートして累積分布関数を求め、それを微分することで分布関数を求めています(参考:累積分布関数をソートで求める)。ただし、きれいな分布にするために、部分的に平均をとっています。
def dist(data):
d = sorted(data)
d = [np.average(d[i*AVE:(i+1)*AVE]) for i in range(NA)]
t = np.array([i/N for i in range(N)])
t = [np.average(t[i*AVE:(i+1)*AVE]) for i in range(NA)]
d = np.array(d)
t = np.array(t)
x = []
y = []
for i in range(NA-1):
v = (t[i+1] - t[i])/(d[i+1]-d[i])
x.append((d[i+1]+d[i])*0.5)
y.append(v)
return np.array(x),np.array(y)
プロットしてみましょう。
d1, f1 = dist(additive_euler_maruyama(N))
fig, ax = plt.subplots()
theory = np.exp(-d1**2/2)/np.sqrt(3.14*2)
ax.plot(d1,f1)
ax.plot(d1,theory)
fig.show()
ちゃんとガウス分布になっていますね。
Ito積分とStratonovich積分
さて、確率変数
まず、Langevin方程式において、確率変数にかかっている係数が定数である場合、それを相加性ノイズ(additive noise)と呼びます。以下のような方程式の場合は定数なので相加性です。
ここで
ここでは
簡単な相乗過程の例として、こんな式を考えましょう。
ただし、
ここでは短冊の高さとして積分区間の左端を使いましたが、時刻
この極限として定義される積分をStratonovich積分といいます。通常のRiemann積分では、「短冊」の高さの参照点をどこにとっても結果は同じでした。しかし、確率過程においては「短冊」の高さをどこにとるかによって極限の行き先が異なってしまいます。すなわち、伊藤積分とStratonovich積分は異なる公式を与えます。これは、確率微分方程式を、どう解釈するか、という問題となります。数値解法も解釈に依存し、もちろんその結果も解釈に依存します。
以下の乗法過程を考えてみます。
これを伊藤解釈で数値積分する場合は簡単です。単純にEuler-Maruyama法を適用すれば良いので、時間刻みを
とするだけです。ただし
一方、Stratonovich解釈を採用すると、確率変数にかかっている係数の部分は一つ先のステップの値との平均値を使うので、こんな感じになります。
右辺に未知の値である
これをTwo-step法と呼び、Stratonovich解釈で数値積分を行うもっとも簡単な方法の一つです。
実際にシミュレーションしてやりましょう。伊藤解釈で数値積分を行う関数をmultiplicative_euler_maruyama
、Stratonovich解釈で数値積分を行う関数をmultiplicative_two_step
として実装してあります。
import numpy as np
from matplotlib import pyplot as plt
from numba import jit
AVE = 1000
N = 100000
NA = N//AVE
h = 0.01
@jit
def multiplicative_euler_maruyama(N):
x = 0
data = []
for _ in range(N):
w1 = np.random.normal(0,np.sqrt(2*h))
w2 = np.random.normal(0,np.sqrt(2*h))
x += -x*x*x*h
x += x*w1
x += w2
data.append(x)
return data
@jit
def multiplicative_two_step(N):
x = 0
data = []
for _ in range(N):
w1 = np.random.normal(0,np.sqrt(2*h))
w2 = np.random.normal(0,np.sqrt(2*h))
x_i = x + (-x * x * x) * h + x * w1 + w2
x = x + (-x * x * x) * h + (x+x_i)*0.5*w1 + w2
data.append(x)
return data
伊藤解釈とStratonovich解釈の分布関数をプロットしてみましょう。
d1, f1 = dist(multiplicative_euler_maruyama(N))
d2, f2 = dist(multiplicative_two_step(N))
fig, ax = plt.subplots()
ax.plot(d1,f1)
ax.plot(d2,f2)
明らかにずれています。
今回のケースは定常分布関数の厳密解が求まります[5]。伊藤解釈の場合はこんな感じです。
重ねてプロットしてみましょう。
d1, f1 = dist(multiplicative_euler_maruyama(N))
d2, f2 = dist(multiplicative_two_step(N))
fig, ax = plt.subplots()
ito = np.exp(-d1**2/2)/np.sqrt(1+d1**2)/1.98
stratonovich = np.exp(-d1**2/2)/np.sqrt(3.14*2)
ax.plot(d1,f1)
ax.plot(d2,f2)
ax.plot(d1,ito,color='blue',label="Ito")
ax.plot(d1,stratonovich,color='red',label='Stratonovich')
ax.legend()
それぞれ理論曲線と一致していますね。
まとめ
微分方程式に確率変数を含むような確率微分方程式の積分を考えてみました。確率変数
Langevin方程式は揺動散逸定理の導出やFokker-Planck方程式の議論などいろいろおもしろい話題がありますが、本稿では触れられませんでした。別の機会にどこかで書ければと思っています。
Discussion