ポアソン過程の定義と性質をわかりやすく解説

ポアソン過程(Poisson process)は、ランダムに発生するイベントを数学的にモデル化する確率過程です。「単位時間あたり一定の平均レートでイベントが起きる」状況を記述するのに適しており、待ち行列理論、通信ネットワーク、保険数理、放射線物理など、極めて広い分野で応用されています。

例えば、1時間に平均3件来る顧客、1日に平均5回発生するWebサーバーのエラー、放射性崩壊による粒子の放出など、ポアソン過程でモデル化できる現象は身の回りに多くあります。

本記事の内容

  • ポアソン過程の定義と公理
  • ポアソン分布との関係
  • 到着間隔の指数分布
  • 重要な性質(無記憶性、重ね合わせ、間引き)
  • Pythonでのシミュレーション

前提知識

この記事を読む前に、以下の概念を理解しておくと理解が深まります。

ポアソン過程の定義

計数過程

計数過程 $\{N(t), t \geq 0\}$ は、時刻 $t$ までに発生したイベントの数を表す確率過程です。

計数過程がポアソン過程(強度 $\lambda > 0$)であるとは、以下の条件を満たすことです。

  1. $N(0) = 0$
  2. 独立増分: 重ならない時間区間でのイベント数は互いに独立
  3. 定常増分: 長さ $t$ の区間でのイベント数は、区間の開始時刻に依存しない
  4. ポアソン分布: 長さ $t$ の区間でのイベント数は、パラメータ $\lambda t$ のポアソン分布に従う

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

別の定義(微小時間での定義)

等価な定義として、以下の3条件を満たす計数過程をポアソン過程といいます。

  1. $N(0) = 0$
  2. 独立増分
  3. 微小時間 $h$ での振る舞い:

$$ P(N(h) = 1) = \lambda h + o(h) $$

$$ P(N(h) \geq 2) = o(h) $$

ここで $o(h)$ は $h \to 0$ のとき $o(h)/h \to 0$ となる量です。つまり、十分短い時間にはイベントが高々1回しか起きないということです。

$\lambda$ の意味

$\lambda$ はイベントの強度(intensity)またはレート(rate)と呼ばれます。単位時間あたりの平均イベント数を表します。

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

ポアソン分布では期待値と分散が等しいという特徴があります。

到着間隔の指数分布

到着間隔

イベント間の時間間隔 $T_1, T_2, \dots$(到着間隔、interarrival time)を考えます。

$T_1$ は最初のイベントが起きるまでの時間です。

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

したがって $T_1$ の累積分布関数は $F(t) = 1 – e^{-\lambda t}$ であり、$T_1 \sim \mathrm{Exp}(\lambda)$(指数分布)に従います。

独立増分性と定常増分性から、すべての到着間隔 $T_n$ は独立に $\mathrm{Exp}(\lambda)$ に従います。

$$ T_n \sim \mathrm{Exp}(\lambda), \quad f_{T_n}(t) = \lambda e^{-\lambda t} \quad (t \geq 0) $$

指数分布の期待値

$$ E[T_n] = \frac{1}{\lambda} $$

レートが $\lambda = 3$ 件/時間 なら、平均到着間隔は $1/3$ 時間(20分)です。

到着時刻のガンマ分布

$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) $$

これは、独立な指数分布の和がガンマ分布に従うことからわかります。

重要な性質

無記憶性

ポアソン過程の到着間隔(指数分布)は無記憶性を持ちます。

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

つまり、すでに $s$ 時間待っていても、残りの待ち時間の分布は変わりません。この性質は指数分布だけが持つ特別な性質です。

重ね合わせ

レート $\lambda_1$ のポアソン過程とレート $\lambda_2$ のポアソン過程を重ね合わせると、レート $\lambda_1 + \lambda_2$ のポアソン過程になります。

間引き(thinning)

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

順序統計量

$[0, T]$ でポアソン過程により $n$ 個のイベントが発生したことが分かっているとき、その $n$ 個の到着時刻は $[0, T]$ 上の一様分布からの $n$ 個の独立な標本の順序統計量と同じ分布を持ちます。

Pythonでのシミュレーション

ポアソン過程の実現パス

import numpy as np
import matplotlib.pyplot as plt

np.random.seed(42)

def simulate_poisson_process(lam, T):
    """ポアソン過程をシミュレーション"""
    # 到着間隔を指数分布から生成
    interarrivals = []
    arrival_times = []
    t = 0
    while t < T:
        dt = np.random.exponential(1 / lam)
        t += dt
        if t < T:
            interarrivals.append(dt)
            arrival_times.append(t)
    return np.array(arrival_times), np.array(interarrivals)

lam = 3  # レート: 1時間あたり3件
T = 10   # 10時間

fig, axes = plt.subplots(2, 2, figsize=(14, 10))

# (1) 複数の実現パス
ax = axes[0, 0]
for i in range(5):
    arrivals, _ = simulate_poisson_process(lam, T)
    N_t = np.arange(1, len(arrivals) + 1)
    ax.step(arrivals, N_t, where='post', linewidth=1.5, alpha=0.8)
ax.set_xlabel('Time $t$')
ax.set_ylabel('$N(t)$')
ax.set_title(f'Poisson process sample paths ($\\lambda = {lam}$)')
ax.grid(True, alpha=0.3)

# (2) N(t)の分布の確認
ax = axes[0, 1]
t_check = 5
n_sim = 10000
counts = [len(simulate_poisson_process(lam, t_check)[0]) for _ in range(n_sim)]
from scipy import stats
k_vals = np.arange(0, 30)
poisson_pmf = stats.poisson.pmf(k_vals, lam * t_check)

ax.hist(counts, bins=np.arange(-0.5, 30.5, 1), density=True, alpha=0.7,
        color='steelblue', edgecolor='white', label='Simulation')
ax.plot(k_vals, poisson_pmf, 'ro-', markersize=5, label=f'Poisson($\\lambda t = {lam * t_check}$)')
ax.set_xlabel('$N(t)$')
ax.set_ylabel('Probability')
ax.set_title(f'Distribution of $N({t_check})$')
ax.legend()
ax.grid(True, alpha=0.3)

# (3) 到着間隔の分布
ax = axes[1, 0]
_, interarrivals = simulate_poisson_process(lam, 1000)
t_vals = np.linspace(0, 2, 100)
ax.hist(interarrivals, bins=50, density=True, alpha=0.7, color='orange', edgecolor='white',
        label='Simulation')
ax.plot(t_vals, lam * np.exp(-lam * t_vals), 'r-', linewidth=2,
        label=f'Exp($\\lambda = {lam}$)')
ax.set_xlabel('Interarrival time')
ax.set_ylabel('Density')
ax.set_title('Interarrival time distribution')
ax.legend()
ax.grid(True, alpha=0.3)

# (4) E[N(t)] = λt の確認
ax = axes[1, 1]
n_sim = 500
t_values = np.linspace(0.1, T, 50)
mean_counts = []
for t in t_values:
    counts_t = [len(simulate_poisson_process(lam, t)[0]) for _ in range(n_sim)]
    mean_counts.append(np.mean(counts_t))

ax.plot(t_values, mean_counts, 'bo', markersize=4, alpha=0.7, label='Simulated $E[N(t)]$')
ax.plot(t_values, lam * t_values, 'r-', linewidth=2, label='$\\lambda t$')
ax.set_xlabel('Time $t$')
ax.set_ylabel('$E[N(t)]$')
ax.set_title('$E[N(t)] = \\lambda t$')
ax.legend()
ax.grid(True, alpha=0.3)

plt.tight_layout()
plt.savefig('poisson_process.png', dpi=150, bbox_inches='tight')
plt.show()

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

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

np.random.seed(42)

fig, axes = plt.subplots(1, 2, figsize=(12, 5))

# 重ね合わせ
ax = axes[0]
lam1, lam2 = 2, 3
T = 100
n_sim = 5000

# 2つのポアソン過程を重ね合わせ
merged_counts = []
for _ in range(n_sim):
    arrivals1, _ = simulate_poisson_process(lam1, T)
    arrivals2, _ = simulate_poisson_process(lam2, T)
    merged_counts.append(len(arrivals1) + len(arrivals2))

k_vals = np.arange(350, 650)
poisson_pmf = stats.poisson.pmf(k_vals, (lam1 + lam2) * T)

ax.hist(merged_counts, bins=40, density=True, alpha=0.7, color='steelblue', edgecolor='white',
        label='Merged process')
ax.plot(k_vals, poisson_pmf, 'r-', linewidth=2,
        label=f'Poisson($\\lambda = {lam1 + lam2}$)')
ax.set_xlabel('$N(T)$')
ax.set_ylabel('Density')
ax.set_title(f'Superposition: $\\lambda_1={lam1}$ + $\\lambda_2={lam2}$')
ax.legend()
ax.grid(True, alpha=0.3)

# 間引き
ax = axes[1]
lam = 5
p = 0.4
thinned_counts = []
for _ in range(n_sim):
    arrivals, _ = simulate_poisson_process(lam, T)
    # 各イベントを確率pで採用
    kept = arrivals[np.random.random(len(arrivals)) < p]
    thinned_counts.append(len(kept))

k_vals = np.arange(100, 300)
poisson_pmf = stats.poisson.pmf(k_vals, lam * p * T)

ax.hist(thinned_counts, bins=40, density=True, alpha=0.7, color='orange', edgecolor='white',
        label='Thinned process')
ax.plot(k_vals, poisson_pmf, 'r-', linewidth=2,
        label=f'Poisson($\\lambda p = {lam * p}$)')
ax.set_xlabel('$N(T)$')
ax.set_ylabel('Density')
ax.set_title(f'Thinning: $\\lambda={lam}$, $p={p}$')
ax.legend()
ax.grid(True, alpha=0.3)

plt.tight_layout()
plt.savefig('poisson_superposition_thinning.png', dpi=150, bbox_inches='tight')
plt.show()

まとめ

本記事では、ポアソン過程の定義と性質を解説しました。

  • ポアソン過程: レート $\lambda$ でランダムにイベントが発生する計数過程
  • イベント数: 長さ $t$ の区間で $N(t) \sim \mathrm{Poisson}(\lambda t)$
  • 到着間隔: $T_n \sim \mathrm{Exp}(\lambda)$(指数分布)、互いに独立
  • 無記憶性: 指数分布の到着間隔は過去の待ち時間に依存しない
  • 重ね合わせ: レート $\lambda_1 + \lambda_2$ のポアソン過程になる
  • 間引き: レート $\lambda p$ のポアソン過程になる

ポアソン過程は待ち行列理論や信頼性工学の基礎です。非定常ポアソン過程($\lambda$ が時間に依存する場合)や複合ポアソン過程などの発展的なトピックにも応用できます。