mcpField
T
transformer-lens-interpretability

transformer-lens-interpretability

github.com/orchestra-researchデータ・データベース14.1k962 回インストール19 週間前に更新
リポジトリ

transformer-lens-interpretability について

TransformerLensは、GPTスタイルの言語モデルの内部メカニズムを研究するためのPythonライブラリです。各活性化に設けられたHookPointを通じて、内部の検査や介入、回路分析を行えます。

主な機能

  1. 01モデル活性化へのフック
  2. 02中間活性化のキャッシュ
  3. 03活性化パッチングと因果追跡
  4. 04注意パターンと回路の分析
  5. 05直接ロジット帰属

活用シーン

  1. 01出力に影響する活性化の追跡
  2. 02注意パターンと情報の流れの検査
  3. 03誘導ヘッドやIOI回路の分析

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/orchestra-research/ai-research-skills --skill transformer-lens-interpretability

インストール後、Claude Code で/transformer-lens-interpretabilityを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
api.md
README.md
tutorials.md

詳細

TransformerLens: Transformer のメカニスティック解釈可能性

TransformerLens は、GPT 系の言語モデルに対するメカニスティック解釈可能性の研究における事実上の標準ライブラリです。Neel Nanda が作成し、Bryce Meyer が保守しています。すべてのアクティベーションに HookPoint を設けることで、モデルの内部を調べたり操作したりするための分かりやすいインターフェースを提供します。

GitHub: TransformerLensOrg/TransformerLens(スター数 2,900 以上)

TransformerLens を使うべき場合

次のような場合は TransformerLens を使用してください:

  • 学習中に獲得されたアルゴリズムをリバースエンジニアリングしたい
  • アクティベーションパッチング / 因果トレーシングの実験を行いたい
  • アテンションパターンと情報の流れを調べたい
  • 回路(例: induction head、IOI 回路)を分析したい
  • 中間アクティベーションをキャッシュして調べたい
  • 直接ロジット帰属を適用したい

次のような場合は代替手段を検討してください:

  • Transformer 以外のアーキテクチャを扱う必要がある → nnsight または pyvene を使用
  • Sparse Autoencoder を学習・分析したい → SAELens を使用
  • 超大規模モデルをリモートで実行する必要がある → NDIF 付きの nnsight を使用
  • より高レベルな因果介入の抽象化が必要 → pyvene を使用

インストール

pip install transformer-lens

開発版の場合:

pip install git+https://github.com/TransformerLensOrg/TransformerLens

コアコンセプト

HookedTransformer

すべてのアクティベーションに HookPoint を設けて Transformer モデルをラップする中心的なクラスです:

from transformer_lens import HookedTransformer

# Load a model
model = HookedTransformer.from_pretrained("gpt2-small")

# For gated models (LLaMA, Mistral)
import os
os.environ["HF_TOKEN"] = "your_token"
model = HookedTransformer.from_pretrained("meta-llama/Llama-2-7b-hf")
対応モデル(50 以上)
ファミリーモデル
GPT-2gpt2, gpt2-medium, gpt2-large, gpt2-xl
LLaMAllama-7b, llama-13b, llama-2-7b, llama-2-13b
EleutherAIpythia-70m から pythia-12b まで, gpt-neo, gpt-j-6b
Mistralmistral-7b, mixtral-8x7b
その他phi, qwen, opt, gemma
アクティベーションのキャッシュ

モデルを実行し、中間アクティベーションをすべてキャッシュします:

# Get all activations
tokens = model.to_tokens("The Eiffel Tower is in")
logits, cache = model.run_with_cache(tokens)

# Access specific activations
residual = cache["resid_post", 5]  # Layer 5 residual stream
attn_pattern = cache["pattern", 3]  # Layer 3 attention pattern
mlp_out = cache["mlp_out", 7]  # Layer 7 MLP output

# Filter which activations to cache (saves memory)
logits, cache = model.run_with_cache(
    tokens,
    names_filter=lambda name: "resid_post" in name
)
ActivationCache のキー
キーのパターン形状説明
resid_pre, layer[batch, pos, d_model]アテンション前の残差
resid_mid, layer[batch, pos, d_model]アテンション後の残差
resid_post, layer[batch, pos, d_model]MLP 後の残差
attn_out, layer[batch, pos, d_model]アテンションの出力
mlp_out, layer[batch, pos, d_model]MLP の出力
pattern, layer[batch, head, q_pos, k_pos]アテンションパターン(softmax 後)
q, layer[batch, pos, head, d_head]クエリベクトル
k, layer[batch, pos, head, d_head]キーベクトル
v, layer[batch, pos, head, d_head]バリューベクトル

ワークフロー 1: アクティベーションパッチング(因果トレーシング)

破損させた入力の実行に対して、クリーンなアクティベーションをパッチとして適用することで、モデルの出力に因果的に影響するアクティベーションを特定します。

ステップごとの手順
from transformer_lens import HookedTransformer, patching
import torch

model = HookedTransformer.from_pretrained("gpt2-small")

# 1. Define clean and corrupted prompts
clean_prompt = "The Eiffel Tower is in the city of"
corrupted_prompt = "The Colosseum is in the city of"

clean_tokens = model.to_tokens(clean_prompt)
corrupted_tokens = model.to_tokens(corrupted_prompt)

# 2. Get clean activations
_, clean_cache = model.run_with_cache(clean_tokens)

# 3. Define metric (e.g., logit difference)
paris_token = model.to_single_token(" Paris")
rome_token = model.to_single_token(" Rome")

def metric(logits):
    return logits[0, -1, paris_token] - logits[0, -1, rome_token]

# 4. Patch each position and layer
results = torch.zeros(model.cfg.n_layers, clean_tokens.shape[1])

for layer in range(model.cfg.n_layers):
    for pos in range(clean_tokens.shape[1]):
        def patch_hook(activation, hook):
            activation[0, pos] = clean_cache[hook.name][0, pos]
            return activation

        patched_logits = model.run_with_hooks(
            corrupted_tokens,
            fwd_hooks=[(f"blocks.{layer}.hook_resid_post", patch_hook)]
        )
        results[layer, pos] = metric(patched_logits)

# 5. Visualize results (layer x position heatmap)
チェックリスト
  • 最小限だけ異なるクリーンな入力と破損した入力を定義する
  • 振る舞いの差を捉える指標を選ぶ
  • クリーンなアクティベーションをキャッシュする
  • (layer, position) の組み合わせをすべて体系的にパッチする
  • 結果をヒートマップとして可視化する
  • 因果的なホットスポットを特定する

ワークフロー 2: 回路分析(間接目的語の特定)

「Interpretability in the Wild」からの IOI 回路の発見を再現します。

ステップごとの手順
from transformer_lens import HookedTransformer
import torch

model = HookedTransformer.from_pretrained("gpt2-small")

# IOI task: "When John and Mary went to the store, Mary gave a bottle to"
# Model should predict "John" (indirect object)

prompt = "When John and Mary went to the store, Mary gave a bottle to"
tokens = model.to_tokens(prompt)

# 1. Get baseline logits
logits, cache = model.run_with_cache(tokens)

john_token = model.to_single_token(" John")
mary_token = model.to_single_token(" Mary")

# 2. Compute logit difference (IO - S)
logit_diff = logits[0, -1, john_token] - logits[0, -1, mary_token]
print(f"Logit difference: {logit_diff.item():.3f}")

# 3. Direct logit attribution by head
def get_head_contribution(layer, head):
    # Project head output to logits
    head_out = cache["z", layer][0, :, head, :]  # [pos, d_head]
    W_O = model.W_O[layer, head]  # [d_head, d_model]
    W_U = model.W_U  # [d_model, vocab]

    # Head contribution to logits at final position
    contribution = head_out[-1] @ W_O @ W_U
    return contribution[john_token] - contribution[mary_token]

# 4. Map all heads
head_contributions = torch.zeros(model.cfg.n_layers, model.cfg.n_heads)
for layer in range(model.cfg.n_layers):
    for head in range(model.cfg.n_heads):
        head_contributions[layer, head] = get_head_contribution(layer, head)

# 5. Identify top contributing heads (name movers, backup name movers)
チェックリスト
  • 明確な IO/S トークンを設定してタスクを用意する
  • ベースラインのロジット差を計算する
  • アテンションヘッドごとの寄与に分解する
  • 主要な回路の構成要素(name mover、S-inhibition、induction)を特定する
  • アブレーション実験で検証する

ワークフロー 3: Induction Head の検出

[A][B]...[A] → [B] のパターンを実装する induction head を見つけます。

from transformer_lens import HookedTransformer
import torch

model = HookedTransformer.from_pretrained("gpt2-small")

# Create repeated sequence: [A][B][A] should predict [B]
repeated_tokens = torch.tensor([[1000, 2000, 1000]])  # Arbitrary tokens

_, cache = model.run_with_cache(repeated_tokens)

# Induction heads attend from final [A] back to first [B]
# Check attention from position 2 to position 1
induction_scores = torch.zeros(model.cfg.n_layers, model.cfg.n_heads)

for layer in range(model.cfg.n_layers):
    pattern = cache["pattern", layer][0]  # [head, q_pos, k_pos]
    # Attention from pos 2 to pos 1
    induction_scores[layer] = pattern[:, 2, 1]

# Heads with high scores are induction heads
top_heads = torch.topk(induction_scores.flatten(), k=5)

よくある問題と解決策

問題: デバッグ後もフックが残る
# WRONG: Old hooks remain active
model.run_with_hooks(tokens, fwd_hooks=[...])  # Debug, add new hooks
model.run_with_hooks(tokens, fwd_hooks=[...])  # Old hooks still there!

# RIGHT: Always reset hooks
model.reset_hooks()
model.run_with_hooks(tokens, fwd_hooks=[...])
問題: トークン化の落とし穴
# WRONG: Assuming consistent tokenization
model.to_tokens("Tim")  # Single token
model.to_tokens("Neel")  # Becomes "Ne" + "el" (two tokens!)

# RIGHT: Check tokenization explicitly
tokens = model.to_tokens("Neel", prepend_bos=False)
print(model.to_str_tokens(tokens))  # ['Ne', 'el']
問題: 分析で LayerNorm が無視される
# WRONG: Ignoring LayerNorm
pre_activation = residual @ model.W_in[layer]

# RIGHT: Include LayerNorm
ln_scale = model.blocks[layer].ln2.w
ln_out = model.blocks[layer].ln2(residual)
pre_activation = ln_out @ model.W_in[layer]
問題: 大規模モデルでのメモリ爆発
# Use selective caching
logits, cache = model.run_with_cache(
    tokens,
    names_filter=lambda n: "resid_post" in n or "pattern" in n,
    device="cpu"  # Cache on CPU
)

主要クラスリファレンス

クラス用途
HookedTransformerフック付きのメインモデルラッパー
ActivationCacheアクティベーションを格納する辞書型のキャッシュ
HookedTransformerConfigモデルの設定
FactoredMatrix効率的な因数分解行列の演算

SAELens との統合

TransformerLens は、スパースオートエンコーダー分析のために SAELens と統合されています:

from transformer_lens import HookedTransformer
from sae_lens import SAE

model = HookedTransformer.from_pretrained("gpt2-small")
sae = SAE.from_pretrained("gpt2-small-res-jb", "blocks.8.hook_resid_pre")

# Run with SAE
tokens = model.to_tokens("Hello world")
_, cache = model.run_with_cache(tokens)
sae_acts = sae.encode(cache["resid_pre", 8])

リファレンスドキュメント

詳細な API ドキュメント、チュートリアル、高度な使い方については、references/ フォルダーを参照してください:

ファイル内容
references/README.md概要とクイックスタートガイド
references/api.mdHookedTransformer、ActivationCache、HookPoints の完全な API リファレンス
references/tutorials.mdアクティベーションパッチング、回路分析、ロジットレンズのステップバイステップのチュートリアル

外部リソース

チュートリアル
論文
公式ドキュメント

バージョンに関する注意

  • v2.0: HookedSAE を削除(SAELens に移行)
  • v3.0 (alpha): 任意の nn.Module を読み込むための TransformerBridge

コメント