見出し画像

量子化トップはF16でなくQ8_0(40%):サイバー特化Dolphin3-Cyber-8Bを汎用Pythonベンチで叩いたら、本当の分水嶺はQ4→Q3にあった

こんにちは、くーるぜろです。

今回の検証対象は Dolphin3-Cyber-8B(作者: RavichandranJ)。名前のとおりサイバーセキュリティ用途に特化してファインチューンされた8Bモデルです。ベースは `Dolphin3.0-Llama3.1-8B-abliterated`(huihui-ai の無検閲版)で、そこにOWASP Top 10 / MITRE ATT&CK / CVE / exploit DB / ペネトレーションテスト手法を学習させた、という素性がモデルカードに書かれています。

先に断っておくと、これを筆者が叩いたのは汎用のPythonバグ修正ベンチ(llmbench)です。つまり最初から土俵違い。低いスコアが出ても、それは「用途と設計の差」であって「モデルがダメ」という話ではありません。この割り引きは記事の最後まで効かせます。

そのうえで、量子化6種(F16 / Q8_0 / Q6_K / Q5_K_M / Q4_K_M / Q3_K_M)を並べたら、この連載でおなじみの見どころが2つ出ました。先に結論だけ言います:名目トップは最高精度のF16ではなく Q8_0(40%)。そして本当に意味のある差は「Q4→Q3の崩落」ただ一点でした。


検証対象モデルの正体(まず正直に)

ひとつ、読者に誤解してほしくない点があります。

配布GGUFのファイル名が基底モデル名のままなんです。`Dolphin3.0-Llama3.1-8B-abliterated.Q8_0.gguf` のような名前で配られていて、ベンチの計測ログにもそのまま `Dolphin3.0-Llama3.1-8B-abliterated.F16` 等と記録されました。ファイル名は基底モデル名を引き継いでいるが、中身はCyber版です(確度: 記事名およびモデル配布元より HIGH)。ログの見た目に引きずられないよう、ここは明記しておきます。

abliteratedとは何かを1文で。モデルの残差ストリーム上で「拒否(refusal)」を担う方向ベクトルを特定し、重みからその方向を除去することで、再学習なしに拒否挙動を機械的に無効化する手法です(考案: mlabonne)。Dolphin系はそもそも学習データ段階で無検閲寄りなので、それをさらに強めた版がベースになっている、という理解でいいと思います。

公称値についての注意(混ぜない)

Cyber版そのものには公開ベンチ値がありません。大元の `dphn/Dolphin3.0`(非Cyber・非abliterated)にはOpen LLM Leaderboard値(Avg 24.97 / IFEval 76.21 / BBH 27.63 / MATH L5 10.50 / GPQA 4.36 / MuSR 8.97 / MMLU-PRO 22.13)がありますが、これは別モデルの参考値です。この記事の実測表には一切混ぜません。念のため。


検証環境

  • 実行環境: llama.cpp / GGUF量子化での計測

  • ハードウェア: (※実行環境の詳細はログ未記録。llama.cpp / GGUF量子化での計測)

  • タスク数: 40問(easy 5 / medium 5 / hard 10 / expert 12 / frontier 8)

  • 実行回数: 各タスク1回のみ(runs=1) → pass@k・5runs平均は無し。単発データです

  • 内容: Pythonのバグ修正・実装タスク(関数レベル、決定論的な隠しpytestで判定)

  • サンプリング: 公式推奨 temp 0.7 / top_p 0.9(Cyber-8Bカード値を採用。※ベンチログにサンプリング値の記録フィールドは無かったため、公式推奨値を採用したものとして記載)

  • 量子化: F16 / Q8_0 / Q6_K / Q5_K_M / Q4_K_M / Q3_K_M の6種

  • 評価軸: Resolved率 / Quality / Combined / usability / tok/s

ハードウェア環境は、正直に言うと今回ログに残っていませんでした。連載でいつも使っているEVO-X2+RTX5090…と書いてしまうのは簡単ですが、確認できないものを実測のように書くのはこの連載の流儀に反するので、環境行はプレースホルダにしています。

llmbenchについて(毎回の再掲)

  • SWE-Bench風の自作ベンチ。バグレポート+ソースをLLMに渡し、patch適用 → LLMには非公開の隠しpytestでresolved判定

  • 難易度tier: easy / medium / hard / expert / frontier。タスクIDは t001〜t040

  • Combined = success_rate ×(0.5 + 0.5 × quality/100)× 100(動かないコードは0点)

  • Qualityはlint密度+保守性指標+別LLMレビューの重み付き合成

  • GitHub: `zephel01/swe-bench`(MIT)。stdlib-onlyで再現可能

単発(1run)である以上、±3pt(=1〜2問)程度の差では優劣を断定しません。 これは今回ずっと効かせる大原則です。


結果サマリ(6量子化 × 40タスク・各1run)【筆者の実測】

結論: 名目トップは Q8_0(40%)だが、F16〜Q4_K_Mは35〜40%の中に団子で並んでおり単発±3ptの範囲、実用上は同格。唯一はっきり落ちるのは Q3_K_M(22.5%)——ここだけが単発ノイズを超えた本物の差だ。

補足として、Q3_K_M・Q4_K_MのQuality平均が高い(91.6 / 93.4)のは生存バイアスです。易しいタスクしか解けず、その解けたものの品質だけが高く出ている。Resolved率とは切り離して読んでください。実際、最もResolvedが低いQ3_K_Mが最もQuality平均が高いという逆転が起きています。「品質の平均が高い=優秀」ではありません。


逆転現象:「ビットを上げれば精度が上がる」は今回も不成立

この連載の常連ネタです。今回もきれいに不成立でした。

  • 最高精度であるはずの F16 は 35%。それを Q8_0(40%)が上回った

  • F16 は Q6_K・Q4_K_M と同値(35%)

ただし——ここで飛びつかないのが連載の作法です。40%と35%の差は2問。各量子化1runなので、この2問はサンプリングの揺れ(temp 0.7で引いた運)で普通に動く範囲です。「Q8_0がF16より賢い」とは言いません。 言えるのは「最高ビットを積んでも精度は伸びなかった。むしろ団子」というところまでです。

なぜ団子になるのか。8Bという規模のモデルにとって、このベンチのmedium以上はそもそも重み精度の問題ではなく能力の天井に当たっているからだと推測します(自信度: MODERATE)。天井に頭がつかえている以上、F16でもQ4でも結果は変わりようがない、という構図です。

本当の分水嶺:Q4→Q3の崩落(35%→22.5%、5問差)

団子の中で唯一、単発ノイズでは説明できない落ち方をしたのが Q3_K_M です。

  • Q4_K_M: 35.0%(14/40)

  • Q3_K_M: 22.5%(9/40)

  • 差: 12.5pt = 5問

±3ptの留保を効かせても、5問差は超えています。これは運ではなく、Q3_K_Mで量子化が効きすぎて壊れた、という信号として読んでいい。難易度別に見ると崩落の場所もはっきりします(後述)。

まとめると、今回の量子化スペクトルは「F16〜Q4_K_Mまではほぼ横ばい、Q4とQ3の間に崖がある」という形。分水嶺はビット最上位ではなく、下限側にありました。


難易度別 Resolved(各1run)

読みどころ:

  • easyは全量子化で満点(5/5)。ここはビットに関係なく確実。

  • mediumから崩れ始める。どの量子化も2/5前後で、Q3だけ1/5。

  • expert/frontierはほぼ全滅。解けているのはexpertのt031など、ごく少数のみ。これは量子化ではなくモデルの天井です。

  • Q3_K_Mの崩落は hard(2/10)と frontier(0/8)に集中している。分水嶺の実体はここ。

expert 1〜2/12、frontier 0〜2/8という数字は、量子化を上げても下げても大して動きません。土俵違いを思い出してください。サイバーセキュリティ特化モデルに、汎用Pythonのバンカーズ丸めやRFC4180パーサやバイトコードVMを直させているわけで、ここが低いのは設計と用途の差です(自信度: MODERATE)。モデルの優劣の話ではありません。


usability(実際どれくらい任せられるか)

Resolved率とは別に、生成物を「そのまま使えるか」で3分類しました。

  • 🟢 自律: レビューほぼ不要でそのまま使える

  • 🟡 補助: レビュー前提なら任せられる

  • 🔴 不可: 任せられない

特徴的なのは、🟡補助がQ8_0とQ6_Kに1問ずつしか無いこと。つまりこのモデルの出力は**「そのまま通るか、全く通らないか」の二極**に寄っています。「惜しい、あと少し直せば動く」という中間層が薄い。resolvedしたものは隠しpytestを通り切っているので基本そのまま使え、落ちたものは根本から間違っている、という白黒のはっきりした挙動でした。Q3_K_Mだけ🔴不可が77.5%まで膨らみます。


量子化ごとの失敗タスク(tNNで具体的に)

全量子化で確実に解けた核(6/6)

t001〜t005(easy全部)、t008(binary_search)、t015(merge_config)、t018(registry)、t031(shortest path with forbidden edges)。これがこのモデルの「確実にできる」土台です。

全量子化で共通して落ちた鬼門(0/6)——モデルの天井

  • t007(word_frequencies: Word/wordの大小文字)

  • t009(fibonacci: 2項目以降が全部ずれる)

  • t010(parse_csv_line: クオート内フィールドが壊れる)

  • t013(rate limiter: 1リクエスト多く通す off-by-one)

  • t017(slugify: 仕様が曖昧なゴミ処理)

  • t019(trie: prefixを登録語として扱う)

  • t020(calculator: 演算子優先順位・括弧を無視)

  • expert大半(t021〜t025・t027〜t030・t032)

  • frontier大半(t033〜t035・t037・t039・t040)

この鬼門群は全量子化で揃って0/6です。 ということは、これらは量子化のせいではなくモデルの天井。ビットをF16まで上げても解けないものは解けない。連載の他モデルでも常連の t020(電卓の優先順位)や off-by-one系(t013)は、ここでも順当に鬼門でした。

量子化で揺れたタスク(=単発の運の範囲、序列の根拠にしない)

  • t006: Q3のみ落

  • t011(LRUCache): Q3のみ落

  • t012(Cart.total_with_discount): Q4/Q3落

  • t014(Scheduler): Q5/Q4のみ解

  • t016(daily_summary): Q8/Q4のみ解

  • t026(toposort: 循環検出): Q8/Q6のみ解

  • t036(where_in: パラメータ化): F16/Q8/Q6/Q5解、Q4/Q3落

  • t038(consecutive list → 1つの`<ul>`): Q6/Q3落

ここは1問=2.5ptの揺れです。「Q8_0だけt026を解いたからQ8_0が賢い」みたいな読み方はしません。単発1runでの解けた・落ちたは運の範囲。序列の根拠にはしていません。Q3_K_Mだけは t006・t011・t012 と、他が解けている易しめのタスクまで連鎖的に落としており、これが崩落の中身です。


tok/s(速度)——読み方に注意

tok/sは速度であって賢さではありません。この連載では毎回「読み方の注意」を3点セットで添えています。

  1. MTP(投機的デコード)搭載モデルは構造的に速い数字が出る(賢さではない)

  2. MoEは活性化パラメータが小さいので速い(35B-A3Bなら実質3B分の読み出し)

  3. dense標準版は素直に遅い——遅い=劣っている、ではない

そして今回の重要な但し書き。Dolphin3-Cyber-8Bはdense標準構成で、MTPもMoEも持ちません。 だから上の1・2のバイアスは効いておらず、tok/sの傾きは純粋に「量子化が軽い→メモリ読み出しが速い」だけを反映しています。F16の~95.6からQ3_K_Mの~260.6まで、ビットが軽くなるほど素直に速くなる。きれいな相関です。

ただし——速度と解決力は完全に無関係であることが、この表と結果表を並べると一目瞭然です。最速のQ3_K_M(~260.6 tok/s)が、最もResolvedが低い(22.5%)。速さに釣られてQ3を選ぶと、いちばん解けないモデルを最速で回すことになります。

もう一点。上のtok/sは単発1ストリームの平均値です。並列実行(バッチ)時の1ストリームあたりtok/sは桁が変わるので、この数字はあくまで「1本流したときの体感速度」として読んでください。


まとめ:結局どれを選ぶか(量子化ごとに1行で)

結論(再掲): F16〜Q4_K_Mは35〜40%の団子で単発±3ptの範囲、実用上ほぼ同格。唯一の実質的な差はQ3_K_Mの崩落(22.5%)。 「ビットを上げれば賢くなる」も「速い量子化がお得」も今回は成立しない。

用途別に言い切ります(サイズは参考値)。

  • F16(約16.1GB):選ぶ理由はない。 35%で下位量子化と同値、しかも最も遅く最も重い。8Bをこのベンチで回すなら丸損。

  • Q8_0(約8.54GB):名目トップ(40%)を取りたいなら。 ただしF16〜Q4との差は運の範囲。品質の安心料として上限を積む人向け。

  • Q6_K(約6.6GB):中庸。 特に選ぶ理由も避ける理由もない35%。

  • Q5_K_M(約5.73GB):バランス枠の筆頭。 37.5%で上位と同格、サイズ・速度も手頃。迷ったらこれ。

  • Q4_K_M(約4.92GB):VRAMを絞りたい実用ライン。 35%で上位と実質同格、約5GB。軽さ優先ならここで十分。

  • Q3_K_M(約4.02GB):非推奨。 22.5%への崩落。約1GBの節約のために解決力を1/3近く失う。分水嶺の向こう側。

一言でまとめると、「精度で選ぶならQ5_K_M、軽さで選ぶならQ4_K_M、Q3には落とすな」。F16やQ8_0に上乗せする実利は、このベンチでは見えませんでした。

教訓

  • 教訓1:量子化の分水嶺は「最上位」ではなく「下限」にある。 ビットを上げても団子、下げていくとある一線(今回はQ4→Q3)で崖から落ちる。買い足すべきは上限ビットではなく、崖の手前で止まる判断です。

  • 教訓2:Quality平均が高い量子化を「優秀」と読むな。 下位量子化ほどQualityが上がるのは生存バイアス。易しい問題しか解けていないから平均が上がっているだけで、Resolved率と切り離して読まないと逆の結論に迷い込みます。

そして最後にもう一度。今回のスコアはサイバーセキュリティ特化モデルを汎用Pythonバグ修正ベンチに掛けた、土俵違いの数字です(自信度: MODERATE)。Dolphin3-Cyber-8Bの本領はOWASP/MITRE/CVE/exploit系のドメインにあります。ここでの低さは設計と用途の差であって、モデルの実力を否定するものではありません。このモデルを試すなら、まずは想定ドメインで叩くのが筋——というのが、土俵違いを承知で回した筆者からの正直な注記です。


検証で生成したコード・テスト結果はアーカイブ済みです。「特定タスク(tNN)の詳細が見たい」「自分の環境でも試したい」はコメントへどうぞ。

モデル情報

#ローカルLLM #llamacpp #ベンチマーク #量子化 #GGUF #Dolphin #8B #サイバーセキュリティLLM #abliterated #uncensored

いいなと思ったら応援しよう!

zephel01 サーバー代とコーヒー代になります☕ 役に立ったら応援よろしくお願いします!