ClaudeのLLM採点を人手ラベルと突き合わせて一致率を測る — κで校正する手順
Claudeに採点させる前に、人手ラベル100件と突き合わせてCohenのκを測ります。採点基準を変えるたびに測り直すスクリプトと、κの読み方、100件の限界までまとめます。
LLMに採点させたスコアは、人が付けたラベルと突き合わせるまで、数字の形をした意見にすぎません。校正の手順は、人手で付けたラベルを100件ほど用意し、採点者の出力と並べて一致率を出すことです。一致率はCohenのκ(偶然の一致を除いた一致度)で見ます。採点基準の文面を直したら、その都度同じ測定をやり直します。
この記事は、Claudeを採点者にした評価パイプラインを持っている人、またはこれから作る人に向けています。ラベルの付け方、採点者のコード、κと信頼区間を出すスクリプト、結果の読み方を順に置きます。
「採点者を信用する」とは何を測ることか
Claudeの評価ガイドは、採点方法の選び方を3段で示しています。コードによる採点は最も速く確実で、人による採点は柔軟で質が高いものの遅くて高価。LLMによる採点は速く柔軟で、複雑な判断に向くとされ、そのうえで「まず信頼性をテストし、それからスケールさせる」と書かれています。
ここで言う信頼性のテストが、人手との突き合わせです。Anthropicのエンジニアリング記事も、LLM採点者は人間の専門家と綿密に校正し、人の採点とモデルの採点のずれが小さいという確信を得るよう求めています。採点者の類型そのものはAIエージェントのEval設計で整理しているので、ここでは校正の手を動かす部分だけを扱います。
測りたいものは1つです。同じ回答を人とClaudeに採点させたとき、ラベルがどれだけ揃うか。揃っていなければ、そのLLM採点のスコアで「モデルAがBより良い」と言っても、差の中身は採点者のクセかもしれません。
用意するもの
- 採点対象の回答100件前後(本番の入力分布から抜いたもの)
- 各回答の人手ラベル(correct / incorrectの2値)
- 採点基準(ルーブリック)の文面
- Anthropic Pythonパッケージ
anthropicと、scikit-learn、numpy
100件は、手作業で付けきれて、κの幅がぎりぎり読める規模として置いた数です(評価ガイドに件数の目安はありません)。幅については後半の「100件で何が言えるか」で計算します。
手順1: 人手ラベルを先に付ける
人手ラベルは、Claudeの採点を見る前に付けます。先に採点結果を見ると、人のラベルが採点者に引きずられ、一致率が実力より高く出ます。
次の3点を決めてから付け始めます。
- ラベルはcorrect / incorrectの2値にする。5段階評価は、段の境目で人同士が割れやすく、校正の最初には重い
- 回答の順番をシャッフルして渡す。モデル名や生成条件を隠す
- ラベルを付ける人は、採点基準と同じ文面を読む。人に渡す基準とClaudeに渡す基準が違うと、一致率の低さが基準の差なのか採点者の差なのか分けられない
可能なら2人が別々に付け、割れた回答だけ協議して決めます。2人で割れる回答の割合は、そのまま採点基準の曖昧さの目安になります。その割合が高いなら、Claudeを調べる前に基準の書き直しが先です。
ラベルはこの形のCSVにします。
id,human_label
0001,correct
0002,incorrect
0003,correct回答本文は別のJSONLに id と question と output を持たせて置きます。
手順2: 採点者を組む
採点者は、基準と回答を渡して <result> タグの中に判定だけを出させる形にします。Claudeの評価ガイドが挙げる採点のコツは3つあり、そのまま設計に使えます。
- 詳細で明確なルーブリックを持つ。ガイドの例は「回答は最初の文で必ず『Acme Inc.』に触れる。触れていなければ自動的に『incorrect』とする」という書き方
- 出力を経験的・具体的に絞る。「correctかincorrectのどちらかだけ出す」「1〜5で採点する」のように、あとで集計できる形にする
- 推論を促す。採点役のモデルで思考をオンにし、判定を出す前に考えさせる。複雑な判断を要するタスクで性能が上がるとされています
もう1つ、Anthropicのエンジニアリング記事には、情報が足りないときの逃げ道を用意する工夫が出てきます。判断材料がないときに「Unknown」を返してよいと指示すれば、モデルが無理に埋めて幻覚を起こすのを避けられます。校正の側から見ると、unknown の件数は「基準の書き方が足りない回答」を数える目印にもなります。
import json
import re
import anthropic
client = anthropic.Anthropic()
GRADER_MODEL = "claude-opus-5-5" # 採点に使うモデル。評価対象とは分ける
PROMPT = """次のルーブリックに従って回答を採点してください。
<rubric>{rubric}</rubric>
<question>{question}</question>
<answer>{answer}</answer>
判断に必要な情報が足りない場合は unknown としてください。
<result> タグの中に correct、incorrect、unknown のいずれか1語だけを出力してください。"""
def grade(rubric: str, question: str, answer: str) -> str:
message = client.messages.create(
model=GRADER_MODEL,
max_tokens=4096,
thinking={"type": "adaptive"},
messages=[{
"role": "user",
"content": PROMPT.format(
rubric=rubric, question=question, answer=answer
),
}],
)
text = "".join(b.text for b in message.content if b.type == "text")
m = re.search(r"<result>\s*(correct|incorrect|unknown)\s*</result>", text)
return m.group(1) if m else "unparsed"thinking={"type": "adaptive"} は、Claude 4.7以降のモデルが受け付ける思考の指定です。4.7以降では type: "enabled" と budget_tokens の組が400エラーになります。古いモデルを採点役にする場合は、そのモデルの思考設定に合わせてください。
正規表現で拾えなかった出力は unparsed として残します。ここを incorrect に丸めると、書式崩れが採点者の判断として一致率に混ざります。
評価ガイドのサンプルコードは、"<result>correct</result>" in grader_response.lower() で正誤を決め、それ以外は incorrect にしています。短いサンプルとしては十分でも、校正の測定には向きません。unknown や書式崩れが「間違い」に吸収されて、その件数が見えなくなるためです。
手順3: κと信頼区間を出す
採点者を全100件に流し、人手ラベルと並べます。次のコードは、手順2のコードと同じ calibrate.py に続けて置きます(grade を呼ぶため)。
import argparse
import json
import numpy as np
from sklearn.metrics import cohen_kappa_score, confusion_matrix
def load_pairs(path_answers, path_labels):
answers = {}
with open(path_answers, encoding="utf-8") as f:
for line in f:
row = json.loads(line)
answers[row["id"]] = row
labels = {}
with open(path_labels, encoding="utf-8") as f:
next(f) # ヘッダー行
for line in f:
i, label = line.strip().split(",")
labels[i] = label
ids = sorted(labels)
return ids, answers, labels
def calibrate(rubric, path_answers, path_labels, seed=0):
ids, answers, labels = load_pairs(path_answers, path_labels)
human = [labels[i] for i in ids]
model = [
grade(rubric, answers[i]["question"], answers[i]["output"])
for i in ids
]
kappa = cohen_kappa_score(human, model)
# ブートストラップで95%区間を出す
rng = np.random.default_rng(seed)
n = len(ids)
boots = []
for _ in range(2000):
idx = rng.integers(0, n, n)
h = [human[j] for j in idx]
m = [model[j] for j in idx]
if len(set(h)) < 2 and len(set(m)) < 2:
continue # 全件同じラベルの標本ではκが定まらない
boots.append(cohen_kappa_score(h, m))
lo, hi = np.percentile(boots, [2.5, 97.5])
agree = sum(h == m for h, m in zip(human, model)) / n
print(f"単純一致率: {agree:.2f}")
print(f"Cohenのκ: {kappa:.2f} (95%区間 {lo:.2f}〜{hi:.2f})")
print("unknown:", model.count("unknown"), "/ unparsed:", model.count("unparsed"))
print(confusion_matrix(
human, model, labels=["correct", "incorrect", "unknown", "unparsed"]
))
return human, model
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--rubric", required=True)
parser.add_argument("--answers", required=True)
parser.add_argument("--labels", required=True)
args = parser.parse_args()
with open(args.rubric, encoding="utf-8") as f:
rubric = f.read()
calibrate(rubric, args.answers, args.labels)
if __name__ == "__main__":
main()--rubric にはルーブリックの文面を入れたテキストファイルを渡します。実行はこう呼びます。
python calibrate.py --rubric rubrics/v1.txt \
--answers data/answers.jsonl --labels data/human_labels.csv出力は、単純一致率、κとその区間、unknown と unparsed の件数、混同行列の4点です。混同行列の行が人手、列が採点者です。correct 行の incorrect 列が大きければ、採点者は厳しすぎ。incorrect 行の correct 列が大きければ、甘すぎ。この向きの偏りは、κ1つの数字では見えません。
手順4: κの読み方 — 一致率が高いのにκが低いとき
単純一致率だけで判断すると、失敗する場面があります。正解側に偏った評価セットです。次の2つを並べると、違いが分かります。計算は κ = (po − pe) / (1 − pe) で、po が単純一致率、pe が偶然に揃う確率です。
| ケース | 単純一致率 | 偶然の一致 | κ |
|---|---|---|---|
| 正誤が半々の100件 | 単純一致率0.90 | 偶然の一致0.50 | κ0.80 |
| 9割がcorrectの100件 | 単純一致率0.90 | 偶然の一致0.82 | κ0.44 |
どちらも90件で揃っていますが、後者は「人と無関係に9割の確率でcorrectと答える採点者」でも82%揃います。κはその分を引くので、同じ90%でも評価が大きく変わります。評価セットの正誤比が偏っているなら、κとあわせて混同行列を必ず見てください。偏りが強いときは、少数側(incorrect)の件数を増やしてラベルを付け直すと、測定が安定します。
κをどの値から「信用できる」とみなすかについて、Claudeの評価ガイドは合格ラインを示していません。一般的な目安の表は教科書にありますが、評価の目的で必要な水準は変わります。測定を始める前に「この用途ではκが0.7を下回ったら採点者を使わない」のように、自分で数字を決めておくと、結果を見たあとで基準を甘くする動きを防げます。
手順5: 採点基準を変えるたびに測り直す
校正は1回で終わりません。採点基準の文面を変えれば、採点者の挙動が変わるからです。ルーブリックをファイルにして版を付け、変えるたびに同じスクリプトを回します。
rubrics/
v1.txt 最初の基準
v2.txt 「Acme Inc.」の言及を必須に追加
v3.txt 部分的に正しい回答の扱いを明記結果は版ごとに1行で残します。
v1 κ=0.58 (0.41〜0.73) unknown=9 甘い側に偏り
v2 κ=0.66 (0.50〜0.80) unknown=4
v3 κ=0.74 (0.60〜0.86) unknown=2上の数値は、表の見方を示す仮の例です。実測値ではありません。
ここで1つ落とし穴があります。同じ100件で基準を何度も直すと、その100件に合わせ込んだ基準になります。κは上がっても、新しい回答で同じ水準が出る保証はありません。対策は、人手ラベルを最初から2つに分けておくことです。
- 調整用(60件): 基準を直しながら何度でも回す
- 確認用(40件): 基準が固まったあとに1回だけ回す
この分け方は、機械学習の検証データとテストデータの考え方を借りた設計です。確認用でκが大きく落ちたら、調整用に合わせすぎたサインです。
100件で何が言えるか
100件の測定は、思ったよりばらつきます。上のブートストラップの区間がその目安ですが、おおまかな見積もりは手計算でもできます。κの標準誤差は、おおよそ √(po(1−po) / (n(1−pe)²)) です。
- 表の1行目(po=0.90、pe=0.50、n=100): 標準誤差0.06で、95%区間はおよそ±0.12。κ=0.80でも、真の値は0.68〜0.92のどこかにあります
- 表の2行目(po=0.90、pe=0.82、n=100): 標準誤差0.17で、95%区間はおよそ±0.33。κ=0.44と出ても、0.1から0.8までありえます
どちらも上の式にあてはめた概算です。偏りの強い評価セットほど、同じ100件でも区間が広がります。区間の幅が判断に響くときは、件数を増やすか、少数側のラベルを増やします。差を誤差込みで読む考え方はモデル評価の統計的手法にまとめています。
校正がうまくいかないときの切り分け
κが上がらないとき、原因は大きく3つに分かれます。
κが上がらないときの切り分け
- Q人同士のラベルが割れていますか?答えがいいえのとき答えがはい
採点基準そのものが曖昧です。割れた回答を読み、どちらの判定でも通る書き方を基準に足します。Claudeを調べるのはその後です。
- Q混同行列は片側に偏っていますか?答えがいいえのとき答えがはい
甘い側か厳しい側かに偏っているなら、基準に境目の例を足します。「この回答はincorrect」と理由つきで書いた例が効きます。
- Qunknown や unparsed が多いですか?答えがいいえのとき答えがはい
情報不足か書式崩れです。回答に添える文脈を増やすか、出力形式の指示を短く言い直します。
それでも揃わない回答
人間も迷う回答です。評価ガイドが、人でも合意が難しい曖昧なテストケースを「エッジケース」の1つに挙げています。そうした回答は、集計から外すか、別枠で扱うのが現実的です。
採点者の誤りを拾うには、数字を見るだけでは足りません。Anthropicの記事は、採点が働いているかは多数の試行の記録と採点結果を読まないと分からないと述べています。タスクが失敗したとき、モデルの本当の間違いなのか、採点者が正しい解答を落としたのかは、記録を読んで初めて判別できます。採点者と人がずれた回答を十数件選び、ラベルだけでなく採点者の推論も読んでください。
採点役と評価対象のモデルを同じにしてよいか
評価対象と採点役を同じモデルにすると、自分の出力に甘くなる偏りが入る、という懸念があります。ただ、その大きさは用途と基準しだいです。この記事の手順で測れば、自分の評価セットでの偏りは数字で確かめられます。評価対象のモデルと採点役を入れ替えて、κと混同行列がどう動くかを見る方法があります。
運用に組み込む
最後に、日々の運用に落とす形を挙げます。
- ルーブリックと人手ラベルをリポジトリに置き、基準を変えるPRでは
calibrateの結果を貼る - 採点役のモデルを入れ替えるときも、同じ人手ラベルでκを測り直す
- 評価対象の入力分布が変わったら、人手ラベルを数十件足す
- 評価の自動化をClaude Code上で回す場合は、DeepEvalプラグインでの評価ループのように、評価の実行を定型にしておくと測り直しが苦になりません
大量の判定を機械に任せる運用では、人手との一致を測る節目が必ず要ります。バッチAPIで論文を一次スクリーニングする運用での同じ測り方は、Claude Batch APIで論文を一次スクリーニングするで扱っています。そちらは「見落とし」を軸にした例です。学習データのラベル誤りを洗い出す場面での使い方は、Claudeとcleanlabでラベルの誤りを洗い出し、再確認の順番を付けるで扱っています。
まとめ
採点者のスコアを信じてよいかは、人手ラベルとの一致で決まります。100件のラベルを先に付け、Cohenのκと区間を出し、基準を変えるたびに測り直す。この3点が骨格です。
単純一致率が高くても、正誤が偏ったセットではκが低く出ます。混同行列で、甘さか厳しさかの向きを確かめてください。調整用と確認用にラベルを分けておけば、基準の合わせ込みにも気づけます。100件のκには広い区間が付くことも、数字の読み方に織り込む必要があります。
参照した一次ソース
この記事の記述は、次の一次ソースと照合しています。更新時に参照先が変わった場合は一覧も更新します。