フィッシャー情報行列(Fisher Information Matrix)とは?
(画像は、Geminiで作成されたものです)
フィッシャー情報行列の概要
フィッシャー情報行列(Fisher Information Matrix: FIM) は、統計学において「観測データが、確率分布の未知のパラメータについてどれだけの情報を持っているか」を定量化する行列です。
機械学習や強化学習(とくに TRPO などの自然勾配法)の文脈においては、単なる統計的な指標という枠を超え、「確率分布の空間における地形(曲率)」を表す計量テンソル として極めて重要な役割を果たします。
ディープラーニングの標準的な最適化手法(最急降下法やAdamなど)は、パラメータ空間の「ユークリッド距離」を基準にパラメータを更新します。しかし、確率分布を扱うアルゴリズムでは、パラメータのわずかな変化が、分布全体の形を致命的に破壊してしまうリスクがあります。フィッシャー情報行列を用いることで、単なる数字の変化量ではなく「確率分布の実際の変化量」を基準にした、安全で効率的な最適化が可能になります。
ユークリッド空間(パラメータ) vs 分布空間

なぜ、通常の勾配降下法ではなくフィッシャー情報行列が必要なのでしょうか? 正規分布 を例に考えてみましょう。
- ケースA: 平均 、標準偏差 から に変更する。
- ケースB: 平均 、標準偏差 から に変更する。
パラメータの「ユークリッド距離(数字上の変化量)」で見ると、どちらも が 変化しただけです。通常の勾配降下法は、この2つを「同じだけ進んだ」とみなします。 しかし、確率分布(ベルカーブ)の形を想像してください。ケースAでは分布の見た目はほとんど変わりませんが、ケースBでは分散が2倍になっており、分布の形状が劇的に変化(崩壊)しています。
このように、「パラメータ空間の距離」と「分布空間での実際の変化量(距離)」は全く一致しません。 フィッシャー情報行列は、現在のパラメータ位置における「分布の変化の激しさ」を行列表現したものです。これの逆行列を勾配に掛ける()ことで、勾配の歩幅を分布空間のスケールに合わせて自動的に補正する 自然勾配法(Natural Gradient Descent) が実現します。
では、なぜ「逆行列を掛ける」ことで歩幅の補正ができるのでしょうか?そして、フィッシャー情報行列は具体的にどのような数式で定義されるのでしょうか。
自然勾配法の仕組みと数学的な定義
なぜ を掛けるのか?
通常の最急降下法は、パラメータ を更新する際、「ユークリッド空間での移動距離 を一定以下に抑えつつ、目的関数を最も改善する方向」 へ進みます。 しかし、確率分布を扱う場合、パラメータの数値的な距離(ユークリッド距離)は「分布の実際の変化量」を正しく測れません。
そこで、「分布間の実際の距離(KLダイバージェンス)の変動を一定以下に抑えつつ、目的関数を最も改善する方向」 を求めます。この制約付き最適化問題を数学的に解くと、通常の勾配 に「KLダイバージェンスの曲率を示す行列」の逆行列を掛けた方向()が進むべき最適な方向として導出されます。
フィッシャー情報行列の数式
その「曲率を示す行列」であるフィッシャー情報行列 は、数式では以下のように定義されます。
ここで登場する は スコア関数 と呼ばれ、「パラメータ を微小に動かしたとき、データ の出現確率がどれくらい敏感に変化するか」を表すベクトルです。
この数式は、「スコア関数の外積の期待値(=分散)」を計算しています。つまり、「パラメータを少し動かしたときに、確率分布全体が平均してどれくらい激しく変動するか」という分布空間の曲率を行列として表現しているのです。
KLダイバージェンスとの美しい関係
この の数式は一見複雑ですが、特定の条件下において、KLダイバージェンスの2階微分(ヘッセ行列:Hessian) と完全に一致するという極めて美しい性質を持っています。
フィッシャー情報行列が単なる統計量ではなく、「現在のパラメータ付近における分布空間の歪み具合」そのものを表していることが、この等式からわかります。
KLダイバージェンスの定義から出発し、 で2回微分することで証明できます。
1. KLダイバージェンスの定義
2. について2階微分 の項は に依存しない定数となるため微分で消え、以下のようになります。
3. を代入 これを で評価すると、「負の対数尤度のヘッセ行列の期待値」になります。
4. 期待値がスコア関数の外積と一致する性質 確率の総和が1である性質()を で1回微分すると、定数()の微分なので になります。
ここで、対数関数の微分公式 を変形した を用います。これを代入すると、
となり、「スコア関数の期待値は である」ことが示せます。
次に、先ほどの の式をさらに でもう一度微分します。ここでは と表現し、積の微分法則()を使います。
第一項の に、再び を代入して整理すると、全体が期待値の形になります。
これを移行することで、探していた統計学の基本的な恒等式が導かれます。
結論 ステップ3の結果とステップ4の恒等式を繋げることで、ヘッセ行列がスコア関数の外積の期待値、すなわちフィッシャー情報行列 と完全に一致することがわかります。
TRPOでの活用
TRPO の理論では、「更新前の方策と更新後の方策のKLダイバージェンスを一定以下に抑える」という制約付き最適化問題を解きます。 このKLダイバージェンスの制約を、 の周りで2次のテイラー展開(二次近似)します。式に書き出すと以下のようになります。
この式の各項は次のように評価されます。
- 0次項: 全く同じ分布同士のKLダイバージェンスは になるため、 です。
- 1次項: KLダイバージェンスは常に の値をとり、 で最小値 をとります。最小値(極値)をとる点での微分は になるため、1階微分(勾配)も ベクトルになります(式の は転置を表します)。
- 2次項: KLダイバージェンスの2階微分(ヘッシアン)は、情報幾何学において「フィッシャー情報行列 」と一致することが知られています。これはKLダイバージェンスの定義式から以下のように導出されます。
これを で評価した値 は、対数尤度のヘッシアンの期待値の符号反転であり、まさに統計学におけるフィッシャー情報行列の定義そのものとなります。 最適化や強化学習の文脈ではヘッセ行列(Hessian)由来で と表記されることが多いですが、これは前述の と全く同じものです(※原論文のAppendix Cでは と表記されています)。
これらを踏まえると、次項と次項が完全に消去されるため、KLダイバージェンス制約は次項のみが残り、次のようにシンプルな二次形式で近似されます( を更新ステップ と置きます)。
コードによる挙動の確認
Pythonコードを使って、通常の「最急降下法」と、フィッシャー情報行列を用いた「自然勾配法」の挙動を比較してみましょう。 現在の正規分布 のパラメータを調整し、ターゲットとなる標準正規分布 に近づける(KLダイバージェンスを最小化する)問題を考えます。
import numpy as np
import matplotlib.pyplot as plt
import japanize_matplotlib
# 目的関数: Target N(0, 1) に対する N(μ, σ) の KLダイバージェンス
# KL(N(0, 1) || N(μ, σ)) = -log(σ) + (σ^2 + μ^2) / 2 - 0.5
def kl_divergence(mu, sigma):
return -np.log(sigma) + (sigma**2 + mu**2) / 2.0 - 0.5
# ユークリッド空間の勾配(1階微分)
# 記事中の数式 g = [∂KL/∂μ, ∂KL/∂σ]^T に対応
def grad_kl(mu, sigma):
grad_mu = mu # ∂KL/∂μ = μ
grad_sigma = sigma - 1.0 / sigma # ∂KL/∂σ = σ - 1/σ
return np.array([grad_mu, grad_sigma])
# フィッシャー情報行列の逆行列 (N(μ, σ)の場合は対角行列になるため解析的に求まる)
# H = [[1/σ^2, 0], [0, 2/σ^2]] -> H^-1 = [[σ^2, 0], [0, σ^2 / 2]]
def fisher_inverse(sigma):
return np.array([
[sigma**2, 0.0],
[0.0, (sigma**2) / 2.0]
])
# 探索空間と等高線の設定
mu_vals = np.linspace(-3, 3, 100)
sigma_vals = np.linspace(0.1, 3.5, 100)
M, S = np.meshgrid(mu_vals, sigma_vals)
Z = kl_divergence(M, S)
plt.figure(figsize=(8, 6))
plt.contour(M, S, Z, levels=np.logspace(-1.5, 2, 25), cmap='viridis', alpha=0.8)
plt.title("KLダイバージェンスの等高線 (横軸: μ, 縦軸: σ)")
plt.xlabel("平均 μ")
plt.ylabel("標準偏差 σ")
plt.colorbar(label='KLダイバージェンス')
plt.plot(0, 1, marker='*', color='gold', markersize=15, markeredgecolor='black', label='最適解 N(0, 1)')
plt.legend()
plt.grid(True, linestyle='--', alpha=0.5)
plt.show()
まず、最適化の対象となる目的関数として、ターゲット分布 と現在の分布 間のKLダイバージェンスを計算する kl_divergence 関数を定義しています。これは前述の に相当します。
続いて、通常の最急降下法で用いられる勾配ベクトル を計算する grad_kl を定義しています。ここでは解析的に求めた偏微分( と )を返します。
最後に、自然勾配法で必要となるフィッシャー情報行列の逆行列 (数式での )を返す fisher_inverse を定義しています。正規分布の場合、フィッシャー情報行列は対角行列となるため、簡単に逆行列を計算することが可能です。この逆行列には要素として が含まれており、これが後に歩幅を自動調整する鍵となります。
このコードでは、ターゲット分布 と現在の分布 の間のKLダイバージェンスを目的関数として設定しています。等高線を見ると、 が に近づく(下の方)と等高線の間隔が極端に狭くなり、急激な崖になっていることがわかります。
実行結果

最急降下法による探索(パラメータ空間での更新)
まず、ユークリッド空間の通常の勾配降下法(学習率 )で最適化を行います。初期値はあえて が小さい状態()からスタートします。
# 初期解の設定
init_params = np.array([-2.5, 0.2]) # μ = -2.5, σ = 0.2
alpha_sd = 0.5
params_sd = init_params.copy()
path_sd = [params_sd.copy()]
for i in range(50):
g = grad_kl(params_sd[0], params_sd[1])
# 勾配の方向へそのまま進む(通常の最急降下法)
# 数式: θ_{new} = θ_{old} - α * g に対応
params_sd = params_sd - alpha_sd * g
path_sd.append(params_sd.copy())
if np.linalg.norm(g) < 1e-3:
break
print(f"最急降下法の反復回数: {len(path_sd)-1}")
print("❌ 課題: σが小さい領域で勾配が爆発し、非効率で危険な大ジャンプをしてしまう。")
# 探索軌跡の可視化
path_sd_arr = np.array(path_sd)
plt.figure(figsize=(8, 6))
plt.contour(M, S, Z, levels=np.logspace(-1.5, 2, 25), cmap='viridis', alpha=0.6)
plt.plot(path_sd_arr[:, 0], path_sd_arr[:, 1], marker='o', color='red', linestyle='-', linewidth=2, label='最急降下法 (Standard GD)', alpha=0.8)
plt.plot(0, 1, marker='*', color='gold', markersize=15, markeredgecolor='black', label='最適解 N(0, 1)')
plt.title("最急降下法の探索軌跡")
plt.xlabel("平均 μ")
plt.ylabel("標準偏差 σ")
plt.legend()
plt.grid(True, linestyle='--', alpha=0.5)
plt.show()
ここでは、学習率 alpha_sd を用いて、通常の最急降下法(Standard Gradient Descent)によるパラメータの更新 を実行しています。 ループ内では、grad_kl で勾配 を計算し、そのままパラメータから引き算しています。しかし、 のように分散が極端に小さい状態からスタートすると、勾配 の の項が非常に大きな負の値(勾配爆発)となります。そのため、固定の学習率 を掛けてもパラメータが大きく弾き飛ばされてしまい、確率分布の空間において致命的な変化(方策崩壊)を引き起こす危険性が示されています。
実行結果
最急降下法の反復回数: 13
❌ 課題: σが小さい領域で勾配が爆発し、非効率で危険な大ジャンプをしてしまう。

の逆数成分()が勾配に含まれるため、 のような小さな領域では勾配が巨大になり、学習率を固定していても大きく弾き飛ばされるような挙動を示します。これを強化学習の方策に当てはめると「方策崩壊」に直結します。
自然勾配法による探索(分布空間での更新)
次に、フィッシャー情報行列の逆行列を掛けた「自然勾配法」で更新します。学習率は同じく です。
params_ngd = init_params.copy()
path_ngd = [params_ngd.copy()]
for i in range(50):
mu, sigma = params_ngd[0], params_ngd[1]
g = grad_kl(mu, sigma)
# フィッシャー情報行列の逆行列を勾配に乗じる (Natural Gradient)
# 数式: natural_grad = F^-1 * g
F_inv = fisher_inverse(sigma)
natural_grad = np.dot(F_inv, g)
# 分布空間のスケールに合わせて補正された自然勾配で更新
# 数式: θ_{new} = θ_{old} - α * natural_grad に対応
params_ngd = params_ngd - alpha_sd * natural_grad
path_ngd.append(params_ngd.copy())
if np.linalg.norm(g) < 1e-3:
break
print(f"自然勾配法の反復回数: {len(path_ngd)-1}")
print("⭕ 利点: 確率分布の変化度合いに合わせて歩幅が補正され、安定して最適解へ向かう。")
# 探索軌跡の可視化
path_ngd_arr = np.array(path_ngd)
plt.figure(figsize=(8, 6))
plt.contour(M, S, Z, levels=np.logspace(-1.5, 2, 25), cmap='viridis', alpha=0.6)
plt.plot(path_ngd_arr[:, 0], path_ngd_arr[:, 1], marker='s', color='blue', linestyle='-', linewidth=2, label='自然勾配法 (Natural GD)', alpha=0.8)
plt.plot(0, 1, marker='*', color='gold', markersize=15, markeredgecolor='black', label='最適解 N(0, 1)')
plt.title("自然勾配法の探索軌跡")
plt.xlabel("平均 μ")
plt.ylabel("標準偏差 σ")
plt.legend()
plt.grid(True, linestyle='--', alpha=0.5)
plt.show()
自然勾配法の実装では、通常の勾配 g をそのまま引くのではなく、先にフィッシャー情報行列の逆行列を生成する fisher_inverse(sigma) を呼び出し、F_inv を取得しています。 そして、np.dot(F_inv, g) によって逆行列と勾配の行列積()を計算し、これを natural_grad(自然勾配)として利用しています。 F_inv には分散 のスケール情報が含まれているため、 が極端に小さいときには歩幅が自動的に縮小され、急激な崖でも安全にパラメータを更新()することが可能となっています。
実行結果
自然勾配法の反復回数: 20
⭕ 利点: 確率分布の変化度合いに合わせて歩幅が補正され、安定して最適解へ向かう。

フィッシャー情報行列の逆行列 には が含まれています。これにより、 が小さい(崖の)領域では歩幅が自動的に小さく抑えられ、逆に平坦な領域では適切に歩幅が大きくなるよう調整されます。
探索軌跡の可視化
両者の軌跡を等高線グラフ上で比較します。
path_sd = np.array(path_sd)
path_ngd = np.array(path_ngd)
plt.figure(figsize=(10, 8))
plt.contour(M, S, Z, levels=np.logspace(-1.5, 2, 25), cmap='viridis', alpha=0.6)
# 最急降下法(赤)
plt.plot(path_sd[:, 0], path_sd[:, 1], marker='o', color='red',
linestyle='-', linewidth=2, label='最急降下法 (Standard GD)', alpha=0.8)
# 自然勾配法(青)
plt.plot(path_ngd[:, 0], path_ngd[:, 1], marker='s', color='blue',
linestyle='-', linewidth=2, label='自然勾配法 (Natural GD)', alpha=0.8)
plt.plot(0, 1, marker='*', color='gold', markersize=15,
markeredgecolor='black', label='最適解 N(0, 1)')
plt.title("最急降下法と自然勾配法の比較", fontsize=14, fontweight='bold')
plt.xlabel("平均 μ", fontsize=12)
plt.ylabel("標準偏差 σ", fontsize=12)
plt.legend()
plt.grid(True, linestyle='--', alpha=0.5)
plt.show()
ここでは、これまでに実行した最急降下法の軌跡(path_sd)と自然勾配法の軌跡(path_ngd)を、KLダイバージェンスの等高線上に同時に重ねてプロットしています。 path_sd[:, 0] と path_sd[:, 1] はそれぞれ各ステップにおける と の値を表しており、赤色の円形マーカー(marker='o', color='red')で描画されます。同様に、自然勾配法は青色の四角形マーカー(marker='s', color='blue')で描画しています。 このようにKLダイバージェンスの等高線上に両者の軌跡を可視化することで、「パラメータ空間のユークリッド距離」に基づく最急降下法が急峻な崖に弾かれる様子と、「確率分布空間のKLダイバージェンス」に基づく自然勾配法が地形に適応しながら一直線に最適解へ収束する様子の違いを直感的に比較できるようにしています。
実行結果

グラフから以下のことが明確にわかります。
- 赤線(最急降下法): スタート直後に 方向の急峻な勾配に弾かれ、 付近まで無意味にジャンプしています。その後、ゆっくりと最適解に戻ってきています。
- 青線(自然勾配法): フィッシャー情報行列によって「確率分布の空間」を基準に最適化しているため、急な崖に弾かれることなく、 と を同時に滑らかに更新しながら一直線に最適解(星マーク)へ収束しています。
深層学習(TRPO)への応用と計算コストの壁
自然勾配法は理論上極めて優秀ですが、ディープニューラルネットワークに直接適用しようとすると 計算量の壁 にぶつかります。
パラメータ数が の場合、フィッシャー情報行列 は の巨大な行列になります。 例えばパラメータが100万個あるモデルでは、行列の要素数は1兆個(約4TBのメモリが必要)となり、さらにその逆行列 を求める計算量 は天文学的な数字になります。
この問題をエレガントに解決したのが、TRPO において利用される 「フィッシャー・ベクトル積(FVP)」 と 「共役勾配法(CG)」 の組み合わせです。
- 共役勾配法は、逆行列 を直接求めることなく、方程式 を近似的に解くことができます。
- さらに、PyTorchなどの自動微分の仕組み(二重逆伝播)を利用すると、行列 を一度もメモリ上に構築することなく、「 とベクトル の掛け算の結果()」だけを直接取り出すことができます。
これにより、メモリや計算時間を爆発させることなく、巨大なニューラルネットワークに対しても自然勾配法の恩恵(安全かつ単調な方策の改善)をもたらすことが可能になりました。
まとめ
- フィッシャー情報行列(FIM) は、確率分布のパラメータ空間における「曲率(地形の歪み)」を表す行列です。
- これは KLダイバージェンスのヘッセ行列 と数学的に等価であり、分布間の真の距離を測る計量テンソルとして機能します。
- FIMの逆行列を用いる 自然勾配法 は、パラメータの数値上の変化ではなく「確率分布の形状変化」を基準にするため、方策崩壊を防ぐ極めて安定した最適化を実現します。
- TRPOなどの最先端のアルゴリズムでは、共役勾配法 を組み合わせて計算コストを削減することで、巨大なモデルへの自然勾配法の適用を実現しています。
本記事の文章・構成の一部に生成AIを使用しています。