原理層は「なぜこの形なのか」、実装層は「どう回すか」。層が違えば効く手も違うが、効かせたい相手(制約)はどこまでも同じ四つです。
| レイヤ | 支配的な制約 | 代表的な解 |
|---|---|---|
| 表現 | 語彙サイズ × 系列長 | サブワード |
| 計算 | Attention の O(L²) | 並列化・FlashAttention・FiD |
| 訓練 | VRAM とインターコネクト | LoRA / ZeRO / 混合精度 |
| 推論 | メモリ帯域律速 | 量子化・蒸留・continuous batching |
| 知識 | パラメータに焼き込めない情報 | RAG |
| 制御 | 単発推論では解けないタスク | エージェントループ |
元の質問文に含まれていた前提のうち、実際とずれていたもの。ここだけ先に読んでも価値があります。共通して厄介なのは、どれも例外を投げないこと —— 精度やスループットだけが静かに落ちます。
streaming=True にすれば RAM への全展開を避けられるdatasets は RAM に全展開しない。Apache Arrow でディスクに置き mmap する。100GB でも RAM は数百 MB。真の違いはディスク容量と初回起動時間、そして len() と再開性を失うこと。asyncio.Queue で LLM をバッチ配信するtorch.compile が同種の最適化を PyTorch 内で行う現在、ONNX の主価値は速度より PyTorch 非依存の環境への移植性に移っています。機械学習とルールベースの差は「賢さ」ではなく、人間が書く対象が入れ替わったことにあります。
従来型プログラミングでは、人間が写像 f そのものを記述していました。機械学習で人間が書くのは二つだけです。(a) パラメータ付き関数族(アーキテクチャ)と(b) 損失関数。f はその中から誤差最小化の探索結果として決まります。
| 理由 | 内容 |
|---|---|
| ① 非線形性の合成 | 線形変換をいくら積んでも線形変換のまま。非線形活性化(ReLU 等)を挟んで初めて、単層では表現できない決定境界が作れる。古典例はパーセプトロンと XOR。 |
| ② 表現の階層性 | 普遍近似定理より単層でも理論上は任意関数を近似できる。しかし必要な幅が指数爆発する。深くすると下位層の特徴を上位層が部品として再利用でき、同じ表現力を遥かに少ないパラメータで達成できる。 |
長距離依存と計算効率という別々の問題を、同じ設計変更ひとつで解いた——ここが要諦です。
Transformer の一手は、再帰を捨てて任意の 2 トークン間を 1 回の Attention で直結すること。これで 経路長 O(1) と 逐次依存の消滅 が同時に成立します。
各トークン埋め込みを 3 つの学習済み行列で射影し、Query(何を探すか)/Key(何を提供できるか)/Value(実際に渡す情報)を得る。Q と全 K の内積でスコアを取り、√dk でスケールし、softmax で合計 1 の重みへ正規化し、その重みで V を加重平均する。
Multi-Head は複数の部分空間で並列実行する仕組みです。あるヘッドは主語-述語の一致を、別のヘッドは代名詞の先行詞を——というように異なる関係を同時に捉える。単一の注意分布では、どれか一つの関係しか表現できないからです。
再帰がないので全トークンの Q, K, V を一度に計算でき、Attention 全体が QKᵀ という一回の行列積に帰着します。GPU が最も得意な形式です。ただし代償が二つ。
並列なのは訓練時と入力符号化時です。自己回帰生成(推論)は 1 トークンずつ逐次にしか進みません。実務では KV キャッシュで再計算を避けますが、逐次性そのものは消えない。§11 のサービング最適化がすべてここに由来します。
Transformer が要求するのは ベクトルの列と位置情報だけ。言語であることは要件ではありません。
| モダリティ | 系列化の方法 |
|---|---|
| 画像(ViT) | 16×16 等の固定パッチに分割 → 平坦化 → 線形射影で d 次元へ。以降「パッチ=単語」。2 次元の位置埋め込みを付与する。 |
| 音声(Whisper 系) | 25ms 窓 / 10ms ホップ → メルスペクトログラム → 時間フレーム列。 |
| 音声(wav2vec 2.0 系) | 生波形に畳み込み層をかけて特徴ベクトル列にする。 |
「文字列を数字にする」以上のことをしています。語彙サイズ V と系列長 L のトレードオフを最適化する装置です。
モデルとトークナイザは必ずペアです。片方を差し替えると ID の意味づけが総崩れになる。AutoTokenizer.from_pretrained() にモデルと同じチェックポイント名を渡す規約は、この制約の反映にすぎません。
語彙に 文字(またはバイト)レベルの単位を必ず含める ことで、任意の文字列を既知断片の列へ分解可能にする——これが設計の骨格です。
| 手法 | 統合 / 削減の基準 |
|---|---|
| BPE | 頻出する隣接ペアを貪欲に統合していく。 |
| WordPiece | 尤度向上量 p(xy) / p(x)p(y) が最大のペアを統合する。 |
| Unigram | 大きな候補集合から損失の小さい単位を削り落とす(逆方向のアプローチ)。 |
バッチ処理は (batch_size, seq_len) の矩形テンソルを要求します。長さの不揃いは許されない。
短い系列に pad_token_id を詰めて長さを揃える。
決定的に重要なのは同時生成される attention_mask。パディング位置を 0 とし、Attention スコア計算時にそこへ −∞ を加算して softmax 後の重みをゼロにする。渡し忘れると、モデルは詰め物を実在の文脈として読む。
max_length(多くは位置埋め込みの上限。BERT なら 512)の超過分を切り捨てる。
[CLS] [SEP] 等の特殊トークン分を予め差し引く必要がある。文ペアでは longest_first 等でどちらを削るか決める。
padding='max_length' より padding='longest'(動的パディング)。Attention が O(L²) である以上、無駄なパディングのコストは 2 乗で効きます。pipeline() の内側事前学習・ファインチューニング・推論で、モデルの内部状態は何が変わり、何が変わらないのか。
| ステージ | 重みの状態 | 目的関数 | コスト |
|---|---|---|---|
| 事前学習 | ランダム初期化 → 全パラメータ更新 | 自己教師あり(MLM / 次トークン予測) | 大半がここに集中 |
| ファインチューニング | 事前学習済みをロード、タスクヘッドのみ新規初期化 | 教師あり | 中〜小 |
| 推論 | 一切変化しない | なし | 小(ただし累積する) |
model.eval() で dropout 無効化・BatchNorm 統計固定、torch.no_grad() で計算グラフの保持を停止。変化するのはアクティベーションだけ。プロンプトに例を並べて挙動が変わるのは学習ではありません。前向き計算のアクティベーションが変わっているだけで、重みは 1 ビットも動いていない。会話が終われば何も残らない。「AI が対話で学ぶ」という比喩が誤解を招くのは、このためです。
pipeline() は何を隠しているか| 実行時の段 | 処理 |
|---|---|
| preprocess | トークナイズ → テンソル化 → デバイス転送 |
| _forward | no_grad 下でモデル呼び出し → 生のロジット |
| postprocess | softmax → config.id2label を引いて LABEL_0 → POSITIVE に変換 |
隠蔽しているのは四つ —— Auto クラスによる設定駆動のクラス解決/キャッシュ管理/前処理・後処理の定型/デバイス配置。この四つを手書きすれば AutoTokenizer + AutoModelForXxx と等価になります。降りるべきタイミングは §06.3 に。
細部に見える定数が、実は学習可能性そのものを決めていることがあります。
qi, ki が平均 0・分散 1・独立なら、内積 q·k = Σ qiki は平均 0・分散 dk、標準偏差 √dk になります。dk=64 なら典型スコアは ±8、dk=128 なら ±11。
softmax は入力差が数倍開くと急速に one-hot 化します。そのヤコビアンは diag(p) − ppᵀ で、p が one-hot に近づくと全成分がゼロに漸近する。Attention 重みが事実上ハード選択になった瞬間、WQ, WK へ勾配が流れなくなる。学習初期にこれが起きると、注意の割り当て方そのものを学習できないまま固まります。
限界も知っておく:これは初期化時の統計を仮定した近似にすぎません。低精度学習では大きな logit が数値問題を起こすため、近年は QK-LayerNorm(Q/K に直接 LayerNorm)や logit soft-capping が併用されます。
Attention は 置換同変(permutation equivariant) です。入力順を入れ替えると出力も同じく入れ替わるだけで、順序そのものは区別できない。語順情報がアーキテクチャから完全に消えているので、外から足し戻す必要があります。
| 世代 | 方式 | 性質 |
|---|---|---|
| 正弦波(絶対) | PE(pos,2i) = sin(pos / 100002i/d) | 周波数が次元ごとに幾何級数変化。PEpos+k が PEpos の線形変換で書けるため、相対距離を線形写像として学習できる。外挿は原理上可能だが実性能は良くない。 |
| 学習型絶対 | 位置埋め込みテーブルを学習(BERT / GPT-2) | 上限が固定(512 / 1024)、外挿不可。 |
| RoPE(現主流) | 埋め込みを 2 次元ペアに分け、位置 m に応じ mθi 回転 | Qm·Kn で回転が相殺され、結果が相対位置 m−n にのみ依存する。加算でなく Q/K の回転として作用するため、相対位置性が数学的に保証される。文脈長拡張(NTK-aware, YaRN)が base 値の調整で可能なのも、この構造ゆえ。 |
別解:ALiBi — 符号化そのものを捨て、Attention スコアに距離比例の負バイアスを直接加算する。
pipeline() から降りるべきとき| 観点 | pipeline() | カスタム構成 |
|---|---|---|
| 前処理 | 既定の truncation/padding が黙って適用される | max_length、動的パディング、slow/fast を明示制御 |
| バッチ | batch_size 引数のみ。長さの偏りに無防備 | length-grouped sampling、bucketing が可能 |
| 中間表現 | 取り出せない | output_hidden_states / output_attentions |
| 後処理 | id2label 固定、閾値調整不可 | ロジット段階での温度・閾値・アンサンブルが自由 |
| デバイス | device / device_map の粗い制御 | 量子化・torch.compile・ONNX と組合せ可 |
判断基準は一つ:入出力の契約が既定と一致するか。 降りるべきトリガは、スループット最適化が要るとき/埋め込みや Attention 重みを副産物として使うとき/共有エンコーダ上に複数ヘッドを乗せるとき/量子化・コンパイル済みモデルを差し込むとき。
pipeline() は前処理の失敗を沈黙のうちに吸収します。長文が黙って 512 で切られていて精度が出ない、が典型事故。§22 の D5 と同じ構造です。
語彙戦略の失敗は、精度ではなく計算量とAPI課金という形で請求されます。
単語単位の語彙は Zipf 則により裾が無限に伸びて飽和しません。サブワードがやっているのは、語彙サイズ V と系列長 L の積に対するトレードオフの最適化です。
ドメイン適応の定量指標は fertility(1 単語あたりの平均トークン数)。これが 2 倍になると何が起きるか:
トークナイザの差し替えは埋め込み行列の行の意味を破壊します。だから事前学習済み重みをそのまま流用できない。ここが選択肢を狭めます。
| 選択肢 | 内容 | 評価 |
|---|---|---|
| 1. ゼロから事前学習 | 効果は最大 | コストも最大 |
| 2. 語彙拡張 | ドメイン語を追加し resize_token_embeddings()。新規行はサブワード平均等で初期化 → 継続事前学習 | 現実的な折衷案。多くの実務でこれが最適 |
| 3. 既存のまま | fertility 悪化を許容する | — |
streaming=True の真の違いdatasets は RAM に全展開しません。Apache Arrow でディスク保存し mmap でメモリマップする。100GB でも RAM 使用は数百 MB。真の違いは (a) ディスク容量 と (b) 初回起動時間です。| 通常 | streaming=True | |
|---|---|---|
| 実体 | Dataset(map-style) | IterableDataset |
| ダウンロード | 全体を事前取得 | HTTP range request で逐次 |
| ディスク | 全量必要 | ほぼ不要 |
| 起動 | 数十分〜数時間 | 即座 |
len() | 可能 | 不可 |
| ランダムアクセス | ds[42] 可 | 不可(順次のみ) |
map() | 即時実行・結果保存 | 遅延実行 |
IterableDataset に素朴に num_workers > 1 を指定すると、各ワーカーが同じデータを読んで 重複バッチ が流れます。元データのシャード数(Parquet ファイル数)がワーカー数で割り切れないと不均衡にもなる。
buffer_size 分のリザーバ内でしか混ざりません。元データがラベル順に並んでいれば局所的な偏りが残る。事前のシャードレベルシャッフルが前提です。
len() がないTrainer では max_steps の明示が必要(num_train_epochs は使えない)。スケジューラの総ステップ数も自分で決めることになります。
resume は skip() による読み飛ばししかなく、大規模では非現実的。StatefulDataLoader(torchdata)を検討する。
VRAM が足りないとき、何が実際に減るのか。ここが最も直感を裏切ります。
表現力が保たれる根拠は Aghajanyan らの 固有次元(intrinsic dimensionality):事前学習済みモデルの下流適応に必要な更新は、パラメータ空間の極めて低次元な部分空間に収まる。事前学習で汎用表現が獲得済みなので、必要なのは既存特徴の再結合であって新規特徴の獲得ではない、ということです。
| 帰結 | 内容 |
|---|---|
| 効く範囲 | LoRA が効くのは 適応。新しい知識ドメインの大量注入では、r を上げても full FT に及ばない。 |
| r の実用域 | 8〜64。それ以上上げても伸びないことが多い。 |
| 効くのは r より | どのモジュールに適用するか(Q/V のみ vs 全線形層)のほう。近年は全線形層が推奨。 |
| α/r スケーリング | r を変えても実効学習率が変わらないための正規化。α = 2r が経験則。 |
| LoRA | Prefix / Prompt Tuning | |
|---|---|---|
| 介入対象 | 重み(ΔW) | アクティベーション(KV / 入力埋め込み) |
| 作用の性質 | 変換そのものを変える | 参照可能な文脈を追加する |
| 推論オーバーヘッド | ゼロ(マージ可能) | あり(実効系列長が p 増加) |
| 文脈長 | 消費しない | 有効文脈を圧迫する |
| 学習安定性 | 高い | 低い(学習率に敏感、収束が遅い) |
| スケール依存性 | 小〜大まで安定 | 10B 超で急に効きはじめる |
実務:安定性と推論効率の両面から LoRA が事実上の標準。Prefix Tuning は、単一基盤モデルに膨大なタスク数を乗せてバッチ内で混在させたい場合に利点が残ります。
| 1 パラメータあたり(Adam) | fp32 | 混合精度 |
|---|---|---|
| 重み | 4 | 2 (fp16) |
| 勾配 | 4 | 2 (fp16) |
| FP32 マスター重み | — | 4 |
| Adam m | 4 | 4 |
| Adam v | 4 | 4 |
| 計 | 16 バイト | 16 バイト |
削減の出所はアクティベーションです。 バックワード用に保持される中間表現は batch × L × d × 層数 に比例し、大規模学習ではメモリの支配項になる。これが半減する。「最大 50%」はアクティベーションが支配的な設定での話です。
s·b·h·L·(34 + 5·a·s/h) バイト(bf16、a=h/128 と仮定)、fp32 はその 2 倍。d は params ≈ 12·L·d² から逆算。checkpointing は層境界のみ保持する full recompute を仮定。桁の感覚を掴むための概算であって、実測の代わりにはなりません。実装・カーネル・Flash Attention の有無で変わります。マスター重みが必要な理由:fp16 の仮数部は 10 ビットしかなく、1.0 + 0.0001 のような微小更新が丸めで消える。だから更新は fp32 マスターコピー上で行い、fp16 にキャストして forward に使います。
| 指数部 | 仮数部 | 損失スケーリング | |
|---|---|---|---|
| fp16 | 5 bit(範囲 6×10⁻⁵ 〜 65504) | 10 bit | 必須(小勾配が subnormal でアンダーフロー) |
| bf16 | 8 bit(fp32 と同範囲) | 7 bit | 不要 |
A100 以降は bf16 が推奨です。
PyTorch の .backward() は param.grad に加算します(上書きしない)。この性質を利用して step() と zero_grad() を N ミクロバッチに 1 回だけ呼ぶ。ただし大バッチと等価ではありません。
/N ではなく総トークン数での正規化が正しい(2024 年に広く報告されたバグの温床)。no_sync() を使わないと、ミクロバッチ毎に all-reduce が走って通信量が N 倍になる。出発点は「DDP は全 GPU に全状態を完全複製している」という無駄です。混合精度 + Adam で 16 バイト/param、うち 12 バイト(マスター重み 4 + m 4 + v 4)がオプティマイザ状態。7B なら 112GB がそれだけで消える。N 台あるなら重複保持する必要はない。
| Stage | 分割対象 | メモリ/param | 通信量 | 削減率 (N=64) |
|---|---|---|---|---|
| DDP | なし | 16 | 2Ψ | 1× |
| 1 (P_os) | オプティマイザ状態 | 4 + 12/N | 2Ψ | ≈4× |
| 2 (P_os+g) | + 勾配 | 2 + 14/N | 2Ψ | ≈8× |
| 3 (P_os+g+p) | + パラメータ | 16/N | 3Ψ | N に線形 |
インターコネクト依存性が強い。 NVLink / InfiniBand なら実用的ですが、10GbE 程度のクラスタでは GPU 利用率が半分以下に落ちることも珍しくありません。Offload はさらに CPU RAM / NVMe へ退避する最後の手段。PCIe(〜32GB/s)は GPU HBM(〜2TB/s)より 2 桁遅く、速度を大きく犠牲にします。
量子化は「精度を捨てて速くする」ではありません。何を捨てて何を得るかが手法ごとに違います。
| 粒度 | 用途 |
|---|---|
| per-tensor | 高速だが精度劣化が大きい |
| per-channel(出力チャネル毎) | Transformer 線形層ではほぼ必須 |
| per-group(64〜128 要素毎) | 4 ビットでの標準 |
キャリブレーションの役割:重みの分布は静的に既知なので測定不要。問題は入力依存のアクティベーションです。代表データを流して範囲を推定する。
| 手法 | 内容 |
|---|---|
| Min-Max | 単一の外れ値でスケールが破壊される |
| Percentile | 99.99%tile でクリップ。クリッピング誤差を許容して大多数の分解能を守る |
| MSE 最小化 | ‖x − Q(x)‖² が最小になるクリップ範囲を探索 |
| KL 最小化(TensorRT) | 元分布と量子化後分布の情報損失を最小化 |
要は クリッピング誤差と丸め誤差のトレードオフ最適化。データは 128〜512 サンプル、本番分布を代表するものが必要です。ドメインがずれると劣化します。
Dettmers らの知見。6.7B を超えると、特定の隠れ次元に桁違いに大きな外れ値(他の 100 倍以上)が系統的に出現し、per-tensor 量子化を破壊します。
| 対処 | 発想 |
|---|---|
| LLM.int8() | 外れ値次元だけ fp16 で計算し、残りを int8 で処理する混合分解 |
| SmoothQuant | 数学的に等価な変形で、アクティベーションの外れ値を重み側へ移す |
| GPTQ | 層ごとに二次情報(ヘッセ行列近似)を使い、あるパラメータの量子化誤差を残りの調整で補償する(OBQ の効率化) |
| AWQ | 全重みは等価でないという観察。アクティベーションの大きさで重要度を推定し、上位 1% を保護するチャネル単位スケーリング |
事前学習済み重みが概ね正規分布に従う事実を利用した 分位点量子化。等間隔ではなく標準正規分布の分位点に基づいて 16 個の代表値を配置し、情報理論的に各ビンの期待値が等しくなるようにする。
ブロック単位(64 要素)にスケールを持ち、そのスケール定数自体も 8 ビット化する(double quantization)ことで約 0.37 bit/param を節約する。
PTQ の限界:4 ビット以下や小規模モデルでは劣化が無視できず、QAT(straight-through estimator で疑似量子化を通す)が必要になります。
ハードラベルは「犬」としか教えません。教師の出力分布「犬 0.9 / オオカミ 0.08 / 猫 0.015 / 車 0.000001」は 誤答クラス間の相対的な類似構造を含んでいる。Hinton の言う dark knowledge です。
T=1 が通常。T>1 で平坦化、T→∞ で一様、T→0 で one-hot。目的は 確率がほぼゼロのクラス間の相対的な大小関係を可視化することです。0.000001 と 0.0000001 の差は T=1 では損失にほぼ寄与しないが、これこそ教師の持つ細かい類似度情報。実用域は T = 2〜10。
① T² 係数:ソフト損失のロジット勾配は 1/T² に比例して小さくなる。T² を掛けることで、ハード損失との相対重みが T に依存しなくなる。
② KLDivLoss は log 確率を要求する:PyTorch の KLDivLoss は入力に log_softmax を通したものを渡す必要がある。典型的なバグ源です。
KL を使う理由:目標が「教師分布の再現」であり、分布間距離の自然な尺度だから。KL(P‖Q) = H(P,Q) − H(P) で H(P) は生徒パラメータに関して定数なので、勾配としては交差エントロピーと同一になります。
発展形:DistilBERT は上記に加えて隠れ状態のコサイン類似度損失を併用し、さらに生徒を教師の層から間引いて初期化する(表現空間の整合が学習を容易にする)。FitNets は中間層の特徴マップを合わせ、Attention Transfer は Attention 行列を転写します。
まず用語を整理しないと議論が噛み合いません。Early / Late Fusion は文献によって逆です。
「Late Fusion=文字列連結」「Early Fusion=クロスアテンション統合」という説明は、RAG 文献の一般的用法とは逆です。Izacard & Grave の FiD が "Fusion-in-Decoder"(=後段での融合)と命名されている通り、クロスアテンション統合は通常 late / deep fusion 側に分類されます。本稿では機構名で呼び分けます。
| 本稿の呼称 | 資料での呼称 | 実体 |
|---|---|---|
| 入力連結型 | Late Fusion | プロンプトに検索結果を結合する |
| 周辺化型 | (なし) | RAG-Sequence / RAG-Token。検索スコアで確率的に重み付け |
| デコーダ融合型 | Early Fusion | FiD。文書を個別符号化しクロスアテンションで統合 |
実務でこの語を使うときは、定義を明示するのが安全です。
メリット:実装が単純(プロンプトテンプレートのみ)/生成モデル無改変で閉じた API モデルにも使える/検索器と生成器を独立に差し替え可能/引用元の追跡が容易。
| 長文脈での課題 | 内容 |
|---|---|
| Lost in the middle | Liu ら。文脈中央の情報利用率が両端より有意に低い。文書数を増やすと中央の正解が無視される。 |
| 計算量 | O(L²)。10 文書連結で 1 文書の 100 倍。 |
| ノイズ劣化 | 無関係文書の混入で「無し」より精度が下がることがある → リランカー(cross-encoder)が事実上必須。 |
| 文書間干渉 | 矛盾する文書があってもモデルは矛盾を検出せず、片方を採用しがち。 |
| 文脈長の上限 | 会話履歴・システムプロンプト・出力予算との取り合いになる。 |
Lewis らのオリジナル RAG は、検索文書を潜在変数 z として扱い明示的に周辺化します。
検索スコアの統合機構の実体:pη(z|x) は DPR の質問/文書エンコーダ内積を top-k 上で softmax したもの。k 個の (x, zi) ペアを BART エンコーダに通し、デコーダのクロスアテンションが各文書表現を参照する。「動的に統合される」の実体は、デコーダ出力の対数確率に log pη(z|x) が加算されて周辺化されることです。
質問エンコーダには勾配が流れ、検索器が生成タスクに合わせて共同最適化される。しかし文書エンコーダは凍結されます。更新すると FAISS インデックス全体の再構築が必要になるためです。
FiD は周辺化を省き、k 文書を別々にエンコードして、その出力を連結したものにデコーダがクロスアテンションを張る。エンコーダ計算量が O(kℓ²)(ℓ=1 文書長)で済み 100 文書規模までスケールします。入力連結型の O((kℓ)²) に対する明確な優位。
数理的には語彙空間(数十万次元)における疎ベクトルの重み付き内積。転置インデックスで候補文書のみ走査するため高速です。ただし語の一致が前提なので、「腎臓」と「renal」は無関係と判定される。
密検索はバイエンコーダで ℝ⁷⁶⁸ 程度へ写像し、幾何的近さで測ります。対照学習を通じて意味的近接性が距離に埋め込まれる。同義語・言い換え・多言語をまたげる一方、訓練分布外の固有名詞・型番・略語に弱い。ABC-1234X は BM25 なら確実に当たるが、密ベクトルでは埋もれます。
L² 距離は cos の単調減少関数。つまり 正規化済みなら L2 と内積の検索順位は完全に一致します。計算が軽い方(FAISS では METRIC_INNER_PRODUCT)を選べばよい。
| 正規化していない場合 | 挙動 | リスク / 用途 |
|---|---|---|
| 内積(IP) | ノルムに比例。ノルムの大きいベクトルが常に有利 | 「人気度」「情報量」をノルムに載せる設計なら意図的に使える(推薦の MIPS)。RAG では長い文書がノルムが大きいだけで上位に来る事故。 |
| L2 | ノルム差を距離として拾う。方向が同じでもノルムが違えば遠い | — |
選択基準は埋め込みモデルの訓練目的に従う。これが唯一の正解です。
| モデル | 訓練時の目的 | 推奨 |
|---|---|---|
| Sentence-BERT, E5, BGE, OpenAI embeddings | コサイン類似度 | 正規化 → IP または L2(等価) |
| DPR | 非正規化内積 | 正規化しない IP |
| 画像特徴(一部) | ユークリッド距離 | L2 |
E5 系のように prefix(query: / passage: )の指定があるモデルは、それも守らないと性能が大幅に落ちます。
HNSW / IVF は距離計量ごとに別の空間構造を作ります。構築時と検索時で計量が食い違うと、エラーにならず静かに精度だけ劣化する。正規化の有無はパイプライン入口の一箇所に固定してください。
劣化のメカニズムは分布ドリフトです。訓練時と異なる分布のデータを追加し続けると、① リスト長が不均衡化(特定セルに集中)してそのセルに当たったクエリのレイテンシが悪化し、② 新分布の密な領域にセントロイドが無いため、同じ nprobe でのリコールが落ちる。
対処:リスト長の分散と recall@k を監視し、閾値超過でバックグラウンド再訓練・再構築 → 原子的差し替え(blue-green)。FAISS はオンライン部分再クラスタリングを提供しないため、インデックス全体の再構築が標準です。
remove_ids() は IVF では動作するがリストの詰め直しで高コスト。HNSW は削除を実質サポートしません(グラフ構造が壊れる)。運用は tombstone 方式(削除フラグを外部保持し検索後にフィルタ)+定期再構築。IndexIDMap でラップするか add_with_ids() で外部 ID を紐付ける。| データ規模 | 推奨インデックス |
|---|---|
| 〜10 万 | IndexFlatIP(総当たり、完全精度) |
| 10 万〜100 万 | IndexHNSWFlat(高速・高リコール、メモリ大) |
| 100 万〜1000 万 | IVF{n}_HNSW32,Flat |
| 1000 万〜 | IVF{n}_HNSW32,PQ64(圧縮、精度と引換え) |
n_list ≈ 4√N が経験則。
両者は目的が異なります。
| シャード (Shard) | パーティション (Partition) | |
|---|---|---|
| 分割基準 | 主キーのハッシュで自動 | ユーザーが論理キーで明示(テナント ID、日付、言語) |
| 目的 | 書き込みスループットと容量のスケールアウト | 検索範囲の枝刈り |
| 機構 | 各シャードが独立の書き込みチャネルを持ち並列取込。検索は scatter-gather(各シャード top-k を統合再ソート) | partition_names=["tenant_42"] でそのセグメントのみスキャン。Partition Key でフィールド値に基づく自動振り分けも可 |
| 効く場面 | 取込量が多い | 10 万テナントの SaaS で、1 テナント検索が全体をスキャンしない |
アーキテクチャの要点はストレージとコンピュートの分離です。実データを S3/MinIO に置き、QueryNode はセグメントをロードして応答するだけのステートレスに近い存在にする。だから水平スケールが容易で、ノード追加時は既存セグメントが再配分(load balance)されます。数十億規模ではこれに DiskANN(メモリに収まらないインデックスを SSD へ)、PQ 圧縮、レプリカによる読取スケールを組み合わせる。
GPU がメモリ帯域律速であるという事実が、サーバ設計をまるごと決めます。
| 設計点 | 内容 |
|---|---|
| Future による結果返送 | 各ハンドラは自分の Future を待つだけ。await 中にイベントループが解放され新規受付が継続する。ハンドラとワーカーを疎結合にする鍵。 |
| GPU 呼出をループから追い出す | run_model は同期の CPU/GPU バウンド処理。直接呼ぶとループ全体が停止し新規接続を受けられない。asyncio.to_thread / run_in_executor へ(PyTorch は GIL を解放するので有効)。 |
| 二つの締切条件 | MAX_BATCH 到達 or MAX_WAIT 経過。これがレイテンシとスループットの調整ダイヤル。MAX_WAIT = 最悪ケースの上乗せ遅延なので、p99 SLA から逆算する。 |
| バックプレッシャ | asyncio.Queue(maxsize=N) で上限を設け、溢れたら 503。無制限キューは過負荷時にメモリを食い潰し、「誰も待っていないリクエスト」を延々処理する。 |
| 長さのばらつき | バッチ内は最長にパディングされる。5 トークンと 500 トークンの同居は 100 倍の無駄。長さ帯ごとの別キュー(bucketing)が効く。 |
| クライアント切断 | await fut 中に切れても計算は続く。request.is_disconnected() の監視やキャンセル伝播を入れる。 |
asyncio.Queue を LLM 配信にも使う解決は continuous batching(in-flight batching)。トークン生成の各ステップでバッチ構成を組み替えます。完了したシーケンスを即座に抜き、待機中リクエストを即座に入れる。vLLM の PagedAttention は KV キャッシュを OS の仮想メモリのようにページ単位で管理し、断片化を排して同時実行数を大幅に増やします。
「思考の連鎖」の実体は、while ループと文字列の追記です。
"Observation:" を指定する(これが決定的。指定しないとモデルはツール結果まで自分で捏造して続ける)Action / Action Input を抽出Observation: として文字列に追記Final Answer が出るまで反復| 脆弱性 | 内容 |
|---|---|
| パース失敗 | LLM がフォーマットを守らない。handle_parsing_errors はエラーを Observation として返し自己修正させるが、確実ではない。 |
| 無限ループ | 同じ Action を繰り返す。max_iterations が必須。 |
| 誤り伝播 | 中間の誤った Observation を訂正できない。ステップ数に対して成功率が指数的に減衰する。 |
| コンテキスト膨張 | 履歴が線形に伸び、長いタスクで上限に達する。 |
現代的な代替:ネイティブ tool calling(構造化 JSON でツール呼出を返す API 機能)がテキストパースの脆さを根本解消し、並列ツール呼出にも対応します。新規実装で ReAct のテキストパース方式を選ぶ理由はほぼありません。ただし Thought → Action → Observation という認知ループの構造自体は不変で、tool calling はその実装層を置き換えただけです。
| 型 | 機構 | 強み | 弱み |
|---|---|---|---|
| インターリーブ型 (ReAct) | 計画を立てず各ステップで次の一手を決める | 環境応答に適応できる | 大局を見失い迂遠な経路を辿る |
| Plan-and-Execute | Planner が全ステップを列挙 → Executor が順次実行 | 計画が明示的で監査可能。実行に安価なモデルを使える | 初期情報だけで計画するため実行中の発見に対応不可 → 再計画ノードが必要 |
| 再帰的分解 | サブタスクをさらに分解し木構造で解く(Least-to-Most, Tree of Thoughts) | 探索空間の広い問題に強い | コストが跳ね上がる |
LangGraph 等の状態機械ベースが主流化した理由は、制御を暗黙のプロンプトではなく明示的なグラフとして書けるからです。分岐条件・リトライ・人間の承認ゲート・チェックポイント再開を、コードとして検証可能な形で表現できる。
| 観点 | RabbitMQ (AMQP) | Redis Pub/Sub |
|---|---|---|
| 永続性 | キュー・メッセージをディスク永続化。再起動後も残る | なし。発行の瞬間に接続中の購読者へ配るだけ。購読者不在なら消滅 |
| 配送保証 | ack を待ち、未 ack で切断なら別コンシューマへ再配送(at-least-once。冪等性は消費側の責任) | at-most-once(fire-and-forget) |
| 配送モデル | 競合コンシューマ(1 メッセージ = 1 コンシューマ、ワークキュー) | ブロードキャスト(全購読者が受信) |
| バックプレッシャ | prefetch_count で未処理数を制限。滞留がプロデューサへの信号になる | なし。遅い購読者は出力バッファ上限で切断される |
| エラー処理 | Dead Letter Exchange、TTL、リトライ上限が組込み | なし |
| ルーティング | direct / topic / fanout / headers | チャネル名のみ |
| レイテンシ | ミリ秒オーダー | サブミリ秒 |
Redis Streams がこの対比で重要です。Pub/Sub の欠点を埋める後発機能で、追記型ログ、コンシューマグループ、XACK、pending entries list による再配送、AOF/RDB 永続化を備える。RabbitMQ に近い保証を Redis のレイテンシで得る中間解です。
| 用途 | 適する技術 | 理由 |
|---|---|---|
| コーディネータ → ワーカーへのタスク委譲 | RabbitMQ / Redis Streams | 消失が許されない。再配送と DLQ が要る |
| エージェント間の共有スクラッチパッド | Redis(KV/Hash) | 低レイテンシの状態共有 |
| 進捗のリアルタイム通知・UI 更新 | Redis Pub/Sub | 消失許容。ブロードキャストが自然 |
| 分散ロック(同一リソースの排他) | Redis(SET NX PX / Redlock) | RabbitMQ にこの機能はない |
| LLM 応答のキャッシュ | Redis(TTL 付き) | — |
| 長時間タスクの結果保管 | Redis / DB | ブローカーは保管庫ではない |
「どちらが優れているか」ではありません。帰納バイアスをどこまで手放すかという連続量の問題です。
CNN には二つの帰納バイアスがアーキテクチャに焼き込まれています。局所性(近傍ピクセルのみ結合)と平行移動同変性(同じフィルタを全位置で共有)。この事前知識のおかげで、比較的少ないデータで学習が成立します。
ViT はこれをほぼ全部捨てます。パッチ分割の中に弱い局所性が残り、位置埋め込みが座標を与えるだけ。代わりに 第 1 層から受容野が画像全体になる。CNN が「局所特徴を積み上げて徐々に大域へ」なのに対し、ViT は最初から任意のパッチ対を直結できます。
DeiT が蒸留トークンを使って ImageNet だけで戦えるようにしたのは、CNN 教師から帰納バイアスを転写する迂回路と読めます(→ §09.2 の蒸留)。データで買えないなら、教師から借りる。
現実の解は融合です。Swin Transformer はウィンドウ分割+シフトで局所性を戻しつつ階層構造を持たせ、ConvNeXt は逆に CNN 側を ViT の設計思想で作り直しました。両側から歩み寄っている。
| CNN | ViT | |
|---|---|---|
| 局所性 | アーキテクチャに内蔵 | 学習で再獲得(下位層の一部ヘッド) |
| 平行移動同変性 | 重み共有で保証 | なし(位置埋め込みで座標を与えるのみ) |
| 第 1 層の受容野 | カーネルサイズ分 | 画像全体 |
| 必要データ量 | 少なくて済む | 大規模事前学習が前提 |
| 性能の天井 | 低め | 高い |
| 歩み寄り | ConvNeXt(ViT 思想で再設計) | Swin(ウィンドウ+シフトで局所性を回復) |
日本語で効く理由は「日本語に特化したから」ではありません。空白依存という前提を取り除いたからです。
BPE / WordPiece / SentencePiece と並列に並べると混乱します。正しくは SentencePiece(BPE) や SentencePiece(Unigram)。従来の BPE 実装は「空白で単語に分ける」という前処理(pre-tokenization)を暗黙の前提にしていました。これが二つの問題を生みます。
SentencePiece の解は、入力を生の Unicode ストリームとして扱い、空白を含めて記号 ▁(U+2581)に置き換えてから学習することです。空白が特別扱いでなくなり、単なる 1 文字になる。
detokenize(tokenize(x)) == x がバイト列レベルで保証される日本語に対して SentencePiece を素で回すと、「という」「ました」のような機能語の連なりが 1 トークンに固まり、形態素境界を無視した分割になりがちです。日本語モデルの多くが MeCab 等で粗く分割してから SentencePiece をかける二段構えを取るのはこのためで、可逆性と言語知識のトレードオフが残ります。前処理を完全に追い出せたわけではない。
この二段構えを採ると、§14.1 で挙げた「辞書とバージョンが再現性の依存先になる」問題が部分的に戻ってきます。何を優先するかの判断であって、正解が一つあるわけではありません。
「ファインチューニング vs 転移学習」は対立概念ではありません。前者は後者の一手法です。
実務で問題になる区分は full fine-tuning vs feature extraction(linear probing) なので、そう読み替えます。
| 線形プローブ | full fine-tuning | |
|---|---|---|
| 更新対象 | 分類ヘッドのみ | 全パラメータ |
| 必要データ | 数百〜数千 | 数千〜数万 |
| 計算 | forward のみ(特徴を一度キャッシュすれば以降ほぼ無料) | backward が全層 |
| メモリ | 小(アクティベーション保持が最小限) | 大 |
| 上限性能 | 低い | 高い |
| 破滅的忘却 | 起きない | 起きうる |
原理的なトレードオフの本質は「事前学習表現が下流タスクに対して線形分離可能か」です。ドメインが近ければ(ImageNet → 一般物体)線形プローブで十分。遠ければ(自然画像 → 医用 X 線、一般文書 → 特許明細書)特徴自体を作り直す必要があり、full FT が要る。
Kumar らが示した通り、full FT は事前学習で得た良質な特徴を歪めます(feature distortion)。ID 精度は上がるが OOD 精度は線形プローブに負けることがある。
対策として提案された LP-FT(まず線形プローブでヘッドを収束させ、その後に全体を微調整)は、ヘッドがランダムなまま backward すると大きな勾配が下層を破壊する、という機序に基づいています。実務でも効きます。
実務の順序:線形プローブでベースラインを取り、不足なら LoRA、それでも足りなければ full FT。最初から full FT に行くのは、コストとリスクの両面で非効率です。しかも LP-FT の知見からすると、full FT に行く場合でも「まずヘッドを収束させる」一手を挟むほうが安全になります。
「重みを小さく保つ」という説明は結果としては正しい。ただし L2 正則化と weight decay は Adam では別物です。
更新式 θ ← θ − η∇ における η の役割は自明ですが、実務で効くのはスケジュールのほうです。
Adam の構造にあります。Adam は勾配の二次モーメント v で更新を正規化しますが、学習開始直後は v のサンプル数が少なく推定が不安定で、実効ステップが暴れる。Transformer は特にこれに弱く、warmup なしでは学習が崩壊することが知られています。
線形 warmup(数百〜数千ステップ)→ cosine decay が現在の標準。
SGD では両者は等価です。損失に (λ/2)‖θ‖² を足すと勾配に λθ が加わり、更新は θ ← θ − η(∇L + λθ) となる。これは減衰そのものです。
Adam では等価になりません。 L2 項を損失に入れると、その寄与も √v で割られるからです。
つまり Adam + L2 では 勾配の大きいパラメータほど正則化が弱くなる。「大きく動いているパラメータこそ抑えたい」という意図と正反対です。AdamW はこれを分離し、全パラメータに一様な減衰をかけます。Transformer の学習で AdamW が事実上の標準になっているのは、この一点の修正の効果です。
バイアス項と LayerNorm のパラメータには weight decay をかけないのが標準です。LayerNorm の γ を 0 に引っ張るのは正規化の破壊であって正則化ではありません。
Hugging Face の Trainer は既定でこれらを除外していますが、自前のオプティマイザ設定では自分でパラメータ群を分ける必要があります。
通常の backward は、連鎖律の計算に各層の入力が必要なので、forward 時の全アクティベーションを保持します。層数 n に対しメモリ O(n)。
チェックポインティングは、一部の層(チェックポイント)の出力だけ保存し、残りは破棄する。backward でその区間に来たら、直前のチェックポイントから forward を再実行して必要なアクティベーションを復元します。
| 手法 | 削減対象 | 代償 |
|---|---|---|
| 混合精度 (bf16) | アクティベーション(半減) | ほぼなし |
| 勾配チェックポインティング | アクティベーション(O(n) → O(√n)) | 計算 +30% |
| 勾配蓄積 | 減らない(実効バッチを増やすだけ) | ステップ時間 N 倍 |
| LoRA | 勾配・オプティマイザ状態 | 表現力(適応用途なら軽微) |
| ZeRO 2/3 | オプティマイザ状態・勾配・パラメータ | 通信 |
この表は §08 の対話パネルで実際に動かせます(checkpointing / LoRA / QLoRA のトグル)。
この切り分けを飛ばして手当たり次第に試すと、効かない手法に時間を使うことになります。§22 の D4「制約が設計を決める」の、最も日常的な適用例です。
どちらも「魔法の高速化ボタン」として誤解されやすい。実際に何をしているかを押さえます。
原理は「動的グラフから静的グラフへの転換」です。PyTorch の eager 実行は、Python インタプリタが 1 演算ずつカーネルを起動する。エクスポート時にグラフ全体が確定すると、実行前に全体を見渡した最適化ができるようになります。
| 最適化 | 内容 |
|---|---|
| ① 演算子融合 | 最大の効き。 Conv → BatchNorm → ReLU や MatMul → Add → GELU を単一カーネルに統合する。効果の本質は計算量ではなくメモリ往復の削減で、中間結果を HBM に書き戻さずレジスタ/共有メモリに留めたまま次の演算へ渡す。GPU がメモリ帯域律速である以上、ここが支配的(→ §11.1)。Attention 全体を融合したのが FlashAttention だと考えると位置づけが見えます。 |
| ② 定数畳み込み | 推論時に不変な部分計算を事前実行。BatchNorm の畳み込み層への吸収など。 |
| ③ メモリプランニング | グラフのライフタイム解析でバッファを再利用し、確保・解放のオーバーヘッドを消す。 |
| ④ Python / GIL の除去 | C++ ランタイムで実行するため、インタプリタのディスパッチコストが消える。小さいモデル・小バッチほどこの比率が大きいので、BERT-base のようなサイズで効果が顕著に出る。 |
効果が大きいのは エンコーダ系(分類・埋め込み・NER)と CPU 推論。ORT の CPU 実行が特に強い。
LLM 生成では話が別です。動的形状・KV キャッシュ・continuous batching が絡み、エクスポート自体が難しい。ここは vLLM / TensorRT-LLM の領域(→ §11.2)。
制御フローや動的形状を含むモデルはエクスポートで壊れやすいので、必ず元モデルと出力を数値比較して検証すること。
そして PyTorch 2.x の torch.compile が同種の最適化(融合・グラフキャプチャ)を PyTorch 内で行うため、ONNX を経由する必然性は以前より下がっています。現在の主価値はむしろ PyTorch 非依存の実行環境への移植性(C++、C#、モバイル、ブラウザ)にある。
設計思想がここに出ています。Trainer が学習ループごと引き受けるのに対し、Accelerate は ループを手元に残したまま分散化します。
prepare() の対象 | 実際にやっていること |
|---|---|
| model | 適切なデバイスへ移動 → DistributedDataParallel / FSDP / DeepSpeed でラップ |
| dataloader | DistributedSampler を注入(各プロセスが異なるシャードを読む)。バッチをデバイスへ自動転送 |
| optimizer | AMP の GradScaler を統合したラッパーに置換 |
| backward | 損失スケーリング、勾配蓄積中の no_sync() を自動処理(→ §08.3 の通信量 N 倍問題) |
バックエンド抽象化が核心です。同じコードのまま、accelerate config の設定だけで 単一 GPU / DDP / FSDP / DeepSpeed / TPU / Apple MPS を切り替えられる。ZeRO Stage の変更が YAML の 1 行になる(→ §08.4 の降り順が設定変更だけで試せる)。これが「コードを修正せずに」の実体です。
find_executable_batch_size デコレータで、OOM が出たらバッチサイズを半分にして再試行する仕組みです。賢く選ぶわけではない。素朴なリトライループの自動化と理解するのが正確です。CLIP と Whisper は同じ機構ではありません。ここを混ぜると、何ができて何ができないかを読み違えます。
やっているのは、両エンコーダの出力を同じ埋め込み空間に写像し、N 枚の画像と N 個のキャプションの N×N 類似度行列を作って、対角成分(正しいペア)が最大になるよう対照学習することだけです(InfoNCE)。
N 個の負例が同時に効くため、バッチサイズが性能に直結します(原論文は 32,768)。この構造ゆえです。
画像について文章を生成できない。「画像のこの部分がテキストのこの語に対応する」という細かい対応も取れない。できるのは類似度を測ることだけで、ゼロショット分類はクラス名を「a photo of a {class}」に埋めて類似度比較しているにすぎません。
Whisper は全く違う機構です。音声を対数メルスペクトログラムにして Audio Encoder に通し、Text Decoder がクロスアテンションでそのエンコーダ出力を参照しながらトークンを自己回帰生成する。標準的な seq2seq です。
ここでは融合が起きています。ただし方向は 音声 → テキストの一方向で、対称ではありません。マルチタスクをタスクトークン(<|transcribe|> / <|translate|> / 言語タグ)で切り替えるのが設計上の特徴です。
| パターン | 機構 | 代表 | できること |
|---|---|---|---|
| 整列のみ | 独立エンコーダ + 対照学習 | CLIP, SigLIP | 検索・ゼロショット分類 |
| クロスアテンション融合 | 一方のエンコーダ出力を他方が参照 | Whisper, Flamingo, BLIP-2 | 条件付き生成 |
| トークン空間統合 | 非テキストを射影して LLM の入力トークン列に混ぜる | LLaVA, GPT-4V, Gemini | 対話的な推論 |
三番目が現在の主流です。LLaVA が典型で、CLIP の視覚エンコーダ出力を MLP プロジェクタで LLM の埋め込み次元に写像し、画像をただのトークンとしてテキストと同じ列に並べる。以降は LLM が自己注意で両者を区別なく扱います。
厄介なのは、バイアスが性能の副作用ではなく、性能そのものの一側面だという点です。
| 経路 | 内容 |
|---|---|
| ① 訓練データの分布 | コーパスは世界の中立な標本ではなく、書く手段と動機を持つ人々の産物です。Web テキストは英語圏・特定層に強く偏る。 |
| ② 目的関数の性質 | 次トークン予測は共起の統計を忠実に再現することが最適解。「看護師 → 彼女」の共起が実際に偏っていれば、それを学習するのはモデルの正しい振る舞いであり、バグではない。 |
| ③ 増幅 | モデルは統計的偏りを元データより強く再現する傾向が報告されています(Zhao らの bias amplification)。決定境界を鮮明にする方向に最適化が働くため。 |
| ④ RLHF による二次的バイアス | アノテータ集団の価値観と報酬モデルの選好が新たな偏りを作る。「無害化」自体が特定の文化的規範の反映であるという批判は妥当なものです。 |
| 段階 | 手法 | 効果の限界 |
|---|---|---|
| データ | フィルタリング、counterfactual data augmentation("he"↔"she" 入替)、再重み付け | フィルタが特定方言・集団の言語を除去し新たな排除を生む |
| 訓練 | 敵対的除去、公平性制約、INLP(部分空間の射影除去) | 表面的にしか消えない |
| 推論 | プロンプト制約、self-debiasing、出力フィルタ | 根本解決ではない |
① デバイアスは「隠している」だけかもしれない。 Gonen & Goldberg は、単語埋め込みのデバイアス(Bolukbasi らの手法)が性別情報を隠しているだけで消していないことを示しました。デバイアス後の埋め込みからも、クラスタリングだけで元の性別が高精度に復元できる。「バイアス方向」という一次元的な定式化が現象を捉え損ねている、ということです。
② 公平性の定義は同時に満たせない。 demographic parity / equalized odds / calibration は数学的に同時充足不可能であることが証明されています(Kleinberg ら)。どれを採るかは技術判断ではなく価値判断で、技術的に決着させられません。
| より妥当な手法 | 内容 |
|---|---|
| 勾配ベース | Integrated Gradients、Grad-CAM。公理を満たす帰属を与える |
| 摂動ベース | SHAP、LIME。入力を変えて出力の変化を見る(計算コスト大) |
| 反実仮想テスト | 属性語だけを入れ替えて出力差を測る。バイアス検出には最も直接的 |
| 機構解釈可能性 | SAE による特徴分解、回路解析。研究段階だが最も本質的 |
評価ベンチマーク:StereoSet、CrowS-Pairs、WinoBias、BOLD、HolisticBias。ただしこれらも英語中心で、日本語を含む多くの言語で十分な評価資源が存在しません。日本語で運用するなら、既製ベンチマークの通過は根拠として弱い、と考えるべきです。
技術的緩和には上限があり、残るのはプロセスの問題です。Mitchell らの Model Cards と Gebru らの Datasheets for Datasets が提案した方向 —— 訓練データの由来、評価した集団と結果、意図された用途と意図されない用途を文書化して開示する —— が、現時点で最も実効性のある枠組みです。EU AI Act の高リスク分類、透明性義務、技術文書要件も基本的にこの線に沿っています。
詰まったときに上から降りていくための降順リスト。
| 判断 | 境界 |
|---|---|
| FAISS か Milvus か | 単一ノードで足りる & CRUD 一貫性が不要 → FAISS |
| RabbitMQ か Redis か | 消失が許されない配送 → RabbitMQ / Redis Streams。共有状態・通知 → Redis |
pipeline() かカスタムか | 入出力の契約が既定と一致し、スループット要件が緩い → pipeline() |
| メッセージング導入 | 単一プロセスで完結するうちはインメモリキュー。水平スケール時に導入 |
| 式 | 内容 | 節 |
|---|---|---|
| softmax(QKᵀ/√dk)V | Scaled Dot-Product Attention | §03.2 |
| Var(q·k) = dk | スケーリングの根拠 | §06.1 |
| diag(p) − ppᵀ | softmax のヤコビアン(飽和で消失) | §06.1 |
| PE(pos,2i) = sin(pos/10000^(2i/d)) | 正弦波位置符号化 | §06.2 |
| h = W₀x + (α/r)BAx | LoRA | §08.1 |
| θ ← θ − η·m̂/(√v̂+ε) − ηλθ | AdamW(decoupled weight decay) | §16.2 |
| q = round(x/s) + z | アフィン量子化 | §09.1 |
| pi = exp(zi/T)/Σexp(zj/T) | 温度付き softmax | §09.2 |
| αT²·KL(pTtea‖pTstu) + (1−α)CE | 蒸留損失 | §09.2 |
| Σz pη(z|x)Πi pθ(yi|x,z,y<i) | RAG-Sequence | §10.2 |
| BM25 スコア式 | 疎検索 | §10.3 |
| ‖a−b‖² = 2 − 2cos(a,b) | 正規化時の L2 と cos の等価性 | §10.4 |
| Σr 1/(k + rankr) | Reciprocal Rank Fusion | §10.3 |
ここまでの全体を貫く原理。技術が入れ替わっても、この五つは残ります。
| 層 | 冗長性 | 除去手法 |
|---|---|---|
| 表現 | 語彙の裾 | サブワード |
| 訓練 | 全 GPU が全状態を複製 | ZeRO |
| 適応 | 全パラメータを更新 | LoRA(固有次元の低さ) |
| 表現精度 | fp32 の情報量 | 量子化 |
| モデル容量 | 教師の過剰な容量 | 蒸留 |
性能劣化の多くは、等価だと思い込んだ操作が実は等価でないことから生じます。
共通する厄介さ:どれも例外を投げず、精度やスループットだけが静かに落ちる。
| 局面 | 律速要因 | 帰結 |
|---|---|---|
| LLM 生成 | メモリ帯域 | バッチ 1 と 32 で時間が変わらない → 動的バッチングが効く |
| Attention | O(L²) | 文脈長拡張が難問。fertility 悪化のコストが 2 乗で効く |
| ZeRO Stage 3 | インターコネクト | NVLink か 10GbE かで実用性が反転する |
| Offload | PCIe(HBM の 1/100) | 最後の手段 |
| エージェント | LLM 呼出(数秒) | ブローカーのミリ秒は誤差 → 判断軸は信頼性 |
pipeline() は前処理の失敗を沈黙のうちに吸収するstreaming=True は len() と再開性を奪う抽象化を使う判断とは、「何が見えなくなるか」を把握したうえで、それを許容できるかを決めること。
この教材の一番の使い道は、通読ではなく 逆引き です。何かが遅い・精度が出ない・メモリが足りないとき、まず §22 の D2(等価でない操作)と D4(何が律速か)を見る。そこで当たりを付けてから該当節へ降りる。
そして §01 の訂正 12 件 は、そのままレビューのチェックリストになります。混合精度を入れたのに VRAM が減らない、4bit にしたのに速くならない、streaming にしたのに起動が遅い —— どれも「間違った期待」から出発した結果であって、実装のバグではありません。