ポアソン過程 完全ガイド — 定義・指数分布・到着間隔から非斉次・複合過程まで

深夜のWebサーバーに、次のアクセスはいつ来るのでしょうか。地震がいつ起きるか、コールセンターに次の電話がいつ鳴るか、ガイガーカウンターが次にカチッと鳴るのはいつか——これらに共通するのは、「いつ起きるか正確には予測できないが、長い目で見ると一定のペースで発生する」という性質です。こうした「完全にランダムなイベントの発生」を記述する、確率過程のなかで最も基本的かつ美しいモデルがポアソン過程(Poisson process)です。

ポアソン過程を理解すると、驚くほど広い分野のつながりが見えてきます。たとえば、コンビニやコールセンターの混雑を予測する待ち行列理論、ネットワークのパケット到着をモデル化する通信工学、保険金請求の総額を見積もる保険数理、そして地震や放射性崩壊といった自然現象のモデリング。いずれも「ランダムなイベントがいつ・どれだけ起きるか」を扱うため、ポアソン過程が共通の言語になります。

本記事は、すでに公開しているポアソン分布の解説ポアソン過程の理論と応用を踏まえつつ、入門から応用までを一本道でたどる完全ガイドとして書きました。定義の3公理から出発し、指数分布・ガンマ分布との関係、重ね合わせ・間引きといった操作、さらに非斉次・複合ポアソン過程、待ち行列への応用までを、図とPython実装で順を追って理解していきます。

本記事の内容

  • ランダムなイベント発生の直感と、計数過程による定式化
  • ポアソン過程の3公理と、ポアソン分布・指数分布・ガンマ分布の関係
  • 無記憶性・重ね合わせ・間引きという3つの重要な性質
  • 非斉次ポアソン過程(時変レート)と複合ポアソン過程(ランダムなジャンプ)
  • M/M/1待ち行列への応用、Pythonでのシミュレーション、実データへの当てはめ

前提知識

この記事を読む前に、以下の記事を読んでおくと理解が深まります。

ランダムなイベント発生の直感

まず、ポアソン過程が描こうとしている世界を直感的にイメージしましょう。ある時間軸の上に、ポツポツとイベントが起きる場面を思い浮かべてください。Webサーバーへのアクセス、店舗への来客、ガイガーカウンターの「カチッ」という音。これらは規則正しく等間隔に並んでいるわけではありません。あるときは立て続けに起き、あるときはしばらく途絶える。それでも「1時間あたり平均◯件」という平均ペースだけは安定している——これがポアソン過程の世界観です。

このイベントの起き方には、2つの「ランダムさの条件」があると考えると見通しがよくなります。1つは、過去にいつイベントが起きたかは、未来の発生に影響しないこと。さっきアクセスが多かったからといって、次のアクセスが来やすくなったり来にくくなったりはしない、という性質です。もう1つは、どの瞬間も同じ確率で起きること。朝でも夜でも、開始直後でも10時間後でも、単位時間あたりの発生ペースは変わらない、という均質性です。

この2つを満たすと、不思議なことに「単位時間あたりのイベント数」は必然的にポアソン分布に、「イベントの時間間隔」は必然的に指数分布に従うことが導かれます。ランダムさのごく自然な仮定だけから、特定の分布がぴたりと決まってしまう——ここがポアソン過程の美しさです。次のセクションで、この直感を数学的な定義に翻訳していきましょう。

ポアソン過程の定義

計数過程

イベントの発生を数学的に扱うには、まず「時刻 $t$ までに何回起きたか」を数える関数を用意します。これを計数過程(counting process)と呼びます。

定義の前にイメージを持ちましょう。横軸を時刻 $t$、縦軸を累積イベント数とすると、イベントが起きるたびに値が1段ずつ上がる階段状のグラフになります。イベントが起きていない間は水平、イベントの瞬間にぴょこんと1だけ跳ね上がる。この「右上がりの階段」こそが計数過程です。

計数過程N(t)の階段グラフ。各到着時刻でN(t)が1ずつジャンプする様子

上の図は、レート $\lambda = 1$ のポアソン過程を実際にシミュレーションして描いた計数過程 $N(t)$ です。赤い点(塗りつぶし)が各到着時刻 $S_n$ で、そこで値が1だけ上にジャンプしています。白抜きの点はジャンプ直前の値で、$N(t)$ が右連続(ジャンプした後の値を採用する)であることを表しています。下部の赤い縦線が、実際にイベントが起きた時刻です。イベントが詰まっている区間では階段が急に駆け上がり、間隔が空いた区間では水平に伸びていることが読み取れます。

形式的には、計数過程 $\{N(t),\, t \geq 0\}$ は次を満たす確率過程です。

  • $N(t) \geq 0$ で整数値をとる
  • $s < t$ ならば $N(s) \leq N(t)$(単調非減少)
  • $N(t) – N(s)$ は区間 $(s, t]$ で起きたイベント数を表す

ポアソン過程の3公理

計数過程のうち、前節で述べた「2つのランダムさの条件」を満たすものがポアソン過程です。強度(レート)$\lambda > 0$ のポアソン過程とは、次の3つの条件を満たす計数過程 $\{N(t),\, t \geq 0\}$ のことです。

  1. 初期条件: $N(0) = 0$
  2. 独立増分: 重ならない時間区間でのイベント数は互いに独立。すなわち $t_1 < t_2 \leq t_3 < t_4$ のとき、$N(t_2) - N(t_1)$ と $N(t_4) - N(t_3)$ は独立。
  3. 定常なポアソン増分: 長さ $t$ の区間でのイベント数は、区間の開始時刻によらず、パラメータ $\lambda t$ のポアソン分布に従う。

3番目の条件を式で書くと、任意の $s \geq 0$ と $t > 0$ について次が成り立ちます。

$$ P\bigl(N(s+t) – N(s) = k\bigr) = \frac{(\lambda t)^k e^{-\lambda t}}{k!}, \quad k = 0, 1, 2, \dots $$

ここで重要なのは、確率が $s$ に依存せず、区間の長さ $t$ だけで決まる点です。これが前節で述べた「どの瞬間も同じ確率で起きる」という均質性(定常性)の数式表現です。

微小時間による等価な定義

ポアソン過程には、もう1つよく使われる等価な定義があります。「ごく短い時間にはイベントは高々1回しか起きない」という局所的な性質から出発するものです。次の3条件を満たす計数過程もポアソン過程になります。

  1. $N(0) = 0$、独立増分をもつ
  2. 微小時間 $h$ にちょうど1回起きる確率: $\displaystyle P(N(h) = 1) = \lambda h + o(h)$
  3. 微小時間 $h$ に2回以上起きる確率: $\displaystyle P(N(h) \geq 2) = o(h)$

ここで $o(h)$ は $h \to 0$ のとき $o(h)/h \to 0$ となる量、つまり「$h$ より速くゼロに近づく無視できる項」です。条件2と3が言っているのは、「十分短い時間幅 $h$ では、イベントは確率 $\lambda h$ でちょうど1回起き、複数回起きる確率は無視できる」ということ。この局所的なルールを時間方向に積み重ねていくと、前節のポアソン分布の式が導かれます。微分方程式を使ったこの導出はポアソン過程の理論と応用で詳しく扱っています。

$\lambda$ の意味と期待値・分散

パラメータ $\lambda$ はイベントの強度(intensity)またはレート(rate)と呼ばれ、単位時間あたりの平均イベント数を表します。ポアソン分布の性質から、期待値と分散はともに $\lambda t$ になります。

$$ E[N(t)] = \lambda t, \qquad \mathrm{Var}(N(t)) = \lambda t $$

期待値が $\lambda t$ なのは「平均ペース $\lambda$ × 時間 $t$」と読めて自然です。期待値と分散が等しいのはポアソン分布特有の性質で、後ほど実データの当てはめ(過分散の判定)でも効いてきます。ここまでで「区間あたりのイベント数」の分布が分かりました。次は視点を変えて、「イベントとイベントの間隔」がどんな分布になるかを見ていきましょう。

到着間隔と指数分布

到着時刻と到着間隔

ポアソン過程のもう1つの見方は、イベントが起きる時刻そのものに注目することです。$n$ 番目のイベントが起きる時刻を $S_n$(到着時刻、arrival time)、隣り合うイベントの時間間隔を $T_n = S_n – S_{n-1}$(到着間隔、interarrival time)と書きます。ただし $S_0 = 0$ とします。

到着時刻S_nと到着間隔T_nの関係を示すタイムライン図

上の図のように、$S_1, S_2, \dots$ は時間軸上のイベント点、$T_1, T_2, \dots$ はその間の長さです。到着時刻と到着間隔は $S_n = T_1 + T_2 + \cdots + T_n$ という関係で結ばれています。計数過程 $N(t)$ が「縦に数える」見方だとすれば、到着間隔 $T_n$ は「横の長さを測る」見方だと言えます。

到着間隔は指数分布に従う

では $T_1$(最初のイベントまでの待ち時間)の分布を求めましょう。「$T_1$ が $t$ より長い」とは、「時刻 $t$ までに1件もイベントが起きていない」ことと同じです。後者の確率はポアソン分布で $k=0$ の場合なので、

$$ P(T_1 > t) = P(N(t) = 0) = \frac{(\lambda t)^0 e^{-\lambda t}}{0!} = e^{-\lambda t} $$

となります。したがって $T_1$ の累積分布関数は $F(t) = P(T_1 \leq t) = 1 – e^{-\lambda t}$ であり、これは指数分布 $\mathrm{Exp}(\lambda)$ の累積分布関数そのものです。確率密度関数は $F(t)$ を微分して、

$$ f_{T_1}(t) = \lambda e^{-\lambda t}, \quad t \geq 0 $$

を得ます。さらに、独立増分性と定常増分性を使うと、$T_1$ だけでなくすべての到着間隔 $T_n$ が独立に同じ指数分布 $\mathrm{Exp}(\lambda)$ に従うことが示せます。直感的には、あるイベントが起きた直後から見ても、過程の「ランダムさのルール」は何も変わらないので、次のイベントまでの待ち時間はまた同じ指数分布になる、というわけです。

到着間隔のヒストグラムと指数分布の理論密度、および無記憶性の確認

左の図は、$\lambda = 2$ のポアソン過程の到着間隔を多数集めたヒストグラム(青)と理論密度 $\lambda e^{-\lambda t}$(赤)です。両者がぴたりと重なり、平均が $1/\lambda = 0.5$(緑の破線)に一致していることが確認できます。右の図は次に説明する無記憶性を表したもので、「すでに $s$ だけ待った」あとの残り待ち時間の分布が、$s$ の値によらず完全に重なる様子を示しています。

指数分布の期待値と無記憶性

指数分布の期待値は $E[T_n] = 1/\lambda$ です。レートが $\lambda = 3$ 件/時間なら、平均到着間隔は $1/3$ 時間(20分)。「1時間に3件来るなら平均20分おき」という直感とぴたり合います。

そして指数分布が持つ最も特徴的な性質が無記憶性(memorylessness)です。

$$ P(T > s + t \mid T > s) = P(T > t) $$

これは「すでに $s$ 時間待っていても、残りの待ち時間の分布は最初から待つのと変わらない」ことを意味します。バス停で10分待っても、次の1分以内にバスが来る確率は、待ち始めた瞬間と同じ。証明は条件付き確率の定義から一行です。

$$ P(T > s+t \mid T > s) = \frac{P(T > s+t)}{P(T > s)} = \frac{e^{-\lambda(s+t)}}{e^{-\lambda s}} = e^{-\lambda t} = P(T > t) $$

途中で $P(T > u) = e^{-\lambda u}$ という指数分布の生存関数を代入し、指数法則 $e^{-\lambda(s+t)} = e^{-\lambda s}e^{-\lambda t}$ で約分しただけです。連続分布で無記憶性を持つのは指数分布だけであり、これがポアソン過程の数学的な扱いやすさの源になっています。

到着間隔が分かれば、その和である到着時刻の分布も決まります。次はそれを見ていきましょう。

到着時刻のガンマ分布

$n$ 番目のイベントの到着時刻 $S_n = T_1 + T_2 + \cdots + T_n$ は、独立な指数分布の和です。「指数分布の和」と聞いてピンとこなくても大丈夫です。これはガンマ分布 $\mathrm{Gamma}(n, \lambda)$ になることが知られています。

$$ f_{S_n}(t) = \frac{\lambda^n t^{n-1} e^{-\lambda t}}{(n-1)!}, \quad t \geq 0 $$

なぜこうなるかは、別の角度から理解することもできます。「$S_n \leq t$」($n$ 番目のイベントが時刻 $t$ までに起きる)は「$N(t) \geq n$」(時刻 $t$ までに $n$ 件以上起きる)と同値です。この関係を使って累積分布関数を計算し、微分してもこの密度が得られます。$n=1$ のときは $f_{S_1}(t) = \lambda e^{-\lambda t}$ となり、指数分布に一致することも確認できます。到着時刻の分布が分かると、「$n$ 件目が起きるのを平均どれくらい待つか」($E[S_n] = n/\lambda$)といった量も計算できます。

ここまでで、ポアソン過程を「区間あたりのイベント数(ポアソン分布)」「到着間隔(指数分布)」「到着時刻(ガンマ分布)」という3つの分布で完全に特徴づけました。次は、複数のポアソン過程を組み合わせたり加工したりしたときに何が起きるかを見ていきます。

重ね合わせと間引き

ポアソン過程の実用上の威力は、組み合わせても加工してもポアソン過程のままでいてくれる、という閉じた性質にあります。代表的な2つの操作を見ましょう。

レートを変えると発生密度が変わる

その前に、レート $\lambda$ そのものが発生の密度をどう決めるかを確認しておきます。

異なるλでのイベント発生密度と累積カウントの比較

上段は $\lambda = 0.5, 2.0, 5.0$ の3つのポアソン過程のイベント発生を時間軸上の縦線で表したものです。$\lambda$ が大きいほどイベントが密に並んでいることが一目で分かります。下段は対応する累積カウント $N(t)$ で、いずれも平均直線 $E[N(t)] = \lambda t$(破線)に沿って増えています。$\lambda$ が大きいほど階段の傾きが急になり、ランダムなゆらぎを伴いながらも平均直線にぴたりと寄り添っているのが読み取れます。

重ね合わせ(superposition)

レート $\lambda_1$ のポアソン過程とレート $\lambda_2$ のポアソン過程を、独立に走らせて両方のイベントをまとめて1つの過程とみなすと、それはレート $\lambda_1 + \lambda_2$ のポアソン過程になります。

$$ N_1(t) + N_2(t) \sim \text{ポアソン過程}(\lambda_1 + \lambda_2) $$

直感的には、2つの蛇口から別々のペースで水滴が落ちてくるとき、洗面台に落ちる水滴の合計ペースは単純に足し算になる、というだけのことです。証明は、独立なポアソン確率変数の和がまたポアソン分布になる(パラメータは和)ことから従います。

2つのポアソン過程の重ね合わせと、合計カウントのポアソン適合

左の図は $\lambda_1 = 1.0$(青)と $\lambda_2 = 1.5$(緑)の2過程をマージして $\lambda_1 + \lambda_2 = 2.5$ の合成過程を作る様子です。右の図は、合成過程の総イベント数 $N(T)$ のヒストグラム(青)が、理論どおり $\mathrm{Poisson}(2.5\,T)$(赤)に従うことを示しています。シミュレーションと理論が見事に一致しています。

間引き(thinning)

逆に、レート $\lambda$ のポアソン過程の各イベントを、独立に確率 $p$ で「採用」、確率 $1-p$ で「棄却」すると、採用されたイベントだけからなる過程はレート $\lambda p$ のポアソン過程になります。

$$ \text{採用された過程} \sim \text{ポアソン過程}(\lambda p) $$

たとえば、店に来る全客のうち40%だけが商品を買うとすれば、購入イベントは元の来客過程を確率 $p=0.4$ で間引いた過程になり、購入のレートは $\lambda p$ です。間引きが面白いのは、採用された過程と棄却された過程が互いに独立なポアソン過程になる点で、これは多くの応用で便利に使われます。

間引き(thinning)の模式図と、採用過程のポアソン適合

左の図は $\lambda = 3.0$ の過程(青)の各イベントを確率 $p = 0.4$ で採用(緑の実線でつないだもの)し、棄却(灰色の点線)する様子です。採用過程のレートは $\lambda p = 1.2$ になっています。右の図は、採用イベント数のヒストグラム(緑)が $\mathrm{Poisson}(\lambda p\,T)$(赤)に一致することを示しています。

重ね合わせも間引きも「ポアソン過程はポアソン過程のまま」という閉じた性質の表れです。ここまでは $\lambda$ が一定の斉次ポアソン過程を扱ってきました。しかし現実の現象では、レートが時間とともに変わることがよくあります。次はその一般化を見ていきましょう。

非斉次ポアソン過程

現実のWebアクセスは、深夜は少なく昼休みと夜にピークが来ます。地震の余震は本震直後ほど頻発します。このようにレートが時刻によって変化するポアソン過程を、非斉次ポアソン過程(nonhomogeneous Poisson process)と呼びます。レートを定数 $\lambda$ から時間の関数 $\lambda(t)$ に置き換えるのが唯一の変更点です。

このとき、区間 $(s, t]$ でのイベント数は、平均が強度の積分で与えられるポアソン分布に従います。

$$ N(t) – N(s) \sim \mathrm{Poisson}\!\left(\int_s^t \lambda(u)\, du\right) $$

積分量 $\Lambda(t) = \int_0^t \lambda(u)\,du$ は累積強度関数と呼ばれ、「時刻 $t$ までに平均何件起きるか」を表します。斉次の場合は $\lambda(u) = \lambda$(定数)なので $\Lambda(t) = \lambda t$ となり、これまでの式に一致します。定数を関数に置き換え、掛け算を積分に置き換えた——それが非斉次への一般化の本質です。

非斉次ポアソン過程の時変強度λ(t)と発生イベントの対応

上の図は、昼(12時)と夜(19時)にピークを持つ時変強度 $\lambda(t)$(紫)を表しています。下の図は、この $\lambda(t)$ から生成したイベントの発生時刻です。$\lambda(t)$ が高い昼と夜の時間帯にイベントが密集し、$\lambda(t)$ が低い早朝にはまばらになっている様子がはっきり読み取れます。強度関数の形がそのままイベントの「混み具合」に反映されています。

非斉次ポアソン過程のシミュレーションには棄却法(thinning)が使えます。レートの最大値 $\lambda_{\max} = \max_t \lambda(t)$ で斉次ポアソン過程を生成し、各候補イベントを確率 $\lambda(t)/\lambda_{\max}$ で採用するのです。間引きの性質を逆に使った、エレガントな生成法になっています。

ここまではイベントの「タイミング」だけを扱ってきましたが、現実にはイベントごとに「大きさ」が伴うこともあります。次はその拡張を見ましょう。

複合ポアソン過程

保険会社にとって重要なのは「請求が何件あったか」だけでなく「請求総額がいくらか」です。各請求の金額はバラバラなので、総額はイベント数とは別のランダム性を持ちます。このように、各イベントにランダムな大きさを割り当て、その累積和を考えるのが複合ポアソン過程(compound Poisson process)です。

レート $\lambda$ のポアソン過程 $N(t)$ と、独立同分布な確率変数列 $Y_1, Y_2, \dots$(各イベントの「大きさ」)を用意し、次の累積和を定義します。

$$ X(t) = \sum_{i=1}^{N(t)} Y_i $$

$N(t)$ がイベントの「個数」、$Y_i$ が各イベントの「大きさ」です。$X(t)$ の期待値は、条件付き期待値の公式(Waldの等式)から簡単に求まります。

$$ E[X(t)] = E[N(t)] \cdot E[Y] = \lambda t \cdot E[Y] $$

「平均個数 × 1個あたりの平均サイズ」と読めて自然です。分散についても $\mathrm{Var}(X(t)) = \lambda t \cdot E[Y^2]$ という公式が知られています。

複合ポアソン過程の実現パスと平均線

上の図は、レート $\lambda = 1.2$ のポアソン過程に、対数正規分布に従うジャンプ高さ $Y_i$ を割り当てた複合ポアソン過程の3つの実現パスです。斉次ポアソン過程の計数過程(図01)と違い、各ジャンプの高さがバラバラになっているのが特徴です。3本のパスはばらつきながらも、平均線 $\lambda E[Y]\,t$(黒の破線)の周りを推移しています。保険金請求の累積額、株式の累積取引高、通信トラフィックの累積データ量など、「個数 × サイズ」の構造を持つ現象のモデルとして広く使われます。

ここまでで、ポアソン過程の基本形・時変版・複合版を見てきました。次は、ポアソン過程が「入力」として最も重要な役割を果たす応用——待ち行列理論を取り上げます。

待ち行列(M/M/1)への応用

スーパーのレジ、コールセンター、サーバーへのリクエスト。これらはすべて「客がランダムに到着し、サービスを受け、待ち行列ができる」システムです。その最も基本的なモデルがM/M/1待ち行列です。記号は「到着がマルコフ的(M、ポアソン到着)/サービス時間がマルコフ的(M、指数分布)/窓口が1つ(1)」を意味します。

到着レートを $\lambda$、サービスレートを $\mu$(1人の客を処理するのに平均 $1/\mu$ 時間)とします。重要なのが利用率 $\rho = \lambda/\mu$ です。$\rho$ は「窓口がどれだけ忙しいか」を表し、$\rho < 1$ でなければ行列が無限に伸びてしまいます。$\rho < 1$ のとき、定常状態での平均系内客数 $L$(待っている人+サービス中の人)は次の美しい式で与えられます。

$$ L = \frac{\rho}{1 – \rho} $$

この式の導出は、状態(系内客数)を $0, 1, 2, \dots$ とする出生死滅過程(連続時間マルコフ連鎖)の定常分布が幾何分布 $P(L = n) = (1-\rho)\rho^n$ になることから得られます。詳細はマルコフ連鎖の定常分布の議論に譲りますが、ポイントは到着がポアソン過程、サービス時間が指数分布(無記憶性)であることが、この解析を可能にしている点です。

M/M/1待ち行列の客数推移と、利用率に対する平均系内数

左の図は $\rho = 0.8$ のM/M/1待ち行列をシミュレーションした系内客数 $L(t)$ の推移です。客数はランダムに増減しますが、長期的には理論平均 $L = \rho/(1-\rho) = 4.0$(赤の破線)の周りで推移しています。右の図は利用率 $\rho$ と平均系内数 $L$ の関係で、$\rho$ が1に近づくと $L$ が急激に発散する様子が分かります。「窓口の稼働率を上げすぎると、わずかな増加で待ち行列が爆発的に伸びる」という、待ち行列理論の最も重要な教訓がこの曲線に表れています。

理論の全体像が見えたところで、ここまでの性質をPythonで実際に確かめてみましょう。

Pythonでのシミュレーション

ポアソン過程の実現パスと諸性質の検証

まず、到着間隔を指数分布から生成する方法でポアソン過程をシミュレートし、計数過程・ポアソン分布・指数分布・期待値の4つを一度に確認します。

import numpy as np
import matplotlib.pyplot as plt
from scipy import stats

rng = np.random.default_rng(42)

def simulate_poisson_process(lam, T, rng):
    """到着間隔を指数分布から生成してポアソン過程をシミュレート"""
    arrivals = []
    t = 0.0
    while True:
        t += rng.exponential(1.0 / lam)  # 次の到着までの待ち時間
        if t >= T:
            break
        arrivals.append(t)
    return np.array(arrivals)

lam, T = 3.0, 10.0  # レート3件/時間, 観測10時間

fig, axes = plt.subplots(2, 2, figsize=(13, 9))

# (1) 複数の実現パス
ax = axes[0, 0]
for _ in range(5):
    arr = simulate_poisson_process(lam, T, rng)
    Nt = np.arange(1, len(arr) + 1)
    ax.step(arr, Nt, where='post', lw=1.5, alpha=0.8)
ax.set_xlabel('時刻 t'); ax.set_ylabel('N(t)')
ax.set_title(f'ポアソン過程の実現パス (λ={lam})')
ax.grid(alpha=0.3)

# (2) N(5) の分布がポアソン分布か
ax = axes[0, 1]
t_check, n_sim = 5.0, 10000
counts = [len(simulate_poisson_process(lam, t_check, rng)) for _ in range(n_sim)]
k = np.arange(0, 35)
ax.hist(counts, bins=np.arange(-0.5, 35.5), density=True, alpha=0.7,
        color='steelblue', edgecolor='white', label='シミュレーション')
ax.plot(k, stats.poisson.pmf(k, lam * t_check), 'ro-', ms=4,
        label=f'Poisson(λt={lam*t_check:.0f})')
ax.set_xlabel('N(5)'); ax.set_ylabel('確率')
ax.set_title('N(t) はポアソン分布'); ax.legend(); ax.grid(alpha=0.3)

# (3) 到着間隔が指数分布か
ax = axes[1, 0]
arr = simulate_poisson_process(lam, 2000, rng)
gaps = np.diff(np.concatenate([[0.0], arr]))
tt = np.linspace(0, gaps.max(), 200)
ax.hist(gaps, bins=50, density=True, alpha=0.7, color='orange',
        edgecolor='white', label='シミュレーション')
ax.plot(tt, lam * np.exp(-lam * tt), 'r-', lw=2, label=f'Exp(λ={lam})')
ax.set_xlabel('到着間隔'); ax.set_ylabel('密度')
ax.set_title('到着間隔は指数分布'); ax.legend(); ax.grid(alpha=0.3)

# (4) E[N(t)] = λt の確認
ax = axes[1, 1]
ts = np.linspace(0.1, T, 40)
means = [np.mean([len(simulate_poisson_process(lam, t, rng)) for _ in range(300)])
         for t in ts]
ax.plot(ts, means, 'bo', ms=4, alpha=0.7, label='シミュレーション E[N(t)]')
ax.plot(ts, lam * ts, 'r-', lw=2, label='λt')
ax.set_xlabel('時刻 t'); ax.set_ylabel('E[N(t)]')
ax.set_title('E[N(t)] = λt'); ax.legend(); ax.grid(alpha=0.3)

plt.tight_layout()
plt.show()

4つのパネルから、ポアソン過程の中核的な性質がすべて確認できます。左上の実現パスは右上がりの階段状で、試行ごとに異なる経路をたどります。右上では $N(5)$ のヒストグラムが $\mathrm{Poisson}(\lambda t = 15)$ のPMF(赤)にぴたりと重なり、定義の3公理が正しく実装されていることが分かります。左下の到着間隔は指数分布の密度に一致し、右下の平均カウントは理論直線 $\lambda t$ にきれいに乗っています。「到着間隔を指数分布で生成する」だけで、計数過程がポアソン分布に従う——理論と実装が一致しました。

重ね合わせと間引きの検証

次に、ポアソン過程の閉じた性質(重ね合わせ・間引き)を数値的に確かめます。

import numpy as np
import matplotlib.pyplot as plt
from scipy import stats

rng = np.random.default_rng(7)

fig, axes = plt.subplots(1, 2, figsize=(12, 5))
T, n_sim = 30.0, 8000

# 重ね合わせ: λ1 + λ2
ax = axes[0]
lam1, lam2 = 2.0, 3.0
merged = [rng.poisson(lam1 * T) + rng.poisson(lam2 * T) for _ in range(n_sim)]
merged = np.array(merged)
k = np.arange(merged.min(), merged.max() + 1)
ax.hist(merged, bins=np.arange(merged.min()-0.5, merged.max()+1.5),
        density=True, alpha=0.7, color='steelblue', edgecolor='white',
        label='合成過程')
ax.plot(k, stats.poisson.pmf(k, (lam1 + lam2) * T), 'r-', lw=2,
        label=f'Poisson(λ={lam1+lam2})')
ax.set_xlabel('N(T)'); ax.set_ylabel('密度')
ax.set_title(f'重ね合わせ: λ1={lam1} + λ2={lam2}')
ax.legend(); ax.grid(alpha=0.3)

# 間引き: λp
ax = axes[1]
lam, p = 5.0, 0.4
thinned = [rng.binomial(rng.poisson(lam * T), p) for _ in range(n_sim)]
thinned = np.array(thinned)
k = np.arange(thinned.min(), thinned.max() + 1)
ax.hist(thinned, bins=np.arange(thinned.min()-0.5, thinned.max()+1.5),
        density=True, alpha=0.7, color='orange', edgecolor='white',
        label='間引き後の過程')
ax.plot(k, stats.poisson.pmf(k, lam * p * T), 'r-', lw=2,
        label=f'Poisson(λp={lam*p:.0f})')
ax.set_xlabel('N(T)'); ax.set_ylabel('密度')
ax.set_title(f'間引き: λ={lam}, p={p}')
ax.legend(); ax.grid(alpha=0.3)

plt.tight_layout()
plt.show()

左のヒストグラムは、$\lambda_1 = 2$ と $\lambda_2 = 3$ の2過程を合成したイベント数が $\mathrm{Poisson}((\lambda_1+\lambda_2)T) = \mathrm{Poisson}(150)$ に従うことを示しています。右は $\lambda = 5$ の過程を確率 $p = 0.4$ で間引いた結果が $\mathrm{Poisson}(\lambda p\,T) = \mathrm{Poisson}(60)$ に従うことを示しています。どちらも理論曲線と一致し、「足してもポアソン、間引いてもポアソン」という閉じた性質が数値的に裏付けられました。

非斉次ポアソン過程の生成

最後に、棄却法を使って時変レートの非斉次ポアソン過程を生成します。

import numpy as np
import matplotlib.pyplot as plt

rng = np.random.default_rng(6)

def lam_t(t):
    """昼(12時)と夜(19時)にピークを持つ時変レート"""
    return (2.0 + 4.0 * np.exp(-0.5 * ((t - 12) / 2.5) ** 2)
            + 3.0 * np.exp(-0.5 * ((t - 19) / 1.5) ** 2))

T = 24.0
tt = np.linspace(0, T, 500)
lam_max = lam_t(tt).max()  # レートの上界

# 棄却法: λ_max の斉次過程を生成し、確率 λ(t)/λ_max で採用
cand, t = [], 0.0
while True:
    t += rng.exponential(1.0 / lam_max)
    if t >= T:
        break
    cand.append(t)
cand = np.array(cand)
accept = cand[rng.random(len(cand)) < lam_t(cand) / lam_max]

fig, axes = plt.subplots(2, 1, figsize=(11, 6), sharex=True,
                         gridspec_kw={'height_ratios': [2, 1]})
axes[0].plot(tt, lam_t(tt), 'purple', lw=2.4, label='強度関数 λ(t)')
axes[0].fill_between(tt, 0, lam_t(tt), color='purple', alpha=0.12)
axes[0].set_ylabel('強度 λ(t)'); axes[0].legend(); axes[0].grid(alpha=0.3)
axes[1].plot(accept, np.zeros_like(accept), '|', color='red', ms=22, mew=1.4)
axes[1].set_yticks([]); axes[1].set_xlabel('時刻 t (時)')
axes[1].set_title('発生イベント'); axes[1].grid(alpha=0.3, axis='x')
plt.tight_layout()
plt.show()

print(f'採用率: {len(accept)/len(cand):.2%}, 総イベント数: {len(accept)}')

下段のイベント点が、上段の強度 $\lambda(t)$ が高い昼と夜の時間帯に集中していることが確認できます。棄却法は「一様に多めに生成して、確率的にふるい落とす」というシンプルな発想ですが、間引きの性質によって正しく非斉次ポアソン過程を生成できる点が美しいところです。採用率はおよそ $\bar\lambda/\lambda_{\max}$(平均レートと最大レートの比)になります。

理論と実装が一致することを確認したところで、最後にポアソン過程が実世界でどう使われるかをまとめましょう。

応用 — 地震・通信・金融・Webアクセス

ポアソン過程は、分野を超えて「ランダムなイベント発生」のモデルとして使われています。

  • 地震・自然現象: ある地域での地震発生は、ある時間スケールではポアソン過程で近似されます。単位時間あたりの発生回数がポアソン分布に従うか、到着間隔が指数分布に従うかを検定することで、地震活動の「ランダム性」を評価できます。
  • 通信・ネットワーク: パケット到着やコール到着の古典的モデルです。重ね合わせの性質により、多数のユーザーからのトラフィックを合成しても全体がポアソン過程として扱え、ネットワーク設計の見積もりに使えます。
  • 金融: 取引の発生や、稀な暴落(ジャンプ)のモデル化に複合ポアソン過程が使われます。保険数理では保険金請求の累積額がまさに複合ポアソン過程です。
  • Webアクセス: アクセスログの解析では、非斉次ポアソン過程で時間帯ごとのアクセス強度をモデル化し、サーバー容量の計画に役立てます。

実データがポアソン過程に従うかは、データから検証できます。

実データのポアソン適合とQ-Qプロットによる指数性の検証

左の図は、単位時間あたりの発生回数(地震/日を想定した合成データ)のヒストグラムと、最尤推定したレート $\hat\lambda$(標本平均に一致)のポアソン分布を重ねたものです。観測頻度と理論PMFがよく一致しており、データがポアソン分布で説明できることを示しています。右の図は到着間隔のQ-Qプロット(アクセスログを想定)で、点が対角線に乗っていれば指数分布、つまりポアソン過程として妥当だと判断できます。実務では、ポアソン分布は期待値と分散が等しいので、標本分散が標本平均より大きい「過分散」が見られたら、ポアソン過程の仮定を疑い、負の二項分布や非斉次モデルを検討する、という流れになります。

まとめ

本記事では、ポアソン過程を入門から応用まで一本道で解説しました。

  • 計数過程と3公理: $N(0)=0$・独立増分・定常なポアソン増分の3条件でポアソン過程が定義され、長さ $t$ の区間のイベント数は $N(t) \sim \mathrm{Poisson}(\lambda t)$
  • 到着間隔は指数分布: $T_n \sim \mathrm{Exp}(\lambda)$ で互いに独立。指数分布だけが持つ無記憶性がポアソン過程の扱いやすさの源
  • 到着時刻はガンマ分布: $S_n \sim \mathrm{Gamma}(n, \lambda)$
  • 重ね合わせと間引き: 足せばレート和 $\lambda_1+\lambda_2$、確率 $p$ で間引けばレート $\lambda p$。どちらもポアソン過程のまま
  • 非斉次・複合への拡張: 時変レート $\lambda(t)$ で平均は $\int \lambda(u)du$、各イベントにサイズ $Y_i$ を付けると $X(t) = \sum_{i=1}^{N(t)} Y_i$ で平均は $\lambda t\,E[Y]$
  • M/M/1待ち行列: 平均系内数 $L = \rho/(1-\rho)$ は $\rho \to 1$ で発散。ポアソン到着と指数サービスが解析を可能にする

ポアソン過程は、待ち行列理論・通信工学・保険数理・信頼性工学など、広い分野の共通基盤です。ランダムさのごく自然な仮定だけから、ポアソン分布・指数分布・ガンマ分布という具体的な分布が必然的に決まる——この美しさこそが、ポアソン過程が長く使われ続ける理由です。

次のステップとして、以下の記事も参考にしてください。