AI・機械学習
上級
弾性的重み固定(EWC)(ダンセイテキオモミコテイ)
Fisher情報行列を用いて過去タスクで重要なパラメータを特定し、それらの変化にペナルティを課すことで壊滅的忘却を防ぐ継続学習手法。Kirkpatrickら(2017年)が提唱。
0 回閲覧
0 いいね
2026/6/6 更新
関連タグ
継続学習
Fisher情報行列
EWC
正則化
壊滅的忘却対策
弾性的重み固定(EWC)とは
EWC(Elastic Weight Consolidation)は2017年にKirkpatrick et al.(DeepMind)が「Overcoming catastrophic forgetting in neural networks」で提案した継続学習アルゴリズム。生物の脳における記憶の固定化(Memory Consolidation)を計算論的に模倣し、重要なシナプス(パラメータ)を保護することで壊滅的忘却を緩和する。
基本原理
数学的定式化
新しいタスクBを学習する際の損失関数にペナルティ項を追加:
L(θ) = L_B(θ) + Σᵢ (λ/2) * Fᵢ * (θᵢ - θ*_A,ᵢ)²
L_B(θ): タスクBの通常損失Fᵢ: パラメータiのFisher情報θ*_A,ᵢ: タスクA学習後の最適パラメータλ: 正則化強度のハイパーパラメータ
Fisher情報行列の計算
import torch
from torch import nn
def compute_fisher_information(model, dataset, device):
"""
タスクAのデータセットを用いてFisher情報行列を推定
各パラメータの重要度スコアを返す
"""
fisher_dict = {n: torch.zeros_like(p)
for n, p in model.named_parameters()}
model.eval()
for inputs, labels in dataset:
model.zero_grad()
outputs = model(inputs.to(device))
# 対数尤度の勾配の二乗期待値 = Fisher情報の対角近似
log_prob = torch.log_softmax(outputs, dim=1)
loss = log_prob[range(len(labels)), labels].mean()
loss.backward()
for n, p in model.named_parameters():
if p.grad is not None:
fisher_dict[n] += p.grad.data.pow(2)
# データ数で正規化
for n in fisher_dict:
fisher_dict[n] /= len(dataset)
return fisher_dict
EWCの実装例
class EWC:
def __init__(self, model, dataset, device, importance=1000):
self.model = model
self.importance = importance
# タスクA学習後のパラメータを保存
self.prev_params = {n: p.clone()
for n, p in model.named_parameters()}
# Fisher情報を計算
self.fisher = compute_fisher_information(
model, dataset, device
)
def penalty(self):
"""EWCペナルティ項を計算"""
loss = 0
for n, p in self.model.named_parameters():
if n in self.fisher:
_loss = (self.fisher[n] *
(p - self.prev_params[n]).pow(2))
loss += _loss.sum()
return self.importance / 2 * loss
# タスクB学習時の使用例
ewc = EWC(model, task_a_dataset, device, importance=1000)
optimizer = torch.optim.Adam(model.parameters(), lr=1e-4)
for batch in task_b_dataloader:
optimizer.zero_grad()
# タスクBの通常損失
outputs = model(batch['input_ids'])
task_loss = criterion(outputs, batch['labels'])
# EWCペナルティを加算
ewc_loss = ewc.penalty()
total_loss = task_loss + ewc_loss
total_loss.backward()
optimizer.step()
λ(重要度)の設定
| λ値 | 効果 |
|---|---|
| 0 | EWCなし(通常ファインチューニング) |
| 100-1000 | 軽度の保護(新タスクへの適応優先) |
| 10000-100000 | 強保護(旧タスク維持優先) |
| ∞ | 完全凍結(旧タスクは完璧に維持、新タスク学習不可) |
最適なλはタスクの類似度・モデル規模・要求される安定性に依存。
LLMへの適用課題と近似手法
スケール問題
GPT-3(175B params)にフルFisher行列を計算すると:
- パラメータ数: 1.75×10¹¹
- Fisher行列ストレージ: 1.75×10¹¹ × 4bytes ≈ 700GB
- 実用不可
近似手法
1. 対角近似(Diagonal Fisher)
- Fisher行列の対角成分のみ使用(パラメータごとのスカラー値)
- ストレージ: パラメータ数 × 4bytes(LLaMA-7B: 約28GB)
- 精度vs実用性のバランスが良い
2. K-FAC(Kronecker-Factored AC)
- 各レイヤーのFisherをKronecker積で近似
- より正確だが実装が複雑
3. EWC + PEFT(推奨)
# LoRAパラメータのみにEWCを適用
# フルモデルより大幅に計算量削減
lora_params = [(n, p) for n, p in model.named_parameters()
if 'lora_' in n]
# LoRAアダプタのFisher情報のみ計算
fisher_lora = compute_fisher_for_params(model, dataset, lora_params)
Online EWC
タスクが増えるたびにFisher情報を蓄積・更新する拡張版:
class OnlineEWC:
def __init__(self, model, gamma=0.95):
self.model = model
self.gamma = gamma # 過去タスクの減衰率
self.F_accum = {} # 蓄積Fisher情報
self.prev_params = {}
def update_after_task(self, dataset, device):
"""タスク完了後にFisher情報を更新"""
new_fisher = compute_fisher_information(model, dataset, device)
for n in new_fisher:
if n in self.F_accum:
# 指数移動平均でFisherを更新
self.F_accum[n] = (
self.gamma * self.F_accum[n] +
new_fisher[n]
)
else:
self.F_accum[n] = new_fisher[n]
# 現在のパラメータを保存
self.prev_params = {
n: p.clone() for n, p in model.named_parameters()
}
EWCの限界と代替手法との比較
| 手法 | 忘却防止効果 | 計算コスト | ストレージ | スケーラビリティ |
|---|---|---|---|---|
| EWC | ★★★ | 中(Fisher計算) | 中(Fisher保存) | △(大規模で困難) |
| LoRA | ★★★★ | 低 | 低 | ◎ |
| リプレイ | ★★★★★ | 低(学習時) | 高(データ保持) | ◯ |
| Progressive Nets | ★★★★★ | 中 | 高(パラメータ増加) | △ |
2025年時点では、LLMへのEWC直接適用よりもLoRAとリプレイの組み合わせが実用的な標準として普及している。ただしEWCの理論的枠組みは継続学習の基礎として依然重要。