# ラーメンスープ評価AI 精度改善報告書

作成日: 2026-06-19  
報告対象: BytePlus提案の検証結果と、自社パイプライン改善の進捗

---

## 1. 結論

BytePlusから提案されたXGBoostベースの後段スコアリング方式について、同じデータで自社側の複数モデルと比較しました。

結果として、自社側の比較結果がBytePlus提案値を全指標で上回りました。特に、比較対象として用意した線形回帰/Ridge系は精度が高く、仕組みも説明しやすいため、メイン方式として採用する判断にしました。

比較結果の要点は以下の通りです。

- BytePlus提案値: MAE 11.7 / 相関 0.53 / グレード一致 74%
- 採用候補（線形回帰）: MAE 8.75 / 相関 0.622 / グレード一致 80.8%
- 採用候補（Ridge回帰）: MAE 8.82 / 相関 0.633 / グレード一致 80.8%
- パイプライン改修後: グレード一致 約88〜89% / 誤差±15点以内 約92〜93%

その後、パイプラインも見直しました。判断できない画像は無理に点数化せず「要確認」に分岐するようにしたことで、最終的なグレード一致率は約88〜89%まで上がりました。

一方で、後半の監査では、現在AIに渡している情報で説明できる人間スコアのばらつきは、総合スコアで50%、スープスコアで44%にとどまることも分かりました。今後さらに精度を上げるには、モデル変更だけでなく、入力情報を細かくすることと、教師ラベルの品質改善が重要です。

---

## 2. BytePlus提案の内容

BytePlusからは、後段スコアリング方式としてXGBoostベースの提案を受けました。提案性能値は以下です。

- MAE: 11.7
- 相関: 0.53
- グレード一致率: 74%

提案内容は、「VLMで4業務次元を独立採点し、教師ありMLで合成する」2段構成です。4次元は、濃度・水位・油・沸騰です。

```text
入力: 動画(fps=1) ＋ Brix ＋ 時間帯
  │
  ▼
Stage1: 視覚理解  Seed 2.0 Pro（VLM）
        4次元を並列4回呼び出し（各: 動画 ＋ 3参照アンカー ＋ Brix ＋ 時間）
        Density 30 / Water 25 / Oil 25 / Boiling 20
  │
  ▼
Stage2: 合成  XGBoost 二系統ヘッド
        4次元スコア ＋ 派生特徴(計12) を投入
        回帰ヘッド → 連続スコア(0-100)
        分類ヘッド → 異常確率(attention_prob)
  │
  ▼
出力: ai_score / grade(A-D) / attention_needed / dim_scores / reasoning
```

提案性能（938動画・684件人間スコア・test137件）は、**グレード一致 74% / MAE 11.7 / 相関 0.53 / 異常検出 44%** でした。

この提案を受けて、同一データ・同一評価条件で複数モデルを比較し、次の点を確認しました。

- BytePlus提案方式が最適か
- 自社で内製した方式と比べてどうか
- 実運用で説明しやすく、安定して使える方式はどれか

評価対象は、最終評価に近い `human_total_score`（濃度込み総合点）を主軸にしました。

---

## 3. 比較の内容

BytePlus提案と横並びで比較するため、自社側では以下の構成で検証しました。この段階では、判断不能画像も含めて全件を後段モデルに通しています。

```text
入力: 動画 ＋ 実測Brix ＋ 時間
  │
  ▼
Stage1: 前処理  DensityResolver（ルール＋学習）
        代表フレーム抽出（多フレーム→湯気除外→RF-DETR抽出→最良選択＋可読性判定）
        濃度確定（実測Brix優先 / なければ濃度推定AI）
  │
  ▼
Stage2: 視覚理解  Seed 2.0 Pro（LLM）
        最良1フレーム ＋ 濃度 ＋ 時間 → 全項目を1回で固定JSON出力
        visual_density / water_level / oil_emulsification / boiling_heat_state / photo_quality
  │
  ▼
Stage3: 後段モデル比較  6モデル（学習）
        特徴量生成 → 固定配点 / 線形 / Ridge / RF / XGBoost / LightGBM × 4特徴量セット
        ※この段階では判断不能画像も含め全件スコア（分岐なし）
  │
  ▼
出力: スコア / グレード
```

### 3.1 比較設計

| 項目 | 内容 |
|---|---|
| データ | 完了済みLLM評価 519件（100点スケール外の異常値1件を除外） |
| 分割 | train 363 / validation 52 / test 104（固定）＋ 5-fold交差検証 |
| 比較モデル | 固定配点 / 線形回帰 / Ridge回帰 / Random Forest / XGBoost / LightGBM |
| 特徴量セット | visual_only / visual+Brix / visual+Brix+時間帯 / Brixのみ |
| 評価指標 | MAE（平均誤差）/ 相関 / グレード一致率（A/B/C/D） |

人間コメントは運用時に得られないため、特徴量には含めていません。

### 3.2 BytePlus提案と自社構成の違い

| 観点 | BytePlus提案 | 自社構成 |
|---|---|---|
| LLM呼び出し | 4次元を**並列4回**＋各3アンカー | 全項目を**1回**で固定JSON出力 |
| フレーム | 動画 fps=1 | 最良1フレーム（RF-DETR選択） |
| 後段モデル | XGBoost 二系統ヘッド | 複数モデルを比較し、線形回帰/Ridge系を有力候補化 |
| 判定可否 | 将来課題（5th call構想） | 比較時点では分岐なし。後段検証で2段ゲート化 |
| 濃度 | Brixを参考入力（最重要特徴） | 同様＋濃度推定AIで将来代替 |

### 3.3 採用候補の結果（`human_total_score`, test）

| モデル | 特徴量 | MAE | 相関 | グレード一致率 |
|---|---|---:|---:|---:|
| 線形回帰 | visual+Brix | **8.75** | 0.622 | **80.8%** |
| Ridge回帰 | visual+Brix+時間帯 | 8.82 | **0.633** | **80.8%** |

### 3.4 BytePlus提案値との比較

| 指標 | BytePlus提案値 | 採用候補（線形/Ridge） | 差 |
|---|---:|---:|---:|
| MAE | 11.7 | **8.75（線形回帰）** | −2.95（改善） |
| 相関 | 0.53 | **0.633（Ridge回帰）** | +0.10 |
| グレード一致率 | 74% | **80.8%** | +6.8pt |

各指標の意味は以下です。

| 指標 | 意味 | 見方 |
|---|---|---|
| MAE | AIの予測点数と人間の点数が、平均で何点ずれているかを示す指標です。 | 小さいほど良いです。今回は11.7点ずれから8.75点ずれまで改善しています。 |
| 相関 | AIの点数と人間の点数が、同じ方向に動いているかを示す指標です。 | 1に近いほど良いです。点数の高低傾向をどれだけ追えているかを見る指標です。 |
| グレード一致率 | AIと人間で、A/B/C/Dの評価ランクが一致した割合です。 | 高いほど良いです。現場で見たときに、評価ランクが合っているかを示します。 |

採用候補の線形回帰/Ridge回帰は、BytePlus提案値を全指標で上回りました。なお、単純な最良値ではRandom ForestやLightGBMも上位でしたが、精度差は小さいため、説明しやすさと運用安定性を重視して線形回帰/Ridge回帰系をメイン方式にしました。

### 3.5 採用方針

学習モデル間の精度差は小さかったため、最終判断では精度だけでなく、説明しやすさと運用安定性も重視しました。

| 役割 | モデル | 理由 |
|---|---|---|
| **メイン** | 線形回帰 / Ridge回帰 | 上位帯の精度、説明しやすさ、交差検証で最も安定（標準偏差が最小） |
| サブ（継続比較） | Random Forest | `human_total_score` でMAE最良 |
| サブ（継続比較） | LightGBM | 相関が最良 |
| サブ（提案比較軸） | XGBoost | BytePlus提案方式との比較軸として継続 |
| 不採用 | 固定配点 | 学習モデルより大幅に劣る |

結論として、メインは線形回帰系で進め、Random Forest・LightGBM・XGBoostは継続比較対象として残す方針にしました。

---

## 4. 比較後に検証した内容

比較後は、予測が大きく外れた原因を確認し、パイプライン改善、入力追加、ゲート整理、教師ラベル監査、店舗別検証を行いました。

### 4.1 大きく外れた原因

予測が大きく外れたサンプル上位50件を画像で確認したところ、原因は以下の3つに分かれました。

| 原因 | 割合 | 内容 |
|---|---:|---|
| LLM評価ミス | 42% | 白泡・脂膜・浮いた具材の白さで濃度を過大評価 |
| **画像では判断不能** | **26%** | LLMが「評価不能」と申告した画像を、後段が無理にスコアしていた |
| その他（回帰の天井効果 等） | 32% | 人間=満点でも予測が頭打ち、など |

特に重要な点は、画像として判断不能なものまで後段で点数化していたことです。これはモデル精度の問題ではなく、パイプライン設計の問題でした。

### 4.2 判断不能画像を分岐する改修

判断不能画像は無理に点数化せず、「要確認/撮り直し」に分岐する設計に変更しました。

```text
【改修前】 全画像 → 後段で一律スコア化（判断不能画像も無理にスコア）
                                  ↓ 大外しの約1/4が発生

【改修後】 画像 ─┬─ 評価不能(assessable=0) → 「要確認/撮り直し」（スコアしない）
                └─ 評価可能(assessable=1) → 後段でスコア化
```

この改修は、既存ファイルを変更せず、自己完結したパイプライン（`精度改善_20260619/pipeline/`）として恒久化しました。LLMプロンプトは変更していないため、LLM再実行による追加コストは発生していません。

### 4.3 採用パイプライン

検証結果を反映し、最終構成では「判定できる画像か」を先に分岐させる2段ゲートを入れました。後段モデルは線形回帰をメインにします。

本番想定の入力は、濃度（実測または濃度推定AI）、動画、時間（開店前・17時〜19時）です。

```text
入力: 動画 ＋ 濃度(実測 or 濃度推定AI) ＋ 時間(開店前/17-19時)
  │
  ▼
Stage1: 前処理・上流ゲート  DensityResolver（ルール＋学習）
        代表フレーム抽出（多フレーム→湯気除外→RF-DETR抽出→最良選択）
        濃度確定（実測Brix優先 / なければ濃度推定AI）
        判定可否① 可読性ゲート: RF-DETR readable=False → 「要確認」★
  │
  ▼
Stage2: 視覚理解・採点ゲート  Seed 2.0 Pro（LLM）
        画像評価: 最良1フレーム ＋ 濃度 ＋ 時間 → 表面状態を固定JSON
                 water / oil / boiling / photo（visual_densityは将来除外, §4.10）
        判定可否② 評価ゲート: assessable=0 → 「要確認」★
  │
  ▼
Stage3: 採点・合成  線形回帰（学習）★
        特徴量生成（濃度 ＋ 動画(LLM評価) ＋ 時間）
        スコア回帰 → グレード付与（A≥80 / B60-79 / C21-59 / D<21）
  │
  ▼
Stage4: 出力生成  LLM
        スコア・グレード・要確認理由を説明文化（スコアはLLMに決めさせない）
  │
  ▼
出力: スコア / グレード / 状態(scored・要確認) / 説明文
```

各工程の入出力・技術・データ仕様・実装状況は `精度改善_20260619/pipeline/PIPELINE_DETAIL.md` に整理済みです。

### 4.4 改修後の最終精度

改修後は、評価可能画像のみをスコアする実運用に近い条件で5-fold交差検証を行いました。

| 指標 | total（総合スコア） | soup（スープスコア） |
|---|---:|---:|
| **グレード一致率（A/B/C/D）** | **89.0%** | **87.9%** |
| 誤差 ±10点以内 | 71.7% | 74.6% |
| 誤差 ±15点以内 | 93.1% | 92.2% |
| 平均誤差（MAE） | 8.56点 | 8.25点 |

改修前後の比較は以下です。

| 指標 | 改修前 | 改修後 |
|---|---:|---:|
| グレード一致率（total） | 75.7% | **89.0%**（+13.3pt） |
| グレード一致率（soup） | 69.0% | **87.9%**（+18.9pt） |
| 誤差±15点以内（total） | 85.0% | **93.1%** |

評価ランク（A/B/C/D）が当たる率は約88〜89%、点数は±15点以内に約9割が収まる水準になりました。

### 4.5 代表フレーム抽出の高度化検証

この検証は実施しましたが、後日、評価前提が誤っていたことが分かりました。数値は記録として残しますが、現在の判断には使いません。

理由は、品質ゲートで見ていた画像が `ffmpeg_middle`（中央切り出し）フレームである一方、LLMが実際に見ていた画像はリゾルバが選んだbestフレームだったためです。つまり、検証対象のフレームがずれていました。

以下は、実施記録として残します。

ゲート: `steam_haze_score≥0.12 または sharpness<20 または blowout_ratio≥0.006` → 要確認  
assessable=1の346件中112件（32%）を追加で要確認へ、残234件をスコア。

| 条件 | target | n | MAE | グレード一致率 | ±10点以内 | ±15点以内 |
|---|---|---:|---:|---:|---:|---:|
| 打ち手1のみ | total | 346 | 8.56 | 89.0% | 71.7% | **93.1%** |
| 打ち手1＋フレームゲート | total | 234 | 8.60 | 89.7% | 76.1% | 89.3% |
| 打ち手1のみ | soup | 346 | 8.25 | 87.9% | 74.6% | 92.2% |
| 打ち手1＋フレームゲート | soup | 234 | **7.76** | **91.5%** | 78.6% | 91.9% |

当時の見立てでは、効果は限定的かつまちまちでした。後日確認により、この検証は無効扱いとし、代表フレーム抽出の高度化は既存パイプラインで既に実装済みと整理しました。

### 4.6 当初考えた改善案と、その後の見直し

当初は以下の改善案を考えていました。ただし、後半のアーキテクチャ確認により「LLMの濃度判定の精緻化」は前提誤りと分かり、撤回しました。濃度はLLMではなく、実測Brixまたは濃度推定AIが担う設計です。

| 優先 | 施策 | 狙い |
|---|---|---|
| ~~高~~（撤回§4.8） | ~~LLMの濃度判定（visual_density）の精緻化~~ | ~~大外しの42%…プロンプトで補強~~（→濃度はLLM対象外。撤回） |
| 高 | **低評価データの拡充＋「要注意判定」の別建て** | 60点未満が全体の2.3%しかなく、低評価を拾う力が弱い（要注意検出率ほぼ0） |
| 中 | 代表フレームの再抽出＋LLM再評価 | best_sample/複数枚統合でより良いフレームを選び直す（品質ゲートだけでは効果限定的＝§4.5） |
| 中 | 濃度推定AIの整備 | 将来、実測濃度が渡されなくなった場合に備える（裏側で推定濃度を併走測定） |

下表も当初の検討記録です。後半の確認により、LLM濃度判定の改善は現在の有効な打ち手から外しています。

| 改善点 | 現状 | 見込み | 根拠・前提 |
|---|---|---|---|
| LLM濃度判定の精緻化 | scored対象 MAE 8.5 | **MAE 7点台 / グレード一致率 90%台前半** を見込む | 大外しの42%がこの原因。ただしLLM再実行（追加コスト）が必要 |
| 要注意判定の別建て | 要注意検出率 ≈0% | **検出率を実用域へ** | 低評価データ拡充が前提。MAEより「見逃さない」価値 |
| 代表フレーム再抽出＋LLM再評価 | ffmpeg中央1枚 | **より大きな改善を見込む（要実測）** | 品質ゲート単独は効果限定的（§4.5）。フレームを選び直すにはLLM再実行コストを伴う |
| 濃度推定AIの整備 | 実測濃度に依存 | 実測濃度がなくなっても劣化を最小化 | CVでは濃度なしの後段劣化は軽微。事前の劣化測定が目的 |

### 4.7 代表フレーム抽出は既に実装済みでした

LLMが実際に評価していた画像は、`DensityResolver` が多フレームから湯気を除外し、RF-DETRでスープ領域を抽出して選んだbestフレームでした。LLM評価済み368件はすべてbestフレームを使用していました。

そのため、代表フレーム抽出の高度化は既存パイプラインで既に実現済みと整理しました。

### 4.8 LLM濃度判定の改善案は撤回しました

濃度はLLMではなく、濃度推定AI（ResNet18、全520件でMAE 0.27）またはCSV実測値で判定する設計でした。LLMには濃度を参考入力として渡しているだけで、これは正しい設計です。

したがって、Brixを切り離す案や、LLMに濃度判定を担わせる案は撤回しました。

### 4.9 入力に時間を追加した検証

本番入力に、濃度・動画に加えて時間（開店前 / 17時〜19時）を入れた場合の効果を測定しました。

| target | 特徴量 | MAE | グレード一致 | ±15点 |
|---|---|---:|---:|---:|
| total | 濃度+動画（従来） | 8.56 | 89.0% | 93.1% |
| total | **濃度+動画+時間** | **8.35** | 88.7% | 91.6% |
| soup | 動画のみ（従来） | 8.25 | 87.9% | 92.2% |
| soup | **濃度+動画+時間** | **8.04** | 87.6% | 90.5% |

時間追加によりMAEは改善しました。グレード一致率と±15点以内は1pt未満の微減であり、交差検証上のばらつきの範囲と見ています。本番パイプラインは `visual_plus_brix_slot` に更新し、再学習済みです。

### 4.10 判定可否ゲートの比較

「そもそも判定できる画像か」を分けるゲートを比較しました。結論として、採点直前の `LLM_assessable` が最も費用対効果が良いです。

| ゲート | カバレッジ | total グレード一致 | total MAE |
|---|---:|---:|---:|
| baseline（全件） | 100% | 75.7% | 9.41 |
| **LLM_assessable（打ち手1・採用）** | **66.7%** | 89.0% | **8.56** |
| RF-DETR可読性（readable） | 71.3% | 87.0% | 8.93 |
| RF-DETR可読性（最厳 assessable） | 42.6% | 90.5% | 9.03 |
| both | 42.4% | 91.4% | 8.91 |

最も厳しいゲートにするとグレード一致は少し上がりますが、カバレッジが大きく下がり、MAEも悪化します。運用上のバランスを考えると割に合いません。

本番では、次の2段ゲートで運用します。

1. 上流: RF-DETRスープ可読性で、撮影・抽出できない画像を弾きます。
2. 採点直前: LLM自身が評価不能とした画像を弾きます。

### 4.11 visual_densityは後段特徴量から外す方向です

`visual_density` を後段特徴量から外しても、精度はほぼ変わりませんでした。後段にはBrixが同じ情報を持つため、実害が出ていなかったと考えられます。

結論として、これは精度向上目的ではなく、設計整合のために外すのが正しいです。濃度はLLMではなく、実測Brixまたは濃度推定AIで扱います。

### 4.12 目標精度に対する現実的な見立て

目標をグレード一致95%、±15点以内98%と置いた場合、ゲート調整だけでは届かないことが分かりました。最も厳しくゲートしても、グレード一致はtotal 91.4%、soup 92.7%が天井でした。

この時点で、主戦場はモデルやゲートではなく、教師データの質に移りました。

### 4.13 教師ラベル監査

同じ観測状態（LLM評価＋濃度＋時間が同一）で、人間スコアがどれだけ割れているかを測定しました。対象はassessable=1の346件です。

| 指標 | total | soup |
|---|---:|---:|
| 説明可能上限（R²上限） | **50%** | **44%** |
| ノイズ床 MAE（群平均予測でも残る誤差） | **7.13** | **6.88** |
| ノイズ床 std | 9.2点 | 8.6点 |
| ユニーク観測状態数 / 346件 | 42 | 42 |
| 群内でグレードが割れる件数（/326） | 269 | 243 |

ここで分かったことは重要です。

- 現在AIに渡している情報で説明できる人間スコアのばらつきは、総合スコアで50%、スープスコアで44%にとどまります。
- 346件が42種類の観測状態に圧縮されており、LLM出力が粗い状態です。
- 現行モデルのMAEは、ノイズ床まで残り約1点で、後段モデルはほぼ天井に近いです。
- `suspected_label_outliers.csv` に要レビュー18件が出ています。

つまり、95%/98%を目指すには、後段モデルだけでは足りません。必要なのは、疑わしい教師ラベルの確認・補正と、LLM出力の高解像度化です。

### 4.14 店舗別検証

最後に、採点データの品質を店舗別に確認しました。考え方は、「採点にブレがある店舗では、同じ後段モデルでも精度が下がるはず」というものです。

評価バッチ（`training_dataset.csv` 520件）の `提出者` は全件「嘉手川航太朗」で、店舗情報を持っていませんでした。そのため、元データ `data/raw_csv/base_export.csv` の `提出者` 列と、SQLiteのmetadata内 `添付ファイル` 名を突合して店舗を付与しました。

モデル学習に足る件数があったのは、神保町（assessable=1で270件）と小田原（56件）の2店舗でした。

5-fold OOF、線形回帰、`visual_plus_brix_slot` で検証しました。

| 店舗 | n | total MAE | total グレード一致 | soup MAE | soup グレード一致 |
|---|---:|---:|---:|---:|---:|
| 【プール】全店舗 | 346 | 8.35 | 88.7% | 8.04 | 87.6% |
| 豚山　神保町店 | 270 | **8.10** | **93.3%** | **7.48** | **96.7%** |
| 豚山　小田原店 | 56 | **9.67** | **60.7%** | **9.60** | **57.1%** |

小田原は神保町より大幅に精度が低いです。これは単なる件数差ではありません。神保町をn=56に揃えた対照でも、神保町のtotal一致90.7%に対し、小田原は60.7%でした。

また、同一観測状態で人間グレードが割れる割合は、神保町 total 43.5% / soup 35.5% に対し、小田原は total 70.0% / soup 65.0% でした。採点ブレが大きい店舗ほどモデル精度が下がる、という仮説は支持されました。

店舗別検証の結論は以下です。

1. モデル精度は、採点データ品質の代理指標として使えます。
2. 神保町は採点品質が高く、全体精度を引き上げています。
3. 小田原は採点ブレが大きく、全体精度を押し下げています。
4. 次は、小田原の群内矛盾サンプルを採点者と照合し、店舗横断で採点基準を揃えるべきです。

### 4.15 今後の進め方

今回の検証から、次の順番で進めるのが現実的です。

1. BytePlus提案のXGBoostは参考比較軸として残し、メインは線形回帰/Ridge系で運用します。
2. 判断不能画像を無理に点数化せず、2段ゲートで「要確認」に分岐します。
3. 時間情報を含めた `visual_plus_brix_slot` を本番パイプラインとして採用します。
4. 疑わしい教師ラベル18件を確認し、明らかな誤りを補正します。
5. 小田原の採点ブレを確認し、店舗間の採点基準を揃えます。
6. その後、必要に応じてLLM出力を高解像度化し、42種類に圧縮されている観測状態を細かく分けられるようにします。

短期的には、追加課金なしでできるラベル確認と店舗別採点基準の整理が最優先です。中期的には、LLM出力の粒度を上げることで、現在の精度天井を押し上げます。

---

## 付録: 関連ファイル

| 種類 | パス |
|---|---|
| BytePlus提案資料 | `docs/byteplus_proposal.md` |
| 後段比較スクリプト | `検証/scripts/run_downstream_model_comparison.py` |
| 後段比較レポート | `reports/後段モデル比較レポート_20260619.md` |
| 大外し分析・分類 | `精度改善_20260619/01_error_analysis/`（`findings_一次分類.md`） |
| 交差検証・濃度条件 | `精度改善_20260619/04_cross_validation/` |
| 打ち手1の効果検証 | `精度改善_20260619/05_branch_comparison/` |
| 代表フレーム品質ゲート検証（§4.5・無効） | `精度改善_20260619/06_frame_quality/` |
| 打ち手2 提案（撤回） | `精度改善_20260619/07_prompt_v2/`（`打ち手2_プロンプト改善案.md`） |
| ゲート比較・入力拡張・vd廃止検証 | `精度改善_20260619/08_gate_comparison/` |
| 教師ラベル監査 | `精度改善_20260619/09_label_audit/`（`label_audit_summary.md`） |
| 店舗別検証 | `精度改善_20260619/10_store_validation/`（`summary.md`） |
| 恒久化パイプライン | `精度改善_20260619/pipeline/`（`README.md` / `PIPELINE_DETAIL.md`） |
