AIシステム全体を設計する

AI評価データセットの作り方:代表例・難例・未知例を分ける

よく動く例だけを集めれば高い点数は作れますが、実際の利用を説明する証拠にはなりません。何の入力を、どんな分布で、どの目的のために集めたかを明確にするところから評価を始めます。

編集・運営:株式会社ノースネスト · AI支援の学習解説

公開: · 更新: · 約3分(目安)

この記事の目的

評価結果の適用範囲と、データの使い回しによる過大評価を説明できる。

こんな方へ

生成AIの比較や改善の根拠を作りたい方。

代表例と重要な失敗を分けて集める

日常の入力を反映する例と、件数は少なくても影響が大きい例を分けます。資料不足、曖昧な質問、権限の境界、入力の破損など、失敗の種類を残すことで、平均点に隠れた問題を見つけられます。

実データを使う場合は、利用の条件と機密情報の扱いを確認します。架空データへ変換した場合も、元の難しさを保てているかを検討し、その出所を記録します。

調整用と最終確認用を分ける

何度も見た評価例へ合わせてプロンプトを直すと、その例への対応だけが良くなることがあります。探索に使う例と、判断を確認する例を分けます。最後の確認例も繰り返し調整へ使ったなら、未知の確認材料ではなくなったことを認識します。

同じ文書の言い換えが別の集合へ入ると、実質的な重複が起こります。見た目の文章だけでなく、元の資料や事例の単位で分割する方法を考えます。

正解が一つでない入力を扱う

自由な文章では表現の一致だけで採点できません。必須の事実、許容する表現、保留が必要な条件を定めます。正解ラベル自体に不一致がある場合は、無理に確定してモデルの失敗にせず、基準を見直す対象として記録します。

評価集合が更新される理由を残す

運用で新しい失敗が見つかったら、評価例へ追加することは有用です。ただし難しい例だけを追加し続けると、全体の点数が下がっても品質が悪くなったとは限りません。集合の版、追加した理由、どの利用分布を代表するかを残します。以前の集合での比較と、新しい集合での比較を区別することで、点数の変化を誤って説明することを避けられます。

正解の確認者も、資料が不足した入力では断定できないことがあります。未確定のラベルを無理に確定し、モデルが別の妥当な回答をした場合に失敗と数えないようにします。複数の許容回答や必須事実、保留条件を明示し、人同士の不一致も確認材料として残します。評価データの品質を、モデルの評価とは別に点検することが重要です。

再現例で判断の境界を確認する

開発用と評価用で設問IDが異なっても元資料が重なるケースを検出し、資料単位で分けたケースと比較します。

sourceIdが正しいことを前提にした一致検査です。言い換えや近似重複の検出、正解ラベルの品質、評価の代表性、モデルの精度は測定していません。

具体例で考える

説明用の100件の評価で、80件が簡単な同種の質問、重要な例外は2件しかない状況です。実測値ではありません。

説明用の入力・判断例
集計:全体と、例外群を別々に表示。
見直し:実際の利用分布と照合。
確認用:同じ原資料の言い換えを調整用へ混ぜない。

件数を揃えるだけで代表性が得られるとは限りません。点数の高低を結論にする前に、何を含めて何を含めなかったかを説明できるようにします。

ローカルで再現する:設問IDだけではデータ分離を確認できない

開発用と評価用で設問IDが異なっても元資料が重なるケースを検出し、資料単位で分けたケースと比較します。

以下は公開コードを実行して得た結果です。入力は学習用に作った架空データで、Claude API・外部サービスへの通信は行っていません。モデルの回答品質や実サービスの性能を測定した結果ではありません。

実行:
Node.js v24.22.1 · darwin/arm64 · 2ケース

再現の手順

  1. 実行コードを保存する(.mjs)
  2. Node.js 20以上の環境で、保存したフォルダから次のコマンドを実行します。追加パッケージやAPIキーは不要です。
  3. 出力の各ケースを読み、入力を一つ変えて判断の違いを確かめてください。
node ai-evaluation-dataset.mjs

実際の入力と出力

{
  "development": [
    {
      "id": "q1",
      "sourceId": "document-A"
    },
    {
      "id": "q2",
      "sourceId": "document-B"
    }
  ],
  "cases": [
    {
      "name": "設問IDは違うが元資料が重複",
      "evaluation": [
        {
          "id": "q3",
          "sourceId": "document-A"
        }
      ],
      "expected": [
        "document-A"
      ],
      "actual": [
        "document-A"
      ],
      "pass": true
    },
    {
      "name": "元資料ごとに分離",
      "evaluation": [
        {
          "id": "q4",
          "sourceId": "document-C"
        }
      ],
      "expected": [],
      "actual": [],
      "pass": true
    }
  ]
}
実行したコードを読む
// Synthetic dataset split experiment; does not measure model accuracy.
export function sourceOverlap(development,evaluation) {
  const used=new Set(development.map(x=>x.sourceId));
  return [...new Set(evaluation.filter(x=>used.has(x.sourceId)).map(x=>x.sourceId))].sort();
}
export function run() {
  const development=[{id:'q1',sourceId:'document-A'},{id:'q2',sourceId:'document-B'}];
  const fixtures=[
    {name:'設問IDは違うが元資料が重複',evaluation:[{id:'q3',sourceId:'document-A'}],expected:['document-A']},
    {name:'元資料ごとに分離',evaluation:[{id:'q4',sourceId:'document-C'}],expected:[]},
  ];
  return {development,cases:fixtures.map(c=>{const actual=sourceOverlap(development,c.evaluation);return {...c,actual,pass:JSON.stringify(actual)===JSON.stringify(c.expected)};})};
}
if(process.argv[1]&&import.meta.url===new URL('file://'+process.argv[1]).href)console.log(JSON.stringify(run(),null,2));

コードのSHA-256:f1c17feeb19e41ffceae0c27727dee85e8f07af77fa99927268f0dff95d85c12

5実験の実行記録を保存する(JSON)

この検証で分かる範囲

sourceIdが正しいことを前提にした一致検査です。言い換えや近似重複の検出、正解ラベルの品質、評価の代表性、モデルの精度は測定していません。

確認課題と合格の目安

用途に対する入力を、通常、境界、資料不足、対象外に分類して評価集合の案を作ってください。

  • 集合の目的と適用範囲を説明できる。
  • 元資料の重複による漏れを防いでいる。
  • ラベルの曖昧さをモデルの誤りと区別できる。