この記事の対象読者
- Transformer の Self-Attention の計算量に限界を感じている方
- Mamba-1 は聞いたことがあるが、Mamba-2 との違いがわからない方
- NVIDIAのNemotron-Nano-9B-v2-Japanese(別記事で解説)の内部アーキテクチャを深く理解したい方
- PyTorch で SSM ベースのモデルを自分で組んでみたい方
この記事で得られること
- Mamba-2 の本質:State Space Duality(SSD)という「TransformerとSSMは実は同じ」という衝撃の理論的背景
- Mamba-1 との差分:何が変わって、なぜ 2〜8倍速くなったのか
-
実際に動かすコード:
mamba-ssmライブラリで Mamba-2 ブロックを使う完全サンプル - ユースケース別ガイド:単体ブロック検証 / 言語モデル構築 / カスタムシーケンスモデルの3パターン
この記事で扱わないこと
- SSM の連続時間微分方程式の数学的導出(論文 arXiv:2405.21060 を参照)
- 大規模分散学習(Tensor Parallelism / Sequence Parallelism)の詳細
- Linux 以外の環境でのインストール(mamba-ssm は Linux + CUDA 必須)
1. Mamba-2との出会い
「このモデル、Attention レイヤーが 56層中 4層しかない」
先日、NVIDIA の Nemotron-Nano-9B-v2-Japanese を触っていたときのことだ(詳細は前の記事に書いた)。アーキテクチャを確認すると、残りの 52 層はほぼ Mamba-2 レイヤーで構成されていた。
「Mamba-2 ってなんだ?」
素直に調べ始めて、論文タイトルに目が止まった。
Transformers are SSMs: Generalized Models and Efficient Algorithms Through Structured State Space Duality
— Tri Dao, Albert Gu(ICML 2024)
TransformerはSSMである、というタイトル。挑発的すぎる。でもこれが Mamba-2 の核心だった。
ここまでで、この記事の方向性が掴めたでしょうか。次は、最低限知っておくべき用語を整理します。
2. 前提知識の確認
本題に入る前に、この記事で登場する用語を確認します。
2.1 State Space Model(SSM)とは
SSM は、連続時間系の制御理論に由来するモデルです。入力 $x_t$ を内部状態 $h_t$ を介して出力 $y_t$ に変換します。
h_t = A * h_{t-1} + B * x_t # 状態更新
y_t = C * h_t # 出力
RNN に似ていますが、行列 $A$, $B$, $C$ の構造に工夫を入れることで、効率的な並列計算が可能になります。
「長い文脈をコンパクトな状態ベクトルに圧縮しながら処理する、メモリ効率型のRNN」と思ってください。
2.2 Mamba-1(Selective SSM)とは
2023年12月に Gu & Dao が発表したモデル(arXiv:2312.00752)。SSM の弱点だった「コンテンツに応じて選択的に情報を取捨選択できない」という問題を、**パラメータを入力に依存させる(Selective SSM)**ことで解決しました。
| 指標 | Mamba-1 | Transformer |
|---|---|---|
| 推論スループット | 5倍高速 | 基準 |
| シーケンス長スケーリング | 線形 O(n) | 二乗 O(n²) |
| 状態次元 (d_state) | 16 | — |
2.3 Tensor Core とは
NVIDIA GPU に搭載されている、行列積(matmul)専用の演算ユニットです。A100 の場合、BF16 matmul は 312 TFLOPS に達しますが、非 matmul の FP32 演算は 19 TFLOPS 止まりです。
つまり、「matmul に変換できるか否か」がGPU上の速度を大きく左右します。
2.4 Structured State Space Duality(SSD)とは
Mamba-2 の核心理論です。「SSMとAttentionは、構造化行列の視点から見ると同一の変換を表現している」という主張を指します。次のセクションで詳しく解説します。
これらの用語が押さえられたら、Mamba-2 が生まれた背景を見ていきましょう。
3. Mamba-2が生まれた背景
3.1 Mamba-1 の栄光と限界
Mamba-1 は 2023年末に登場し、「Transformer を超えうる最初のアーキテクチャ」として大きな注目を集めました。しかし Tri Dao と Albert Gu は、その直後からある問題に頭を悩ませていました。
Mamba-1 は理論上は速いはずなのに、学習中は Transformer より遅かった。
原因は、Selective Scan アルゴリズムが GPU の Tensor Core を使えなかったことです。Mamba-1 のスキャン処理は本質的に逐次的で、matmul に変換できなかったのです。
3.2 問題の核心:matmul への変換
Tri Dao の問いはシンプルでした。
「SSM の計算を行列積に書き直せないか?」
これは表面的には最適化の話のように見えます。しかし掘り下げていくと、そこには「TransformerとSSMが数学的に同一のクラスに属する」という驚くべき理論的な真実が隠れていました。
3.3 State Space Duality の発見
SSM の再帰計算を全シーケンスで展開すると、下三角の構造化行列(半可分行列)になります。
| モデル | 行列の形 | 計算方式 |
|---|---|---|
| SSM | 半可分行列 | スキャン(逐次) |
| Linear Attention | 同じ半可分行列 | 行列積(並列) |
| Mamba-2(SSD) | 同じ半可分行列 | どちらも使える |
同じ行列を、SSMとして再帰的にも、Attentionとして並列的にも計算できる。これが「双対性(Duality)」の意味です。
この発見により、訓練時は行列積として並列計算し、推論時は再帰として定数メモリで処理する、という両取りが理論的に正当化されました。
背景がわかったところで、具体的に何が変わったのかを見ていきましょう。
4. 基本概念と仕組み ── Mamba-1 との差分
4.1 アーキテクチャの変更点
Mamba-2 の論文は「SSD理論が主役で、アーキテクチャ変更は添え物」と著者自身が述べています。ただし添え物とはいえ、実用上は重要な変更があります。
| 項目 | Mamba-1 | Mamba-2(SSD) |
|---|---|---|
| 状態次元 (d_state) | 16 | 64〜256(大幅拡大) |
| パラメータ生成順序 | 逐次(A, B, C の後に X) | 並列(全て同時投影) |
| GPU Tensor Core 活用 | ✗ できない | ◎ できる |
| 学習速度 | 基準 | 2〜8倍高速 |
| 頭(Head)構造 | なし | マルチヘッド(Attentionに類似) |
| テンソル並列(TP) | 1レイヤーに2回 allreduce | 1回に削減 |
4.2 SSD ブロックの構造
Mamba-2 のコアである SSD レイヤーの計算フローを追ってみましょう。
# SSD レイヤーの概念的な流れ(擬似コード)
# 入力: X (B, T, D) B=バッチ, T=シーケンス長, D=次元
# Step 1: 並列投影(Mamba-1との最大の違い)
# A, B, C, X を全て同時に入力から投影する
z, x, B, C, dt = parallel_projection(X)
# Step 2: A を決定(Mamba-2では A は head 共有)
A = -exp(A_log) # スカラーで head 内を共有(Mamba-1はチャネルごと)
# Step 3: SSD アルゴリズム(chunk-wise matmul + スキャン)
# chunk内は行列積、chunk間はスキャン
y = ssd_chunk_algorithm(A, B, C, x, dt, chunk_size=256)
# Step 4: RMSNorm + Gate
y = rmsnorm(y) * silu(z)
# Step 5: 出力投影
output = out_proj(y)
4.3 なぜ d_state が 16 → 128 以上になれたのか
Mamba-1 では d_state=16 が限界でした。状態次元を増やすとスキャン処理のメモリが爆発するためです。
Mamba-2 では SSD アルゴリズムにより matmul が使えるため、d_state を 128 以上に拡大できるようになりました。状態次元が大きいほど「メモリ(長期記憶の容量)」が増えるため、表現力が向上します。
「Mamba-1 は 16 個の引き出しを持つキャビネット、Mamba-2 は 128 個以上の引き出しを持つキャビネット」と思ってください。
基本概念が理解できたところで、実際にコードを書いて動かしてみましょう。
5. 実践:実際に使ってみよう
5.1 環境構築
重要: mamba-ssm は Linux + NVIDIA GPU (CUDA 11.8+) が必須です。Windows / macOS では動作しません。
# 必須: causal-conv1d を先にインストール
pip install causal-conv1d>=1.4.0
# mamba-ssm 本体のインストール
pip install mamba-ssm
# インストール確認
python -c "from mamba_ssm import Mamba2; print('Mamba-2 OK')"
nvcc が見つからないエラーが出る場合:
mamba-ssmは CUDA のコンパイラ (nvcc) が必要です。
pytorch/pytorch:latestではなくpytorch/pytorch:*-develタグの Docker イメージを使ってください。
動作確認スクリプト
# verify_install.py
import torch
from mamba_ssm import Mamba2
batch, seq_len, d_model = 2, 128, 256
x = torch.randn(batch, seq_len, d_model).to("cuda")
model = Mamba2(
d_model=d_model,
d_state=128,
d_conv=4,
expand=2,
headdim=64,
ngroups=1,
chunk_size=256,
).to("cuda")
y = model(x)
print(f"入力形状: {x.shape}")
print(f"出力形状: {y.shape}")
assert x.shape == y.shape, "形状不一致!"
print("OK: Mamba-2 が正常動作しています")
$ python verify_install.py
入力形状: torch.Size([2, 128, 256])
出力形状: torch.Size([2, 128, 256])
OK: Mamba-2 が正常動作しています
5.2 環境別の設定ファイル
以下の3種類の設定を用途に応じて使い分けてください。
開発環境用(config_dev.yaml)
# config_dev.yaml - 開発・実験用(そのままコピーして使える)
model:
d_model: 256 # 小さめで試しやすい
d_state: 64 # 状態次元
n_layer: 6 # 浅めでデバッグしやすい
vocab_size: 50277
ssm_layer: "Mamba2"
headdim: 32
ngroups: 1
chunk_size: 64 # 短めのチャンク(メモリ少)
training:
batch_size: 4
seq_len: 512
lr: 1e-4
dtype: "float32" # 安定性重視
grad_checkpointing: false
logging:
level: DEBUG
verbose: true
本番環境用(config_prod.yaml)
# config_prod.yaml - 大規模学習用
model:
d_model: 2048
d_state: 128
n_layer: 48
vocab_size: 131072 # 大語彙
ssm_layer: "Mamba2"
headdim: 64
ngroups: 1
chunk_size: 256 # 標準チャンクサイズ
training:
batch_size: 32
seq_len: 8192 # 長いコンテキスト
lr: 3e-4
dtype: "bfloat16" # 速度重視
grad_checkpointing: true
logging:
level: INFO
verbose: false
テスト環境用(config_test.yaml)
# config_test.yaml - CI/CD・単体テスト用
model:
d_model: 64 # 最小サイズ(テスト専用)
d_state: 16
n_layer: 2
vocab_size: 1000
ssm_layer: "Mamba2"
headdim: 16
ngroups: 1
chunk_size: 16
training:
batch_size: 2
seq_len: 64
lr: 1e-3
dtype: "float32"
grad_checkpointing: false
logging:
level: DEBUG
verbose: true
5.3 基本的な使い方
"""
Mamba-2 基本使用例
実行方法: python basic_mamba2.py
"""
import torch
from mamba_ssm import Mamba2
from mamba_ssm.models.mixer_seq_simple import MambaLMHeadModel
from mamba_ssm.models.config_mamba import MambaConfig
def build_mamba2_block(d_model: int = 256, d_state: int = 128) -> Mamba2:
"""Mamba-2 ブロックを構築する"""
return Mamba2(
d_model=d_model,
d_state=d_state, # デフォルト: 128(Mamba-1の8倍)
d_conv=4,
expand=2,
headdim=64, # マルチヘッドの1ヘッドあたりの次元
ngroups=1, # グループ数(TP用途で増やす)
chunk_size=256, # SSD アルゴリズムのチャンクサイズ
).to("cuda")
def build_mamba2_lm(vocab_size: int = 50277, n_layer: int = 24) -> MambaLMHeadModel:
"""Mamba-2 ベースの言語モデルを構築する"""
config = MambaConfig(
d_model=1024,
n_layer=n_layer,
vocab_size=vocab_size,
ssm_cfg=dict(
layer="Mamba2",
d_state=128,
headdim=64,
ngroups=1,
),
)
return MambaLMHeadModel(config, device="cuda", dtype=torch.float16)
def main():
# ブロック単体テスト
print("=== Mamba-2 ブロック単体テスト ===")
block = build_mamba2_block()
x = torch.randn(2, 512, 256).to("cuda")
y = block(x)
print(f" 入力: {x.shape} → 出力: {y.shape}")
# パラメータ数確認
n_params = sum(p.numel() for p in block.parameters())
print(f" パラメータ数: {n_params:,}")
if __name__ == "__main__":
main()
5.4 実行結果
$ python basic_mamba2.py
=== Mamba-2 ブロック単体テスト ===
入力: torch.Size([2, 512, 256]) → 出力: torch.Size([2, 512, 256])
パラメータ数: 528,384
5.5 よくあるエラーと対処法
| エラー | 原因 | 対処法 |
|---|---|---|
nvcc not found |
CUDA コンパイラ未インストール | Docker の devel タグを使う |
ImportError: selective_scan_cuda ... undefined symbol |
PyTorch と CUDA のバージョン不一致 |
pip install torch --index-url https://download.pytorch.org/whl/cu124 でバージョン統一 |
ModuleNotFoundError: No module named 'causal_conv1d' |
causal-conv1d 未インストール |
pip install causal-conv1d>=1.4.0 を先に実行 |
RuntimeError: CUDA out of memory |
d_state や batch_size が大きすぎ |
d_state を下げるか chunk_size を小さくする |
AssertionError: chunk_size must be ... |
chunk_size が d_state より小さい |
chunk_size >= d_state になるよう調整 |
5.6 環境診断スクリプト
#!/usr/bin/env python3
"""
Mamba-2 環境診断スクリプト
実行方法: python check_mamba2_env.py
"""
import sys
import subprocess
def check_python():
if sys.version_info < (3, 8):
return f"Python 3.8以上が必要(現在: {sys.version})"
return None
def check_cuda():
try:
result = subprocess.run(
["nvidia-smi", "--query-gpu=name,driver_version,memory.total",
"--format=csv,noheader"],
capture_output=True, text=True, timeout=10
)
if result.returncode == 0:
return None, result.stdout.strip()
return "nvidia-smi 実行失敗", None
except FileNotFoundError:
return "NVIDIA ドライバ未インストール", None
def check_package(name: str):
try:
__import__(name)
return None
except ImportError:
return f"{name} がインストールされていない"
def check_mamba2_forward():
"""実際に forward pass が通るかチェック"""
try:
import torch
from mamba_ssm import Mamba2
if not torch.cuda.is_available():
return "CUDA が利用できない(CPU 上での mamba-ssm は非対応)"
m = Mamba2(d_model=64, d_state=16, d_conv=4, expand=2,
headdim=16, ngroups=1, chunk_size=16).to("cuda")
x = torch.randn(1, 32, 64).to("cuda")
_ = m(x)
return None
except Exception as e:
return f"forward pass 失敗: {e}"
def main():
print("=" * 55)
print(" Mamba-2 環境診断")
print("=" * 55)
all_ok = True
checks = [
("Python バージョン", check_python()),
("torch", check_package("torch")),
("mamba_ssm", check_package("mamba_ssm")),
("causal_conv1d", check_package("causal_conv1d")),
("Mamba-2 forward pass", check_mamba2_forward()),
]
cuda_issue, gpu_info = check_cuda()
if cuda_issue:
print(f" [NG] GPU: {cuda_issue}")
all_ok = False
else:
print(f" [OK] GPU: {gpu_info}")
for label, issue in checks:
if issue:
print(f" [NG] {label}: {issue}")
all_ok = False
else:
print(f" [OK] {label}")
print("=" * 55)
print(" すべて OK!" if all_ok else " 上記の問題を解決してください")
print("=" * 55)
if __name__ == "__main__":
main()
5.7 Docker 環境(推奨)
Linux 環境が手元にない場合や、依存関係を汚したくない場合は Docker が最も確実です。
# Dockerfile
FROM pytorch/pytorch:2.3.0-cuda12.1-cudnn8-devel
WORKDIR /app
RUN pip install causal-conv1d>=1.4.0 mamba-ssm
COPY . .
CMD ["python", "basic_mamba2.py"]
# docker-compose.yml
version: "3.8"
services:
mamba2:
build: .
runtime: nvidia
environment:
- NVIDIA_VISIBLE_DEVICES=all
volumes:
- .:/app
実装方法がわかったので、次は具体的なユースケースを見ていきます。
6. ユースケース別ガイド
6.1 ユースケース1:Mamba-2ブロックの動作確認・研究用
想定読者: SSM の研究者・アーキテクチャを比較したいエンジニア
推奨構成: Mamba-2 ブロック単体 + ベンチマーク計測
サンプルコード:
"""
Mamba-1 と Mamba-2 の速度比較スクリプト
実行方法: python benchmark_mamba1vs2.py
"""
import time
import torch
from mamba_ssm import Mamba, Mamba2
def benchmark(model, x: torch.Tensor, n_runs: int = 50) -> float:
"""平均推論時間(ms)を計測する"""
# ウォームアップ
for _ in range(5):
_ = model(x)
torch.cuda.synchronize()
start = time.perf_counter()
for _ in range(n_runs):
_ = model(x)
torch.cuda.synchronize()
elapsed_ms = (time.perf_counter() - start) / n_runs * 1000
return elapsed_ms
def main():
d_model = 512
batch, seq_len = 4, 2048
x = torch.randn(batch, seq_len, d_model).to("cuda").to(torch.float16)
mamba1 = Mamba(d_model=d_model, d_state=16, d_conv=4, expand=2).to("cuda").half()
mamba2 = Mamba2(
d_model=d_model, d_state=128, d_conv=4, expand=2,
headdim=64, ngroups=1, chunk_size=256
).to("cuda").half()
t1 = benchmark(mamba1, x)
t2 = benchmark(mamba2, x)
print(f"{'モデル':<12} {'時間(ms)':<12} {'高速化倍率'}")
print(f"{'Mamba-1':<12} {t1:<12.2f} 1.00x")
print(f"{'Mamba-2':<12} {t2:<12.2f} {t1/t2:.2f}x")
if __name__ == "__main__":
main()
6.2 ユースケース2:カスタム言語モデルの構築
想定読者: 独自の語彙・ドメインに特化したLLMをゼロから訓練したいエンジニア
推奨構成: MambaLMHeadModel + MambaConfig で設定ドリブンに構築
サンプルコード:
"""
Mamba-2 ベースの言語モデル構築と推論
実行方法: python mamba2_lm.py
"""
import torch
from mamba_ssm.models.mixer_seq_simple import MambaLMHeadModel
from mamba_ssm.models.config_mamba import MambaConfig
from transformers import AutoTokenizer
def build_model(vocab_size: int, n_layer: int, d_model: int) -> MambaLMHeadModel:
"""Mamba-2 言語モデルを構築する"""
config = MambaConfig(
d_model=d_model,
n_layer=n_layer,
vocab_size=vocab_size,
ssm_cfg=dict(
layer="Mamba2",
d_state=128,
headdim=64,
ngroups=1,
),
rms_norm=True,
residual_in_fp32=True,
fused_add_norm=True,
)
return MambaLMHeadModel(config, device="cuda", dtype=torch.bfloat16)
def count_params(model: torch.nn.Module) -> str:
n = sum(p.numel() for p in model.parameters())
if n >= 1e9:
return f"{n/1e9:.1f}B"
return f"{n/1e6:.0f}M"
def main():
# GPT-NeoX のトークナイザを流用(Mamba 公式モデルと互換)
tokenizer = AutoTokenizer.from_pretrained("EleutherAI/gpt-neox-20b")
model = build_model(vocab_size=tokenizer.vocab_size, n_layer=24, d_model=1024)
print(f"パラメータ数: {count_params(model)}")
# テキスト生成
prompt = "State space models are"
input_ids = tokenizer(prompt, return_tensors="pt").input_ids.to("cuda")
with torch.no_grad():
output_ids = model.generate(
input_ids=input_ids,
max_length=50,
temperature=0.7,
top_p=0.9,
eos_token_id=tokenizer.eos_token_id,
)
generated = tokenizer.decode(output_ids[0], skip_special_tokens=True)
print(f"生成テキスト: {generated}")
if __name__ == "__main__":
main()
6.3 ユースケース3:時系列・シーケンスデータへの応用
想定読者: テキスト以外の連続データ(センサー、音声、ゲノム)を扱うエンジニア
推奨構成: Mamba-2 ブロックをカスタム PyTorch モデルに組み込む
サンプルコード:
"""
Mamba-2 ブロックを組み込んだカスタム時系列分類モデル
実行方法: python mamba2_timeseries.py
"""
import torch
import torch.nn as nn
from mamba_ssm import Mamba2
class Mamba2TimeSeriesClassifier(nn.Module):
"""
Mamba-2 ブロックを使った時系列分類モデル。
入力: (B, T, input_dim) → 出力: (B, n_class)
"""
def __init__(
self,
input_dim: int,
d_model: int,
n_layers: int,
n_class: int,
d_state: int = 64,
):
super().__init__()
self.input_proj = nn.Linear(input_dim, d_model)
self.layers = nn.ModuleList([
Mamba2(
d_model=d_model,
d_state=d_state,
d_conv=4,
expand=2,
headdim=min(64, d_model // 4),
ngroups=1,
chunk_size=64,
)
for _ in range(n_layers)
])
self.norm = nn.LayerNorm(d_model)
self.classifier = nn.Linear(d_model, n_class)
def forward(self, x: torch.Tensor) -> torch.Tensor:
# x: (B, T, input_dim) → (B, T, d_model)
h = self.input_proj(x)
for layer in self.layers:
h = layer(h) + h # 残差接続
h = self.norm(h)
# 最終タイムステップで分類
return self.classifier(h[:, -1, :])
def main():
model = Mamba2TimeSeriesClassifier(
input_dim=16, # センサー数など
d_model=128,
n_layers=4,
n_class=10,
).to("cuda")
# ダミーデータ: バッチ8、シーケンス長1024、特徴量16次元
x = torch.randn(8, 1024, 16).to("cuda")
logits = model(x)
print(f"入力: {x.shape} → 出力: {logits.shape}") # (8, 10)
if __name__ == "__main__":
main()
ユースケースを把握できたところで、この先の学習パスを確認しましょう。
7. 学習ロードマップ
この記事を読んだ後、次のステップとして以下をおすすめします。
初級者向け(まずはここから)
-
公式 HuggingFace モデルで遊ぶ:
state-spaces/mamba2-130m(130M パラメータ)をダウンロードしてgenerateを実行してみる -
state-spaces/mamba GitHub の README と
examples/を一通り読む - 本記事のベンチマークスクリプトで、Mamba-1 と Mamba-2 の速度差を自分の環境で測定してみる
中級者向け(実践に進む)
- 自分のデータセットで
MambaLMHeadModelをファインチューニングしてみる(HuggingFaceTrainerとも組み合わせ可能) -
ハイブリッドアーキテクチャ(Mamba-2 + Attention)を試す:
mamba2attn-2.7bが公式で提供されている - SSD 論文 (arXiv:2405.21060) の Section 3〜4 を読んで、SSD アルゴリズムを数式レベルで理解する
上級者向け(さらに深く)
-
Tensor Parallelism の実装:
ngroupsパラメータと TP 度を合わせる設定を理解する - SSD ブログシリーズ(Goomba Lab) を Part I〜IV まで読む
- Nemotron-H のようなMamba-2 + Transformer ハイブリッドを設計する(Mamba-2 層の比率・配置を変えながら実験)
8. まとめ
この記事では、Mamba-2 について以下を解説しました。
- Structured State Space Duality(SSD)の理論:TransformerとSSMは数学的に同じ構造化行列を表現しており、「双対性」がある
- Mamba-1 からの変更点:並列パラメータ投影 / マルチヘッド構造 / d_state の大幅拡大(16→128以上)により、学習が 2〜8倍高速化
- 実用的なコード:ブロック単体 / 言語モデル / 時系列分類の3パターンをカバー
私の所感
Mamba-2 が面白いのは、「速くするために数学を掘った結果、TransformerとSSMが同じものだとわかってしまった」という展開だ。最適化の問題を解いていたら、理論的な大発見に繋がるというのは科学の醍醐味だと思う。
Nemotron-Nano-9B-v2-Japanese が 56層中 52層を Mamba-2 で構成できたのも、この理論的な裏付けがあるからだ。長いコンテキスト(約100万トークン)を線形コストで処理できる点は、今後のモデル設計に確実に影響を与える。
「Transformer は必ずしも唯一の答えではない」という時代が、静かに始まっていると感じている。
参考文献
- Mamba-2 論文 (arXiv:2405.21060) — Dao & Gu, ICML 2024
- Mamba-1 論文 (arXiv:2312.00752) — Gu & Dao, 2023
- state-spaces/mamba - GitHub — 公式実装
- SSD ブログシリーズ Part I (Goomba Lab)
- SSD ブログシリーズ Part III (Princeton)
- mamba-ssm - PyPI
- [Nemotron-Nano