# モデル比較ベンチマーク (メモ)

narashi の表記ゆれ統合で使う埋め込みモデルを、同じ「物差し」で横並び比較した記録です。
モデルを差し替えるたびにこの手順 (`.claude/skills/model-eval`) を再実行し、本表を更新してください。

**測定データセットは v2(153 語 / 67 グループ / 11628 ペア)**。下の「ベンチマークの飽和対策」の通り、
最上位モデルが容易に満点へ達して分離できなくなった v1(74 語 / 2701 ペア)を難化したもの。
本ページの数値はすべて v2 での実測値です。

## 物差し

- **評価データ**: `tests/data/glossary.txt`(日本語の表記ゆれ + 日英中のクロス言語同義 + 難正例 + 難負例)
  - 同一グループ内ペア = 統合すべき(正例)、異グループ間ペア = 統合すべきでない(負例)
- **実行**: `cargo run --example benchmark -- <model> [threshold]`(指標ロジックは `src/eval.rs`)。
  ORT 非依存の Candle 勢は `cargo run --release --no-default-features --features candle --example candle_eval -- <model>`。
- **既定閾値**: `DEFAULT_THRESHOLD` は既定モデルに合わせバックエンド別。ONNX 既定 bge-m3 は `70`、Candle
  単独ビルド既定 qwen3-4b は `83`(CLI のデフォルト値・開始点)。スコア校正は全モデル共通の
  `SCORE_BASELINE = 0.7`。**適切な運用閾値はモデルごとに異なる**ので、モデルを替えたら
  `fine_sweep`(品質ピーク)と `robustness`(暴走オンセット)で閾値を選び直す。
- **モデル間比較は最適閾値で行う**: 各モデルの余弦分布が違うため固定 70.0 の横並びは最適動作点を反映しない。本記録では best-thr / clusterF1 真ピーク(=各モデルの最適閾値での値)で比較する
- 指標の意味:
  - **best-F1 / best-thr**: 分類 F1 を最大化する閾値とその値(各モデルを最適閾値で測った素ペア性能の上限)
  - **margin**: `正例min − 負例max`。0 に近いほど正例・負例の分離が良い(完全分離なら正)
  - **clusterF1(真ピーク)**: `normalize`(union-find の推移閉包込み)の実出力と正解グループのペア F1 = **実運用の挙動**。各モデルの最適閾値(1 刻みスイープのピーク)で比較する
  - **誤統合(false merges)**: `normalize` の推移閉包込みの実出力で、**異グループの語を同一クラスタにしてしまったペア数**(= データ破壊)。表記ゆれ統合では誤統合は取りこぼしより痛いため、clusterF1 が同程度なら誤統合が少ないモデルを選ぶ。**各モデルの真ピーク閾値で測る**
  - **最難負例 / 最難正例(閾値非依存・飽和対策の主軸)**: 誤統合しやすい順の負例ペア(= 適合率の境界。上位モデルほどスコアが**低い**)と、取りこぼしやすい順の正例ペア(= 再現率の境界。上位モデルほどスコアが**高い**)を上位 10 件表示する。**clusterF1 が上位で頭打ちになっても、ここのスコアは分離が続く**ため、最上位モデル同士の比較に使う
  - **per_text**: 1 用語あたり埋め込み時間(語あたりでデータ内容に依存しないため、単一セッションで測った値を流用)

## ベンチマークの飽和対策(データセット v2)

v1(74 語 / 26 グループ / 2701 ペア)は、最上位モデルが容易に上限へ達してモデル間の優劣を分離
できなくなった(= 飽和)。代表例として **Qwen3-Embedding-4B が v1 で clusterF1 0.964・P=1.000・誤統合 0 件**に
達しており、これ以上高性能なモデルが来ても差が出ない。そこで用語集を **v2: 153 語 / 67 グループ /
11628 ペア**へ拡張し、最上位モデルでも誤りうる「難所」を増やした。

### 何を難しくしたか

- **難正例(再現率の難所)**: 表層がほとんど重ならない多言語同義語を 10 グループ追加。略語・外来語・
  漢語・英語・中国語が入り混じり、文字の重なりに頼れない。例: `便所 / トイレ / お手洗い / restroom / 厕所`、
  `医者 / 医師 / ドクター / doctor / 医生`、`じゃがいも / ポテト / 馬鈴薯 / potato / 土豆`。
- **難負例(適合率の難所)**: 埋め込み空間で近接するが統合してはいけない語を単独グループで追加。3 種:
  - **共下位語**(同カテゴリの兄弟語): 季節 `春/夏/秋/冬`・色 `赤/青/黄色`・曜日・方角・兄弟・飲料
  - **紛らわしい異義語**(字面が近い別語): `科学/化学`・`保証/保障`・`関心/感心`・`公園/公演`
  - **対義語**(同じ話題で極性だけ反転し空間上で近い): `増加/減少`・`拡大/縮小`

### 飽和が解消された実証(v1→v2)

最上位 **Qwen3-4B は v1 で「完璧」(P=1.000・誤統合 0)だったが、v2 では実際に誤る**ようになった。
clusterF1 は依然トップだが頭打ちが解け、難負例 `保証⇔保障`(89.1)`厕所⇔台所`(80.9)を誤統合し、
難正例 `人参⇔carrot`(37.7)を取りこぼす。難所の連続スコア(最難負例/最難正例)で更に上のモデルとの
分離が測れる状態になった。他モデルも軒並み誤統合が増え、上位帯が広がった:

| モデル | v1 真ピーク | **v2 真ピーク** | v1 誤統合 | **v2 誤統合(真ピーク)** | v2 最難負例top |
|---|---:|---:|---:|---:|---|
| Qwen3-4B | 0.964 | **0.956** | **0** | **7** | 保証⇔保障 89.1 |
| Qwen3-0.6B | 0.748 | **0.764** | 1 | **10** | 減少⇔縮小 81.2 |
| bge-m3 | 0.725 | **0.699** | 1 | **7** | 月曜日⇔水曜日 89.0 |
| granite-278m | 0.705 | **0.682** | 24 | **28** | 兄⇔弟 91.5 |
| gte | 0.682 | **0.657** | 17 | **27** | 春⇔秋 83.1 |
| distiluse | 0.667 | **0.662** | 3 | **12** | 火曜日⇔水曜日 98.4 |

`兄⇔弟`・`月曜日⇔水曜日`・`保証⇔保障`・`減少⇔縮小` は多くのモデルが高スコアで誤統合する代表的な
難負例で、最上位モデル同士でもここのスコア差が優劣を分ける。

## 堅牢性: 連鎖暴走(over-merge)対策

### 背景 — 実データで起きた崩壊

`normalize` は閾値以上のペアを union-find で**推移閉包(単連結クラスタリング)**する。実データ
(qwen3-embedding-4b・閾値 70・ユニークタグ 9166 件)では、**7993 件(約 87%)が 195 グループに統合**され、
うち **7663 件が代表「1」という単一の巨大ゴミクラスタに崩壊**した(`["2B","3D","うさぎ","アイドル",
"アニメ",…]` が無差別に同居)。原因は、`1`/`2B`/`3D` のような**汎用短トークン(ハブ語)**が埋め込み空間の
中心付近に潰れて何にでも中程度に近くなり、無関係なクラスタ間の「橋」になって連鎖を起こす**連鎖暴走**。

クリーンな小規模用語集(153 語)はこれを再現できない(連鎖は規模 × ハブ密度の創発現象)。そこで
**ディストラクタ集 `tests/data/distractors.txt`(数字・単一文字などのハブ語 + 多ドメインの無関係タグ、
計 314 語・全て単独語)**を用語集に連結し(計 467 語)、`examples/robustness.rs` で 1 刻みスイープして
**最大予測クラスタの規模(`largest_cluster_ratio`)とそこに巻き込まれた無関係グループ数
(`groups_in_largest`)**を測る。指標は `src/eval.rs` の `SweepRow` / `Clustering` に追加済み。

```sh
cargo run --example robustness -- <model>   # 既定 bge-m3。Candle 勢は --features candle で
```

### スコア校正

スコア校正は全モデル共通の単一定数 `SCORE_BASELINE = 0.7`(`src/lib.rs`)による一次変換
(`score = (cos - 0.7) / (1 - 0.7) * 100`、cos 0.85→50 / cos 0.91→70 / cos 0.95→83)。**閾値 70 は全モデルで
余弦 0.91**に対応し、モデル間の余弦分布差は**閾値そのものをモデルごとに選ぶ**ことで吸収する(モデルを
替えたら閾値も `fine_sweep`/`robustness` で選び直す)。値は全モデル実測の暴走オンセットから、主要モデルの
安全運用点が 70 前後に来るよう選定した(下表参照)。

> 注: clusterF1 真ピーク・誤統合・最難ペアの**値**は校正(単調変換)に対し不変だが、**閾値依存の数値
> (下の主表の「最適閾値」)は計測時の校正に依存する**。下の暴走オンセット表は `SCORE_BASELINE=0.7` の値だが、
> 主表の「最適閾値」は以前の校正で測った値なので、現行の運用閾値は `fine_sweep`/`robustness` で測り直して決める
> (閾値の換算は単調なので `T₀.₇ = T₀.₅ × 5/3 − 200/3`)。

### 暴走オンセット(`SCORE_BASELINE=0.7`・467 語ストレスセット実測)

「暴走」= 最大クラスタ率 ≥ 10% または 巻込グループ数 ≥ 5。**オンセット = 暴走と判定された最高閾値**
(これより上で安全)。**比較軸はこのオンセットと、各モデル自身の安全運用点(オンセット直上)での再現率**で
あって、固定閾値での横並びではない——単一定数 `SCORE_BASELINE=0.7` 校正下では閾値 70 は全モデルで余弦 0.91
に対応するが、同じ余弦が意味する近さはモデルの余弦分布ごとに違うため、**特定閾値での数値をモデル間で比べても
意味がない**(その分布差をオンセットが per-model に吸収している)。計測環境: ONNX 勢は CPU、**Candle 勢
(qwen3 系・e5-instruct)は CUDA(NVIDIA RTX 3090・24GB)**。全 17 モデルとも `b=0.7` で実測。下表はオンセット昇順:

**ONNX 勢:**

| モデル | 暴走オンセット | 安全側の運用例(オンセット直上) |
|---|---:|---|
| **bge-m3(既定)** | **52** | @53–56 で巻込1・R≈0.20–0.25 |
| arctic-l | **54** | @55 以上で巻込4・R≈0.06–0.09(再現率が極端に低くそもそも統合しない) |
| **granite-278m** | **55** | **@57–63 で巻込2・R≈0.55–0.58(ONNX/小型で最良)** |
| granite-107m | **65** | @66–70 で巻込2–4・R≈0.47–0.50 |
| e5-small | **69** | @70–72 で巻込2–3・R≈0.34–0.42 |
| gte | **72** | @74–76 で巻込1・R≈0.06–0.07 |
| granite-97m-r2 | **74** | @78 で巻込1・R=0.191 |
| distiluse | **78** | @82–83 で巻込1・R≈0.22–0.24 |
| e5-base | **80** | @81–82 で巻込1・R=0.134 |
| e5-large | **81** | @82–83 でも巻込4・R≈0.19–0.22 |
| granite-311m-r2 | **91** | @92 でようやく巻込1・R=0.129 |
| paraphrase | **92** | @93–96 で巻込1・R≈0.16–0.26 |
| mpnet | **92** | @93–98 で巻込1–4・R≈0.04–0.20 |

**Candle 勢(CUDA / RTX 3090 実測):**

| モデル | 暴走オンセット | 安全側の運用例(オンセット直上) |
|---|---:|---|
| **qwen3-8b** | **76** | **@77–81 で巻込1・R≈0.89–0.91・clusterF1 0.873@81(全モデル中で最良)** |
| qwen3-4b | **82** | @83–86 で巻込2・R≈0.57–0.75 |
| e5-instruct | **84** | @85 で巻込4・R=0.108(高オンセット×低再現) |
| qwen3-0.6b | **94** | @95 以上で安全だが R≈0.02(実質安全域なし) |

> 計測済み: ONNX 13 モデル + Candle 4 モデル(全て 0〜100 を 1 刻みでスイープ)。**未計測は paraphrase-q
>(現環境の ORT で実行不可)と別系統の下限確認用(bge-zh / all-minilm / clip)のみ**。新しいモデルは同じ
> `robustness` example で **各自の暴走オンセットを測ってから閾値を決める**こと。
>
> 注: スイープ範囲は 0〜100。上限近くにオンセットを持つモデル(qwen3-0.6b はオンセット 94 で安全点 @95 以上だが
> R≈0.02、paraphrase / mpnet は @93 以降にわずかな安全域・R≈0.04–0.26)は、範囲を狭めると上限で切れて真の
> オンセットを見誤る。**オンセットがスイープ上限に張り付くモデルは範囲を広げて測り直すこと**。

### 結論

- **qwen3-4b の本番崩壊を再現できた**: 余弦 0.85 付近(現校正で閾値 50)で最大クラスタ率 **97.4%・
  371 グループを巻込**=単一巨大ゴミクラスタへ崩壊。実データ(9166 件で 87% が統合・7663 件が単一クラスタ)と
  同型の崩壊を 467 語ストレスセットで再現。オンセットは 82 で、安全側は @83–86(巻込2・R≈0.57–0.75)。
- **qwen3 系は last-token プーリングで余弦が高帯域に偏る**ため一様に高いオンセットを持ち、**サイズが大きいほど
  オンセットが下がり安全点の再現率が上がる**(0.6b: オンセット 94 で安全点 @95 以上だが R≈0.02 と実質無し →
  4b: @83 で R≈0.75 → 8b: @77 で R≈0.91)。**堅牢性 × 再現率の絶対最良は qwen3-8b**(オンセット 76・@77–81 で巻込1・R≈0.89–0.91・clusterF1 0.873@81)。
  granite-278m(R≈0.55–0.58)を大きく上回る。弱点は速度/サイズ(Candle・f16・要 GPU・約 16GB の VRAM/RAM)。
- **ONNX/小型で堅牢性 × 再現率が最良なのは granite-278m**(オンセット 55・@57–63 で巻込 2・R≈0.55–0.58)。
  granite-107m が @66–70 で R≈0.47–0.50 と続く。bge-m3 は @53–56 で安全だが R≈0.2 と低め、distiluse は @82 まで
  上げないと安全にならない。
- **E5 系・granite-97m/311m-r2・paraphrase・mpnet はオンセットが高い(74–92)**ため、安全に使うには高い運用閾値が
  必要で、そこでは再現率がほぼ残らない(余弦が自然に高く分布が潰れているのが原因。paraphrase / mpnet は @93 以降に
  わずかな安全域があるが R≈0.04–0.26)。arctic-l はオンセットこそ低い(54)が再現率が極端に低く(安全点で
  R≈0.06–0.09)、そもそも統合が起きないだけ。**どのモデルが堅牢かは余弦分布で
  決まり、適切な運用閾値はモデルごとに異なる**ので、必ず `robustness` で測ってから選ぶ。
- **運用閾値は clusterF1 のピークではなく、`robustness` の暴走オンセットより安全側で選ぶ**(example が ⚠ で
  ピークが暴走域内のとき警告する)。**モデルを替えたら閾値も選び直す**。

> 注意: 表記ゆれ統合では誤統合(データ破壊)が取りこぼしより痛い。安全側へ寄せると本物の表記ゆれの
> 再現率(R)は下がるが、巨大ゴミクラスタによる全体崩壊を避けることを優先する。

## 結果 — 1 刻みスイープでの真ピーク(モデル間比較の主表)

各モデルを `fine_sweep`(1 刻み 0〜100)で測り直した真ピーク clusterF1 と、その最適閾値・ピーク時 P/R・
**真ピーク時の誤統合**・**最難ペア(閾値非依存)**。誤統合と最難ペアが採用判断の主軸。

| モデル | 次元 | BE | 真ピーク | 最適閾値 | ピーク時 P / R | 誤統合(真ピーク) | 最難負例top | 最難正例top |
|---|---:|--|---:|---:|---:|---:|---|---|
| **Qwen3-Embedding-8B【Candle・精度上限】** | 4096 | C | **0.974** | 79 | 0.984 / 0.964 | **3** | 保証⇔保障 92.8 | 人参⇔carrot 60.0 |
| **Qwen3-Embedding-4B【Candle・精度上限】** | 2560 | C | **0.956** | 70 | 0.963 / 0.948 | 7 | 保証⇔保障 89.1 | 人参⇔carrot 37.7 |
| **Qwen3-Embedding-0.6B【Candle・精度枠】** | 1024 | C | **0.764** | 71 | 0.926 / 0.649 | **10** | 減少⇔縮小 81.2 | 人参⇔carrot 33.5 |
| **bge-m3(既定)** | 1024 | O | **0.699** | 70 | 0.939 / 0.557 | **7** | 月曜日⇔水曜日 89.0 | ひこうき⇔飞机 23.3 |
| granite-278m-multilingual | 768 | O | 0.682 | 76 | 0.804 / 0.593 | 28 | 兄⇔弟 91.5 | トウモロコシ⇔玉米 35.5 |
| **distiluse-multilingual-v2** | 768 | O | 0.662 | 70 | 0.895 / 0.526 | 12 | 火曜日⇔水曜日 98.4 | 猫⇔ねこ 0.0 |
| gte-multilingual-base | 768 | O | 0.657 | 70 | 0.800 / 0.557 | 27 | 春⇔秋 83.1 | ひこうき⇔airplane 11.3 |
| granite-311m-multilingual-r2 | 768 | O | 0.652 | 87 | 0.809 / 0.546 | 25 | 兄⇔弟 93.8 | 航空機⇔ひこうき 67.2 |
| granite-107m-multilingual | 768 | O | 0.652 | 80 | 0.799 / 0.552 | 27 | 月曜日⇔火曜日 94.0 | トウモロコシ⇔玉米 39.7 |
| multilingual-e5-large-instruct【見送り・Candle】 | 1024 | C | 0.645 | 70 | 0.631 / 0.660 | **75** | 兄⇔弟 91.7 | ひこうき⇔airplane 17.8 |
| e5-large | 1024 | O | 0.638 | 69 | 0.728 / 0.567 | 41 | 兄⇔弟 88.5 | ひこうき⇔airplane 25.1 |
| paraphrase-MiniLM-L12 | 384 | O | 0.591 | 89 | 0.590 / 0.593 | 80 | みず⇔やま 96.6 | めがね⇔glasses 0.0 |
| paraphrase-mpnet-base | 768 | O | 0.567 | 86 | 0.578 / 0.557 | 79 | いぬ⇔みず 97.0 | にんじん⇔carrot 0.0 |
| e5-small | 384 | O | 0.561 | 70 | 0.853 / 0.418 | 14 | 兄⇔弟 79.3 | りんご⇔苹果 22.8 |
| granite-97m-multilingual-r2 | 384 | O | 0.537 | 79 | 0.706 / 0.433 | 35 | 月曜日⇔水曜日 92.5 | 林檎⇔苹果 50.7 |
| e5-base | 768 | O | 0.514 | 68 | 0.684 / 0.412 | 37 | 兄⇔弟 88.2 | ニンジン⇔carrot 15.9 |
| snowflake-arctic-embed-l-v2.0【見送り】 | 1024 | O | 0.495 | 52 | 0.645 / 0.402 | 43 | 兄⇔弟 76.4 | ネコ⇔cat 0.0 |

> BE: O=ONNX(ORT Runtime)、C=Candle(ピュア Rust・CPU)。Candle 勢の per_text は別系統で直接比較不可。
> **未再計測(コード非搭載で v1 のまま)**: LaBSE(v1 0.662)・snowflake-arctic-embed-m-v2.0(v1 0.512)。
> **paraphrase-q** は現環境の ORT で実行不可。**qwen3-8b** は RTX 3090(24GB VRAM・CUDA)で計測:真ピーク
> **0.974@79(P=0.984・R=0.964・誤統合 3)で全モデル中最高**(GPU 実行で per_text≈26ms と f16 でも高速)。

### 素性能(best-F1 / best-thr / margin / per_text)

各モデルを最適閾値で測った素ペア分類性能(best-F1)・分離度(margin)・コスト(per_text)。
per_text は語あたりで内容非依存のため単一セッション値(参考・相対比較用)。

| モデル | 次元 | best-F1 | best-thr | margin | per_text |
|---|---:|---:|---:|---:|---:|
| Qwen3-Embedding-4B【Candle】 | 2560 | **0.950** | 67.0 | −51.4 | ≈3886ms† |
| Qwen3-Embedding-0.6B【Candle】 | 1024 | 0.715 | 68.0 | −47.8 | ≈200ms† |
| gte-multilingual-base | 768 | 0.693 | 60.0 | −71.9 | 5.37ms |
| **bge-m3(既定)** | 1024 | 0.675 | 67.5 | −65.7 | 16.12ms |
| granite-278m-multilingual | 768 | 0.665 | 75.0 | −56.0 | 3.86ms |
| multilingual-e5-large-instruct【Candle】 | 1024 | 0.665 | 64.5 | −73.9 | ≈250ms† |
| **distiluse-multilingual-v2** | 768 | 0.660 | 69.5 | −98.4 | 2.45ms |
| granite-311m-multilingual-r2 | 768 | 0.643 | 84.5 | **−26.6** | 3.36ms |
| paraphrase-MiniLM-L12 | 384 | 0.639 | 89.0 | −96.6 | 1.28ms |
| granite-107m-multilingual | 768 | 0.639 | 80.5 | −54.3 | **0.73ms** |
| e5-large | 1024 | 0.626 | 69.5 | −63.4 | 13.60ms |
| paraphrase-mpnet-base | 768 | 0.562 | 87.0 | −97.0 | 3.30ms |
| e5-small | 384 | 0.538 | 64.5 | −56.4 | 1.70ms |
| e5-base | 768 | 0.521 | 64.5 | −72.2 | 5.47ms |
| granite-97m-multilingual-r2 | 384 | 0.513 | 78.0 | −41.9 | 1.49ms |
| snowflake-arctic-embed-l-v2.0【見送り】 | 1024 | 0.483 | 42.0 | −76.4 | 17.44ms |

† Candle 勢(qwen3 / e5-instruct)は ORT 勢と別系統のため per_text 直接比較不可(参考値)。

## 採用判断・所見

- **精度の絶対最高は Qwen3-Embedding-8B(Candle・精度上限枠)**。RTX 3090(24GB VRAM・CUDA)で計測でき、
  真ピーク **0.974**(P=0.984・R=0.964・**誤統合わずか 3**)と全モデル中で最高、堅牢性ベンチでも @77–82 で
  巻込1・R≈0.87–0.91 と暴走耐性が最良。GPU 実行なら per_text≈26ms と f16 でも十分高速。要 GPU(CPU では非現実的)。
- **その次が Qwen3-Embedding-4B(Candle・精度上限枠)**。v2 でも真ピーク **0.956**(@70・P=0.963・
  R=0.948)で 8B 以外を大きく引き離す。v1 では P=1.000・誤統合 0 と「完璧」だったが、**v2 では誤統合 7 件**
  (`保証⇔保障` `厕所⇔台所` など)・難正例 `人参⇔carrot`(37.7)取りこぼしと、初めて明確な誤りが出た。
  弱点は速度/RAM(Candle CPU・f16・1 件ずつ前向き計算・≈3.9 秒/語・約 8GB RAM)。GPU・バッチ・オフライン
  等で速度を許容できる精度最優先用途向け(`--model qwen3-4b`、Apache 2.0)。**Candle 単独ビルドの既定モデル**
  で、暴走オンセット 82・安全運用点 @83 で R≈0.75 と Candle 勢で堅牢性 × 再現率のバランスが良い。
- **Qwen3-Embedding-0.6B(Candle・軽量枠)**。真ピーク **0.764**(@71・P=0.926・誤統合 10)で、
  bge-m3(0.699)を精度で上回る。candle 0.9 の制約から 1 件ずつ前向き計算するため ≈200ms/語(bge-m3 の
  約 12 倍)。軽量だが堅牢性ベンチで暴走オンセット 94・実用的な安全運用点が無い(安全点で R≈0.02)ため
  既定にはしない(`--model qwen3`)。
- **既定は bge-m3(精度と速度のバランス・ONNX で高速)**。真ピーク **0.699 は ONNX 勢で最高**、かつ
  **真ピーク時の誤統合 7 件は強モデル中で最小**(gte 27・granite-278m 28・distiluse 12・large 41)。
  ピーク時 P=0.939 と適合率も最高水準。「高 clusterF1 は誤統合増と引き換え」というトレードオフ
  (granite-278m は 0.682 だが誤統合 28)を破り、精度・安全性・サイズ(1.06GB)で gte(0.657 / 誤統合 27)を
  上回る。`Xenova/bge-m3` の fp16 単一 ONNX を読み込む(`--model bge-m3`)。唯一の弱点は
  推論速度(gte の約 3 倍 ≈16ms/語)。
- **速度重視の代替は gte / 軽量代替は distiluse**。gte は真ピーク 0.657 で推論が bge-m3 の約 1/3(≈5ms/語)
  と軽快だが**誤統合 27 件**と多め。distiluse は真ピーク 0.662 を高適合率(P=0.895)・誤統合 12 件で達成し、
  **最小サイズ(0.54GB)・最速級(2.45ms)**。v2 では distiluse が gte を clusterF1・誤統合の双方で上回る。
  ただし distiluse は単漢字かな(`猫⇔ねこ`)の難正例を取りこぼす(最難正例 0.0)弱点がある。
- **clusterF1/再現率を最優先するなら granite-278m(選択肢)**。真ピーク 0.682(bge-m3 に次ぐ)で再現率
  R=0.593 が高いが、**誤統合 28 件**と「猫=犬」型のデータ破壊が多い。再現率最優先の用途に留める
  (`--model granite`)。
- **granite 系のその他 / e5 系 / paraphrase 系**は上位群に届かない。granite-311m-r2(0.652@87)・
  granite-107m(0.652@80)は高閾値ピークで誤統合も多い。e5-large(0.638)は E5 系で最高だが重い(13.6ms)。
  e5-small(0.561)は最軽量・最保守(ピーク時 P=0.853)で誤統合 14 件と少なく、保守性重視の選択肢。
  e5-base(0.514)は e5-small に劣後。paraphrase(0.591@89)・mpnet(0.567@86)は高閾値ピークかつ誤統合
  80 / 79 件と多い。
- **multilingual-e5-large-instruct は見送り(`--model e5-instruct`)**。真ピーク 0.645 で、**誤統合 75 件と
  全評価モデル中で最多**(指示プレフィックスでコサインが高帯域に寄り推移閉包が異義語まで巻き込む)。
  Candle で safetensors を直読みできるため ONNX 非依存環境の選択肢には残す。
- **snowflake-arctic-embed-l-v2.0 は見送り**。検索特化のため対称類似度で低調(真ピーク 0.495・@52)。
  素の bge-m3(0.699)が大差で上回り、検索特化の再学習が本タスクには逆効果と分かる
  (`--example benchmark -- arctic-l`)。
- **校正の含意**: スコア校正は全モデル共通(`SCORE_BASELINE=0.7`)。最適閾値がモデルで異なるのは余弦分布の
  違いであって優劣ではない。**運用閾値はモデルごとに `robustness` の暴走オンセットを見て選ぶ**。この表の
  「最適閾値」は計測時点の値なので、閾値の数字は測り直す(clusterF1 等の値は校正非依存で有効)。

## clusterF1 スイープ(代表モデル・5 刻み)

固定閾値の値はモデルの余弦分布で動くため、概形把握用。太字は各モデルのピーク帯
(閾値の絶対値は計測時点の値で、運用閾値は `robustness` で測り直す)。

| 閾値 | qwen3-4b | qwen3-0.6b | bge-m3 | gte | distiluse | e5-large | e5-small |
|---:|---:|---:|---:|---:|---:|---:|---:|
| 55 | 0.235 | 0.047 | 0.038 | 0.321 | 0.466 | 0.038 | 0.035 |
| 60 | 0.705 | 0.137 | 0.055 | 0.450 | 0.538 | 0.043 | 0.056 |
| 65 | 0.898 | 0.436 | 0.422 | 0.630 | 0.640 | 0.160 | 0.279 |
| 70 | **0.956** | **0.753** | **0.699** | **0.657** | **0.662** | 0.614 | **0.561** |
| 75 | 0.945 | 0.718 | 0.648 | 0.512 | 0.649 | 0.599 | 0.451 |
| 80 | 0.916 | 0.655 | 0.549 | 0.377 | 0.635 | 0.498 | 0.244 |
| 85 | 0.781 | 0.496 | 0.379 | 0.187 | 0.604 | 0.194 | 0.070 |

> 1 刻みの真ピークは上の主表を参照(qwen3-0.6b は 0.764@71、e5-large は 0.638@69 など)。

## 別系統モデル(多言語特化でないベースライン)

「全く別のモデル」も同じ物差しで測った。いずれも日本語中心の本データでは大きく劣り、**多言語特化の
学習が本質的に効いている**ことを裏づける(v2・best-F1 / @70 誤統合)。

| モデル | 系統 | best-F1 | @70 誤統合 | 備考 |
|---|---|---:|---:|---|
| bge-small-zh-v1.5 | BGE(中国語特化) | 0.172 | 181 | 中国語語彙には反応するが日本語は学習外。`リンゴ⇔たまご`=100.0 |
| all-MiniLM-L6-v2 | 英語 SentenceTransformers | 0.038 | 1132 | 英語専用。日中はほぼ識別不能 |
| clip-ViT-B-32-text | CLIP(対照学習・別アーキ) | 0.033 | 11434 | 全テキストが高類似に潰れ 1 クラスタに統合してしまう |

## 用途別の選び方

| 重視点 | 推奨 | 閾値 |
|---|---|---|
| 精度の絶対最優先・速度不問(真ピーク 0.956・Candle f16・≈3.9秒/語・8GB RAM・GPU/バッチ向け) | **qwen3-4b** | 70 |
| 精度重視 × そこそこ動く(真ピーク 0.764・Candle・≈200ms/語) | **qwen3** | 70 |
| 精度と速度のバランス(**既定**・真ピーク 0.699・誤統合最小 7・ONNXで高速・1.06GB) | **bge-m3** | 70 |
| 速度重視(1.2GB・bge-m3 の約 1/3 の推論時間。誤統合はやや多い) | **gte** | 70 |
| 精度に近い × 軽量・最速(0.54GB・誤統合 12) | **distiluse** | 70 |
| clusterF1/再現率最優先(誤統合は増える・1.1GB) | **granite-278m** | 70 |
| 最軽量・最保守(高適合率・誤統合 14・0.45GB) | e5-small | 70 |

> 測定環境: CPU(4 コア)。ONNX 勢は ONNX Runtime、Candle 勢(qwen3 / e5-instruct)は Candle(ピュア Rust)。
> per_text は相対比較用で、Candle 勢は ONNX とは直接比較不可。別系統 3 種は多言語性能の下限確認用。
