Poisson 過程で遊んでみた。
Poisson 過程
Poisson 過程では強度関数 $\lambda (t)$ により特徴づけられる。強度関数は与えられた区間内の $\forall t \in [0, T]$ に対して $\lambda (t) \geq 0$ を満たす。
強度関数 $\lambda (t)$ の Poisson 過程では、ある微小区間 $[t, t+\delta]$ 内でイベントが起きた回数を $N(t, t+\delta)$ とし、イベントが起きる確率を以下で表す。
\begin{align}
P\left[N(t, t+\delta) = 1\right] &= \lambda (t)\delta + o(\delta)\\
P\left[N(t, t+\delta) \geq 2\right] &= o(\delta)
\end{align}
これより、 $\delta$ が微小だとして1次のみを考えれば
\begin{align}
P\left[N(t, t+\delta) = 0\right] &= 1 - \lambda (t)\delta \approx \exp \left(-\lambda(t)\delta\right)
\end{align}
となる。強度関数が定数の場合を定常 Poisson 過程と呼び、そうでない場合を非定常 Poisson 過程と呼ぶ。上記の表式を使って①イベント数 $N$ とイベントの発生時刻の分布②イベント数の分布③イベント間の時間間隔の分布の3つの表式を得よう。
イベント数とイベントの発生時刻の分布
時間区間 $[0, T]$ 内で $N$ 個のイベントがそれぞれ時刻 $t_1< t_2<...<t_N$ に発生した場合を考えれば、その確率密度関数は以下で得られる。
\begin{align}
P(N, t_1, ..., t_N) &= \Pi_{i=1}^N P\left[N(t_i, t_i+\delta) = 1\right] \Pi_{t \neq t_1, ..., t_N} P\left[N(t, t+\delta) = 0\right]\\
&\approx \Pi_{i=1}^N \lambda(t_i)\delta \Pi_{t \neq t_1, ..., t_N} \exp\left[-\lambda(t)\delta\right]\\
&\propto \Pi_{i=1}^N \lambda(t_i)\delta \exp\left(-\int_0^T \lambda(t)dt\right)\\
\end{align}
イベント数の分布
①の分布で時間の引数全てを積分で落としてやれば良い。以下のように強度が $\int_0^T \lambda(t)dt$ の Poisson 分布が得られる。
\begin{align}
P(N) &= \int_0^T dt_1 ... \int_0^{t_{N-1}}dt_N P(N, t_1, ..., t_N)\\
&= \int_0^T dt_1 ... \int_0^{t_{N-1}}dt_N \Pi_{i=1}^N \lambda(t_i)\delta \exp\left(-\int_0^T \lambda(t)dt\right)\\
&= \frac{1}{N!}\int_0^T dt_1 ... \int_0^Tdt_N \Pi_{i=1}^N \lambda(t_i)\delta \exp\left(-\int_0^T \lambda(t)dt\right)\\
&= \frac{\left(\int_0^T \lambda(t)dt\right)^N}{N!}\exp\left(-\int_0^T \lambda(t)dt\right)
\end{align}
イベント間の時間間隔の分布
イベントが $t_i$ に起きたとし、次に起きる時間 $t_{i+1}$ との差 $\tau_i = t_{i+1} - t_i$ が従う分布を考える。 $t_i \leq \tau$ となる分布 $P(\tau\geq\tau_i)$ は、
\begin{align}
P(\tau\leq\tau_i) &= 1 - P(\tau > \tau_i)\\
&= 1 - P((\tau_i,\tau_{i+1}) で N = 0)\\
&= 1 - \exp\left(-\int_{t_i}^{t_{i+1}} \lambda(t) dt\right)
\end{align}
これを $\tau$ で微分すれば時間間隔の確率密度関数が得られ、 $dP(\tau\leq\tau_i)/dt = \lambda(t_i + \tau_i)\exp\left(-\int_{t_i}^{t_{i+1}} \lambda(t) dt\right)$ となる。これは定常 Poisson 過程の場合は指数分布になる。
間引き法
間引き法は非定常 Poisson 分布からイベント発生時刻のサンプルを得る方法のひとつ。詳しくは参考文献を参照。
区間は $[0, T]$ とする。間引き法は、棄却法の点過程バージョンのようなイメージを持つと良いかもしれない?間引き法はサンプリングをしたい非定常 Poisson 過程に対し、別の非定常 Poisson 過程でサンプリングしたものをある確率で受容すると、その受容されたサンプルはサンプリングしたい非定常 Poisson 過程から得られたサンプルだと保証することができる。もちろん実用上では、上に書いた”別の非定常 Poisson 過程” は定常 Poisson 分布を使用しても良い。ここではサンプリングしたい非定常 Poisson 過程の強度関数を $\lambda (t)$、棄却法における提案分布に対応する別の非定常 Poisson 分布の 強度関数を $\lambda^* (t)$ で書き分ける。
証明のスケッチ(スケッチという名の逃げ)
両強度関数が満たなさくてはならない条件は、対象とする区間の任意の点 $t$ に於いて $\lambda^* (t) \geq \lambda(t)$ である。
強度関数 $\lambda^* (t)$ に従う非定常 Poisson 分布から得られたサンプル $N$ 個 $t_1, ..., t_N$ に対し、強度関数 $\lambda (t)$ に従う非定常 Poisson 分布をそれぞれ $\lambda(t) / \lambda^*(t)$ の確率で受容する。$N$ 個のサンプルのうち $n$ 個が受容されたとし、受容されなかったものは積分して落とすことで、 $n$ 個が受容された場合の確率分布は以下のように得られる。
\begin{align}
p_N(n, t_1, ..., t_n) &= \int_0^T \frac{dt_{n+1} ... dt_N}{(N-n)!} \Pi_{i=1}^N \lambda^* (t_i)\exp\left(-\int_0^T \lambda^* (s) ds\right) \Pi_{j=1}^n \frac{\lambda(t_j)}{\lambda^* (t_j)} \Pi_{k=n+1}^N \left(1 - \frac{\lambda(t_k)}{\lambda^*(t_k)}\right)\\
&= \int_0^T \frac{dt_{n+1} ... dt_N}{(N-n)!} \exp\left(-\int_0^T \lambda^* (s) ds\right) \Pi_{j=1}^n \lambda(t_j) \Pi_{k=n+1}^N \left(\lambda^*(t_k) - \lambda(t_k)\right)\\
&= \Pi_{j=1}^n \lambda(t_j)\exp\left(-\int_0^T \lambda^* (s) ds\right) \frac{\left(\int_0^T \left[\lambda^*(t_k) - \lambda(t_k)\right] dt\right)^{N-n}}{(N-n)!}\\
\end{align}
これを $N$ を $n$ から $\infty$ まで足し上げたものは以下の通り強度関数 $\lambda(t)$ の非定常 Poisson 分布のイベント発生時刻の分布と同一になる。
\begin{align}
p(n, t_1, ..., t_n) &= \sum_{N=n}^\infty p_N(n, t_1, ..., t_n)\\
&= \Pi_{j=1}^n \lambda(t_j)\exp\left(-\int_0^T \lambda^* (s) ds\right) \sum_{N=n}^\infty \frac{\left(\int_0^T \left[\lambda^*(t_k) - \lambda(t_k)\right] dt\right)^{N-n}}{(N-n)!}\\
&= \Pi_{j=1}^n \lambda(t_j)\exp\left(-\int_0^T \lambda(t_k) dt\right)\\
\end{align}
アルゴリズム
定常 Poisson 過程のイベント間隔は指数分布に従うため、簡単にサンプルを得ることができる。そのため定常 Poisson 過程を提案分布に採用する。この場合強度関数をどうするかでいろいろと手法があるようだが、ここでは $\lambda^* = \max_{t\in[0, T]}$ \lambda(t)$ とする。
- 強度 $\lambda^*$ の定常 Poisson 分布からイベント発生時刻のサンプル ${t_i}$ を作成する。
- サンプル ${t_i}$ を $\lambda(t_i)/ \lambda^*$ の確率で受容する。
上の方法では一気にサンプルを取得し、一気に受容するかを選択しているが、ひとつひとつ行っても良い。
シミュレーション
行ったこと
以下の場合の非定常 Poisson 過程からのサンプリングのシミュレーションを行った。
\begin{align}
T &= 1\\
\lambda(t) &= 24 \left(t-\frac{1}{2}\right)^2
\end{align}
$\int_0^1 \lambda(t) = 2$ のため、イベント発生数は平均2の Poisson 分布に従う。10000回のサンプリングをした結果、イベント間隔の平均が1.99、標準偏差が1.41 が得られたためおそらく正しくサンプリングされているだろう(ほんとうは分布の同一性の検定をしたいが、まだ実装していないので行えない。。。)
コード
非定常 Poisson 過程のサンプリング部分
privateIEnumerable<double>GetEventSample(NonStationaryPoissonProcessConfigconfig){varmaxIntensity=config.Intensity(FindIntensityMaximumTime(config));varuniform=newProbability.Distribution.Uniform();varuniformParam=newProbability.Parameter.Uniform(0,1);varstPoissonProc=newStochasticProcess.PointProcess.StationaryPoissonProcess();varsample=stPoissonProc.GetEventSamples(newStationaryPoissonProcessConfig(maxIntensity,config.Start,config.End),1).First();returnsample.Where(t=>config.Intensity(t)/maxIntensity>=uniform.GetSamples(uniformParam,1).First());}
定常 Poisson 過程のサンプリング部分
privateIEnumerable<double>GetEventSample(StationaryPoissonProcessConfigconfig){vart=config.Start;varexp=newProbability.Distribution.Exponential();varexpParam=newProbability.Parameter.Exponential(1.0/config.Intensity);while(t<=config.End){t=t+exp.GetSamples(expParam,1).First();if(t<=config.End)yieldreturnt;}}
実際に数値計算をした部分
varsize=10000;varnpp=newStochasticProcess.PointProcess.NonStationaryPoissonProcess();varnppStart=0.0;varnppEnd=1.0;Func<double,double>nppIntensity=(doublet)=>3.0*Math.Pow(t-(nppEnd+nppStart)/2,2)/Math.Pow((nppEnd+nppStart)/2,3);varnppConfig=newStochasticProcess.PointProcessConfig.NonStationaryPoissonProcessConfig(nppIntensity,nppStart,nppEnd);varnppTimeSamples=npp.GetEventSamples(nppConfig,size).Select(t=>t.ToList()).ToList();varnppTimeSamplesCount=nppTimeSamples.Select(t=>t.ToList().Count()).ToList();Console.WriteLine(nppTimeSamplesCount.Average());Console.WriteLine(nppTimeSamplesCount.StandardDeviation());