グラフィカルモデルとは?確率変数の依存関係をグラフで表現する

グラフィカルモデルは、多変量の確率変数間の依存関係をグラフ構造で表現する手法です。機械学習やベイズ統計の論文で頻繁に登場し、複雑な確率分布を視覚的に整理する強力なツールとなっています。

確率変数をノード、依存関係をエッジで表すことで、同時確率分布の分解構造が一目で理解でき、条件付き独立性の判定も体系的に行えるようになります。

本記事の内容

  • グラフィカルモデルの2つの種類(有向・無向)
  • ベイズネットワークにおける確率の分解
  • Head-to-tail, Tail-to-tail, Head-to-head の3パターン
  • d分離の概念
  • Pythonによるベイズネットワークの構築

前提知識

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

  • 条件付き確率 $p(A|B)$
  • 確率の乗法定理 $p(A,B) = p(A|B)p(B)$
  • 確率変数の独立性

グラフィカルモデルの種類

グラフィカルモデルは大きく2種類に分類されます。

有向グラフィカルモデル(ベイズネットワーク, Bayesian Network):

エッジに方向がある(矢印で表現)。DAG(Directed Acyclic Graph, 有向非巡回グラフ)を用いて因果関係を表現します。

無向グラフィカルモデル(マルコフ確率場, Markov Random Field):

エッジに方向がない。変数間の相互関係を表現し、画像処理などで利用されます。

ベイズネットワークと確率の分解

ベイズネットワークでは、各ノードの条件付き確率を親ノードのみで条件付けることで、同時確率分布を効率的に分解します。

ノード $x_1, x_2, \dots, x_K$ からなるベイズネットワークの同時確率は、

$$ p(x_1, x_2, \dots, x_K) = \prod_{k=1}^{K} p(x_k | \text{pa}(x_k)) $$

と表されます。ここで $\text{pa}(x_k)$ はノード $x_k$ の親ノードの集合です。

例えば、$a \to c \to b$ という構造の場合、

$$ p(a, b, c) = p(a) \cdot p(c | a) \cdot p(b | c) $$

と分解できます。これにより、全変数の同時分布を直接扱う代わりに、局所的な条件付き確率の積として表現できます。

条件付き独立の3パターン

ベイズネットワークにおける条件付き独立性は、3つの基本パターンで理解できます。

Head-to-tail型

$$ a \to c \to b $$

変数 $c$ が観測されている場合、$a$ と $b$ は条件付き独立です。

$$ p(a, b | c) = p(a | c) \cdot p(b | c) $$

同時確率を展開して確認します。

$$ \begin{align} p(a, b, c) &= p(a) \cdot p(c | a) \cdot p(b | c) \\ p(a, b | c) &= \frac{p(a, b, c)}{p(c)} = \frac{p(a) \cdot p(c | a)}{p(c)} \cdot p(b | c) \\ &= p(a | c) \cdot p(b | c) \end{align} $$

$c$ が観測されると、$a$ の情報は $b$ に伝わりません。

Tail-to-tail型

$$ a \leftarrow c \to b $$

$c$ が $a$ と $b$ の共通の親である場合。$c$ が観測されると $a$ と $b$ は条件付き独立になります。

$$ \begin{align} p(a, b, c) &= p(c) \cdot p(a | c) \cdot p(b | c) \\ p(a, b | c) &= p(a | c) \cdot p(b | c) \end{align} $$

Head-to-head型(合流点, V構造)

$$ a \to c \leftarrow b $$

$c$ が観測されていない場合、$a$ と $b$ は独立です。しかし、$c$(またはその子孫)が観測されると、$a$ と $b$ は条件付き従属になります。

$$ p(a, b) = p(a) \cdot p(b) $$

ですが、$c$ を観測すると $a$ と $b$ に依存関係が生じます。これは「explaining away」効果と呼ばれます。

d分離(d-separation)

上記の3パターンを一般化した概念がd分離です。

ノード集合 $A$ と $B$ が、ノード集合 $C$ によって d分離 されているとは、$A$ から $B$ への全てのパスが $C$ によってブロックされていることを意味します。パスがブロックされる条件は、

  1. パス上にHead-to-tailまたはTail-to-tail型のノードがあり、そのノードが $C$ に含まれる
  2. パス上にHead-to-head型のノードがあり、そのノードもその子孫も $C$ に含まれない

d分離が成り立つとき、$A \perp B | C$($C$ を条件として $A$ と $B$ は独立)が成り立ちます。

Pythonでの実装

ベイズネットワークの構造をPythonで構築し、条件付き独立性を確認します。

import numpy as np
import matplotlib.pyplot as plt
import networkx as nx

np.random.seed(42)

# --- ベイズネットワークの構造を定義 ---
G = nx.DiGraph()
G.add_edges_from([
    ('Rain', 'Wet_Grass'),
    ('Sprinkler', 'Wet_Grass'),
    ('Rain', 'Sprinkler')
])

# ネットワークの可視化
fig, ax = plt.subplots(figsize=(8, 5))
pos = {'Rain': (1, 2), 'Sprinkler': (0, 1), 'Wet_Grass': (2, 1)}
nx.draw(G, pos, with_labels=True, node_color='lightblue',
        node_size=3000, font_size=12, font_weight='bold',
        arrows=True, arrowsize=20, ax=ax)
ax.set_title('Bayesian Network: Rain-Sprinkler-WetGrass')
plt.tight_layout()
plt.show()

# --- 条件付き確率表の定義 ---
# P(Rain)
p_rain = {True: 0.2, False: 0.8}

# P(Sprinkler | Rain)
p_sprinkler = {
    (True,): 0.01,   # P(Sprinkler=True | Rain=True)
    (False,): 0.4    # P(Sprinkler=True | Rain=False)
}

# P(WetGrass | Sprinkler, Rain)
p_wet = {
    (True, True): 0.99,
    (True, False): 0.9,
    (False, True): 0.8,
    (False, False): 0.0
}

# --- モンテカルロシミュレーション ---
n_sim = 100000
rain = np.random.random(n_sim) < p_rain[True]
sprinkler = np.array([
    np.random.random() < p_sprinkler[(r,)] for r in rain
])
wet_grass = np.array([
    np.random.random() < p_wet[(s, r)] for s, r in zip(sprinkler, rain)
])

# --- 条件付き独立性の確認 ---
# Rain=Trueのとき、SprinklerとWet_Grassは条件付き独立か?
mask_rain = rain == True
mask_rain_sprinkler = mask_rain & (sprinkler == True)
mask_rain_wet = mask_rain & (wet_grass == True)
mask_all = mask_rain & (sprinkler == True) & (wet_grass == True)

p_s_given_r = mask_rain_sprinkler.sum() / mask_rain.sum()
p_w_given_r = mask_rain_wet.sum() / mask_rain.sum()
p_sw_given_r = mask_all.sum() / mask_rain.sum()

print("=== Rain=True を条件としたとき ===")
print(f"P(Sprinkler=T | Rain=T) = {p_s_given_r:.4f}")
print(f"P(WetGrass=T | Rain=T) = {p_w_given_r:.4f}")
print(f"P(S=T, W=T | Rain=T)   = {p_sw_given_r:.4f}")
print(f"P(S|R) * P(W|R)        = {p_s_given_r * p_w_given_r:.4f}")
print(f"→ 差分: {abs(p_sw_given_r - p_s_given_r * p_w_given_r):.4f}")

# 周辺分布での確認(条件なし)
p_s = sprinkler.mean()
p_w = wet_grass.mean()
p_sw = (sprinkler & wet_grass).mean()
print(f"\n=== 条件なし ===")
print(f"P(Sprinkler=T) = {p_s:.4f}")
print(f"P(WetGrass=T)  = {p_w:.4f}")
print(f"P(S=T, W=T)    = {p_sw:.4f}")
print(f"P(S) * P(W)    = {p_s * p_w:.4f}")

まとめ

本記事では、グラフィカルモデルの基本概念について解説しました。

  • グラフィカルモデルは確率変数間の依存関係をグラフで表現する手法
  • ベイズネットワーク(有向グラフ)では同時分布を条件付き確率の積に分解できる
  • 条件付き独立はHead-to-tail、Tail-to-tail、Head-to-headの3パターンで理解できる
  • d分離により、観測変数を条件としたときの独立性を体系的に判定できる

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