SQuAD(Stanford Question Answering Dataset)は、Wikipedia の段落と質問を渡し、答えにあたる文字範囲を段落から抜き出させる機械読解の評価用データセットです。スタンフォード大学の Rajpurkar らが 2016年6月に arXiv:1606.05250 で公開しました。「squad ai」で探されることが多いものの、AI 製品やツールの名前ではありません。モデルの読解精度を測るための問題集で、JSON ファイルとして配布されています。
この記事では、公式配布の JSON を集計した設問数と無回答比率、ファイルの中身の構造、公式スコアラーで EM と F1 を出す手順、そして生成型の LLM を SQuAD で採点したときに起きることを、2026年10月12日に実行した結果で示します。
まとめ
SQuAD は生成ではなく抽出のデータセットです。答えは段落の中の連続した文字範囲で、文字列一致による自動採点が成り立ちます。版は 1.1 と 2.0 の 2 つで、2.0 は「段落に答えが無い設問」を足しました。
公式 JSON を数えると、学習用は 1.1 が 87,599 問、2.0 が 130,319 問。検証用は 1.1 が 10,570 問、2.0 が 11,873 問で、2.0 の検証用は半分の 5,945 問が無回答です。そのため 2.0 の検証用は、全問を空欄で出すだけで EM・F1 とも 50.07 になります。この 50 点を基準に読まないと、2.0 のスコアは過大に見えます。
採点は EM(完全一致)と F1。公式スコアラーは大文字小文字・句読点・英語の冠詞を落としてから比べますが、単語の分割は空白区切りなので、空白を含まない日本語の答えどうしでは設問単位の F1 が EM と同じ 0 か 1 になります。公式リーダーボードの掲載データは 2023年10月12日を最後に更新されておらず、新しい LLM を公式のテストスコアで並べることはできません。一方、自社の抽出型 QA や RAG の無回答判定を改修したときの回帰テスト用の固定データとしては今も役に立ちます。日本語なら JSQuAD が同じ形式です。
SQuADの定義と1.1・2.0の違い
原文から答えの範囲を抜き出す抽出型タスク
1 件のデータは、段落(context)、質問(question)、答え(answers)の組です。答えは文字列と、段落の先頭から数えた文字位置(answer_start)の両方を持ちます。モデルに求められるのは文章を書くことではなく、原文のどこからどこまでが答えかを指すことです。
正解が原文の部分文字列に固定されるので、人が出来を判定しなくても採点できます。2016年の論文では、当時のロジスティック回帰モデルが F1 51.0%、単純なベースラインが 20%、人間が 86.8% でした。この差を埋める競争の中で精度を押し上げたのが BERT などの Transformer 系事前学習モデルで、仕組みは Transformerとは?自己注意の仕組みとBERT・GPTの違いを実装目線で解説 にまとめています。抽出型 QA は今もエンコーダ型モデルの得意分野で、後継の ModernBERTとは?BERT後継エンコーダの特徴・base/large・日本語版と使い方 も同じ枠組みで使えます。
SQuAD 2.0が追加した5万問超の回答不能な設問
1.1 は全設問に答えがあるため、モデルは「答えが無い」と判断する必要がなく、常に段落のどこかの範囲を返せば済みました。正解と単語が重なれば部分点も入ります。段落に答えが無いと見抜く力は測れません。2018年の arXiv:1806.03822(ACL 2018)は、答えられそうに見えて段落に答えが無い質問 53,775 問をクラウドワーカーに作らせて追加しました。論文によれば、1.1 で F1 86% のモデルが 2.0 では 66% まで落ちています。
2.0 の無回答設問には plausible_answers という項目があり、誤答として選ばれやすい範囲が入っています。検証用の無回答 5,945 問はすべてこの項目を持ち、そのうち 5,930 問は中身が入っています(15 問は空の配列)。誤答分析にそのまま使えます。
公式JSONを集計した記事数・設問数・無回答比率
train・devの記事数と設問数
SQuAD explorer が配布する 4 つの JSON を全件走査した結果です。
| ファイル | 記事数 | 段落数 | 設問数 | 無回答 | サイズ |
|---|---|---|---|---|---|
| train-v1.1.json | 442 | 18,896 | 87,599 | 0 | 30.3MB |
| dev-v1.1.json | 48 | 2,067 | 10,570 | 0 | 4.9MB |
| train-v2.0.json | 442 | 19,035 | 130,319 | 43,498 | 42.1MB |
| dev-v2.0.json | 35 | 1,204 | 11,873 | 5,945 | 4.4MB |
テストセットは公開されていません。2.0 の論文の Table 2 では 1.1 のテスト用が 46 記事 9,533 問で、公開分の 442+48 記事と合わせた 536 記事が 2016年の論文の総記事数と一致します。
1.1から2.0へ引き継がれなかった設問
学習用の記事タイトルは 1.1 と 2.0 で完全に一致しますが、「1.1 に無回答設問を足しただけ」ではありません。段落は 139 件増えて 1 件消え、1.1 の学習用 87,599 問のうち 2.0 の回答可能設問に残るのは 86,821 問で、778 問が外れています。検証用の変化はもっと大きく、1.1 の 10,570 問のうち残るのは 5,928 問です。2.0 の論文の 4.1 節によれば、1 記事で 25 問以下しか書かなかった作業者の設問を既存の回答可能設問も含めて除き、さらに検証用とテスト用では無回答設問を集められなかった記事を外しました。検証用の記事が 48 から 35 に減ったのはこのためで、結果として回答可能と無回答がほぼ 1 対 1 になったと書かれています。1.1 と 2.0 の検証スコアを同じ母集団の数字として並べてはいけません。
trainとdevで33.4%対50.1%に開く無回答比率
学習用の無回答比率は 43,498 ÷ 130,319 で 33.4%、検証用は 5,945 ÷ 11,873 で 50.1% です。学習用は 442 記事のうち無回答を含むのが 285 記事なのに対し、検証用は 35 記事すべてが無回答を含みます。2.0 のモデルは確信度の閾値で「答える/無回答とする」を切り替えるのが一般的です。学習用と検証用で無回答の比率がこれだけ違うので、学習用で決めた閾値がそのまま通用する前提は置けません。閾値は検証用の予測で決めてください。
SQuADのデータ形式(JSONの階層とフィールド)
data・paragraphs・qasの3階層
公式 JSON は、記事(data)の中に段落(paragraphs)、段落の中に設問(qas)が入る 3 階層です。dev-v2.0.json の先頭記事「Normans」から、回答可能な設問と無回答の設問を 1 件ずつ抜き出すと次のとおりです(context は途中で、answers は重複する 4 件のうち 2 件に省略)。
{
"version": "v2.0",
"data": [{
"title": "Normans",
"paragraphs": [{
"context": "The Normans (Norman: Nourmands; French: Normands; Latin: Normanni) were the people who in the 10th and 11th centuries gave their name to Normandy, a region in France. ...",
"qas": [
{
"question": "In what country is Normandy located?",
"id": "56ddde6b9a695914005b9628",
"answers": [{"text": "France", "answer_start": 159}, {"text": "France", "answer_start": 159}],
"is_impossible": false
},
{
"plausible_answers": [{"text": "Normans", "answer_start": 4}],
"question": "Who gave their name to Normandy in the 1000's and 1100's",
"id": "5ad39d53604f3c001a3fe8d1",
"answers": [],
"is_impossible": true
}
]
}]
}]
}
answer_start は文字単位の位置です。2026年10月12日に公式 JSON の全回答(train-v1.1 の 87,599 件、train-v2.0 の 86,821 件、dev-v2.0 の 20,302 件)で、context をこの位置から切り出した文字列と text を突き合わせたところ、ずれは 0 件でした。前処理で context の空白を詰めたり正規化したりすると位置がずれるので、トークン化の前に位置を変換する処理を入れてください。
2.0で増えるis_impossibleとplausible_answers
| フィールド | 型 | 1.1 | 2.0 |
|---|---|---|---|
| title | 文字列 | あり | あり |
| context | 文字列 | あり | あり |
| question・id | 文字列 | あり | あり |
| answers(text・answer_start) | 配列 | あり | 無回答は空配列 |
| is_impossible | 真偽値 | なし | あり |
| plausible_answers | 配列 | なし | 無回答のみ |
回答可能な設問の正解は、学習用では 1 件だけですが、検証用では原則として複数の作業者が付けた複数件です。dev-v1.1 の正解件数は 3 件が 8,490 問で最も多く、5 件が 1,147 問、4 件が 759 問、2 件が 136 問、6 件が 35 問、1 件は 3 問でした。採点はこの複数の正解のうち最も点が高いものを採ります。同じ設問・同じ予測でも、正解 1 件と突き合わせた EM は複数件と突き合わせた EM 以下にしかならないので、学習中の自己採点と検証スコアを同じ物差しとして比べないでください。
入手先とライセンス
公式JSON・Hugging Face・TensorFlow Datasetsの違い
同じデータを 3 つの経路で入手できます。行数はどれも同じですが、形式と前処理が異なります。
| 経路 | 形式 | 2.0の容量 | 注意点 |
|---|---|---|---|
| SQuAD explorer | 入れ子のJSON | 42.1MB+4.4MB | 公式スコアラーが直接読める |
| Hugging Face | 平坦な行(Parquet) | 17.7MB | is_impossibleなし |
| TensorFlow Datasets | FeaturesDict | DL 44.34MiB | 3.0.0で19例を修正 |
Hugging Face の rajpurkar/squad_v2 は 1 行 1 設問の平坦な形で、id・title・context・question・answers の 5 列です。無回答は answers の text が空の配列で表されます。2026年10月12日時点の直近 30 日のダウンロードは rajpurkar/squad が 207,190 回、rajpurkar/squad_v2 が 44,343 回でした。
from datasets import load_dataset
squad2 = load_dataset("rajpurkar/squad_v2")
print(squad2["train"].num_rows, squad2["validation"].num_rows)
# 130319 11873
no_ans = squad2["validation"].filter(lambda r: len(r["answers"]["text"]) == 0)
print(no_ans.num_rows)
# 5945
TensorFlow Datasets の squad は 2.0 で is_impossible と plausible_answers を持ちます。版 3.0.0 で、context の空白を削った影響で答えの範囲がずれていた 19 例を直したと記載があります。古い版のキャッシュを使い回している環境は、この修正が入っているか確認してください。
CC BY-SA 4.0の継承条項
ライセンスは CC BY-SA 4.0 です。作成者の表示、ライセンスへのリンク、改変の有無の明示といった ライセンス本文の第3条 の表示条件を満たせば商用でも使えます。SQuAD を改変した派生データセットを配布する場合は、CC BY-SA 4.0、同じ要素を持つ後継版、または BY-SA 互換ライセンスのいずれかで公開しなければなりません。学習済みモデルの重みが派生物にあたるかは配布ページに書かれていないので、モデルを社外に配る予定があるなら事前に法務確認を通してください。SQuAD の設問は人手で作られたもので、同じ形式の自社データを作るときの品質設計は データラベリングとは?ラベル設計・一致率・自動化を実装目線で解説 を参照してください。
EMとF1の採点仕様
冠詞と句読点を落とす正規化処理
公式スコアラー evaluate-v2.0.py は、比較の前に予測と正解の両方を正規化します。小文字化、句読点の除去、英語の冠詞 a・an・the の除去、連続空白の圧縮の 4 段です。
import re
import string
def normalize_answer(s):
"""Lower text and remove punctuation, articles and extra whitespace."""
def remove_articles(text):
regex = re.compile(r'\b(a|an|the)\b', re.UNICODE)
return re.sub(regex, ' ', text)
def white_space_fix(text):
return ' '.join(text.split())
def remove_punc(text):
exclude = set(string.punctuation)
return ''.join(ch for ch in text if ch not in exclude)
def lower(text):
return text.lower()
return white_space_fix(remove_articles(remove_punc(lower(s))))
EM はこの正規化後の文字列が一致すれば 1、F1 は正規化後に空白で区切った単語の重なりから適合率と再現率を出した調和平均です。「The Amazon」と「amazon」はどちらの指標でも満点になります。
部分点が発生しない無回答設問の二値採点
無回答設問の正解は空文字列として扱われ、F1 の計算では正解か予測のどちらかが空なら、一致で 1、不一致で 0 を返します。単語の重なりによる部分点はありません。検証用の半分が無回答なので、閾値の当たり外れがそのままスコアの半分を動かします。2.0 で F1 が伸びないときは、読解より先に無回答の閾値を疑ってください。
公式スコアラーevaluate-v2.0.pyで採点する手順
予測ファイルの形式と実行コマンド
予測ファイルは、設問 id をキー、予測した答えの文字列を値にした 1 つの JSON オブジェクトです。無回答と判定した設問は空文字列にします。下の例は 2 問だけの抜粋で、実際には検証用の全 11,873 問の id を入れてください。欠けた id があると集計の途中で KeyError になります。スコアラーは公式サイトから入手でき、引数は検証用 JSON と予測ファイルの 2 つです。
{"56ddde6b9a695914005b9628": "France", "5ad39d53604f3c001a3fe8d1": ""}
pip install numpy
python evaluate-v2.0.py dev-v2.0.json predictions.json -o eval.json
スクリプトは先頭で numpy を読み込むため、グラフを出さない通常の採点でも numpy が無いと ModuleNotFoundError で止まります(Python 3.9.6 で確認)。出力の exact と f1 が全体、HasAns と NoAns が回答可能設問と無回答設問それぞれの内訳です。
全問を空欄で出すだけでEM 50.07になる検証セット
dev-v2.0.json の全 11,873 問に空文字列を返す予測ファイルを作って実行すると、結果は次のとおりでした(HasAns_f1 と NoAns_f1 は exact と同値のため省略)。
{
"exact": 50.07159100480081,
"f1": 50.07159100480081,
"total": 11873,
"HasAns_exact": 0.0,
"HasAns_total": 5928,
"NoAns_exact": 100.0,
"NoAns_total": 5945
}
何も読まずに 50 点が出ます。2.0 の検証スコアを報告された場合は、総合点ではなく HasAns と NoAns の内訳を見てください。総合 F1 が 60 台でも HasAns が低ければ、読解はほとんどできておらず無回答判定で点を取っているだけです。
na-prob-fileによる無回答閾値の探索
各設問について「答えが無い確率」を書いた JSON を -n(--na-prob-file)で渡すと、閾値を動かしたときの最良値 best_exact・best_f1 と、そのときの閾値が出力に加わります。閾値の既定は 1.0 で、確率がこれを超えた設問だけが無回答扱いになります。best_f1 と f1 の差が大きいほど、点を落としている原因は読解ではなく閾値の設定です。
生成型LLMの回答をSQuADで採点するときの注意
冗長な答えと言い換えで下がるF1
生成型の LLM は、段落の文字列をそのまま抜き出さずに文で答えがちです。公式スコアラーの関数で、dev-v1.1 の「Which NFL team represented the AFC at Super Bowl 50?」(正解 Denver Broncos)に対する答え方を変えて採点しました。
| 予測 | EM | F1 |
|---|---|---|
| Denver Broncos | 1 | 1.000 |
| The Denver Broncos won Super Bowl 50. | 0 | 0.500 |
| Broncos | 0 | 0.667 |
この例では、内容が正しくても文で答えただけで F1 が 0.500 に下がりました。LLM を SQuAD で測るなら、プロンプトで「段落中の語句をそのまま 1 つだけ出力し、答えが無ければ空で返す」と指定し、EM と F1 の両方を見てください。それでも言い換えは減点されるので、EM が低いことだけで読解力が低いと判断するのは誤りです。
Hugging Face evaluateのsquad_v2指標の入力形式
Python から採点するなら、Hugging Face evaluate の squad_v2 指標が公式スコアラーと同じ関数を内部で使っています。予測は id・prediction_text・no_answer_probability の 3 項目、参照は id と answers を渡します。
import evaluate
squad_v2 = evaluate.load("squad_v2")
preds = [{"id": "56ddde6b9a695914005b9628", "prediction_text": "France", "no_answer_probability": 0.0}]
refs = [{"id": "56ddde6b9a695914005b9628", "answers": {"text": ["France"], "answer_start": [159]}}]
print(squad_v2.compute(predictions=preds, references=refs))
no_answer_probability は閾値(既定 1.0)を超えたときだけ無回答扱いになるので、0.0 を入れておけば prediction_text の空かどうかで判定されます。なお evaluate の最新版は 2025年9月の 0.4.6 で、README は LLM の評価には後継の LightEval を勧めています。評価をパイプラインに組み込んで継続的に回す運用は LLMOpsとは?MLOpsとの違いとトレース・評価・コスト管理の実装を解説【2026年版】 で扱っています。
日本語の機械読解評価とJSQuAD
JSQuADの規模と構成
日本語で同じ形式の評価をするなら、ヤフーと早稲田大学の日本語言語理解ベンチマーク JGLUE の QA タスク JSQuAD を使います。SQuAD 1.1 準拠で無回答設問は無く、日本語 Wikipedia の 2021年11月1日時点のダンプから翻訳ではなく新規に作られました。JSON の形式は SQuAD と同じです。
2025年3月31日の v1.3 のファイルを数えると、学習用 62,697 問(710 記事)、検証用 4,442 問(59 記事)、テスト用 4,420 問(59 記事)でした。テスト用はリーダーボード無しで公開済みです。ライセンスは CC BY-SA 4.0。検証用の人手スコアは EM 0.871・F1 0.944 で、Waseda RoBERTa large(s512)が EM 0.918・F1 0.963 と人手を上回っています。
英語版スコアラーを日本語に当てると壊れる理由
公式スコアラーの句読点除去は Python の string.punctuation、つまり ASCII 記号だけが対象で、日本語の句点は残ります。さらに単語分割が空白区切りなので、空白を含まない日本語の答えは全体が 1 単語になり、正解と予測がともにそうであれば設問単位の F1 は部分点を返せず EM と同じ 0 か 1 になります(空白を含む答えなら部分点は出ます)。実際、正解「東京駅」に対する予測「東京駅。」も、「1998年4月1日」に対する「1998年4月1日に」も EM 0・F1 0 でした。JSQuAD は JGLUE 側の評価手順に従い、自前で採点するなら文字単位か形態素単位で分割してから F1 を計算してください。分割単位の選び方は トークナイザーとは?BPE・WordPiece・Unigramの違いと日本語での実装判断を解説【2026年版】 が参考になります。
リーダーボード更新停止後にSQuADを使う判断
人間を超えたまま2023年10月で止まった公式リーダーボード
2.0 の首位は RICOH_SRCB_DML の IE-Net(アンサンブル)で EM 90.939・F1 93.214、提出は 2021年6月5日です。人間は EM 86.831・F1 89.452 なので、上位は 4 ポイント前後人間を上回っています。掲載データの out-v2.0.json は 264 件を収め、最も新しい提出が 2023年9月29日、ファイルの更新は 2023年10月12日で、リポジトリの最終コミットも同じ日です。公式ページに提出の案内は残っていますが、それ以降の掲載は 3 年間ありません。受付の終了は告知されていないものの、提出しても掲載される前提で計画を立てるのは避けてください。
2026年に使ってよい場面と使うべきでない場面
新しい LLM どうしの性能比較には使わないでください。公開されている検証用でなら条件を揃えたローカル比較はできますが、非公開のテストセットでの公式スコアは 2023年9月を最後に増えていないので、他社の数字と同じ条件で並べる手段がありません。上位のスコアは人間を超えたところで頭打ちになっています。加えて、CC BY-SA 4.0 で Web 上に複製が大量にあるため、現行の LLM が事前学習でこのデータを見ている可能性を否定できません。高いスコアが読解力なのか暗記なのかを切り分けられない以上、「SQuAD で高スコア」は 2026年時点の選定材料になりません。
固定の回帰テストとしては今も使えます。自社の抽出型 QA の読解モデルや無回答判定を改修したときに、同じ 11,873 問で HasAns と NoAns の増減を見る使い方です。見るのは絶対値でなく差分なので、改修で壊れていないかの確認には十分です。ただし上限に近いモデルでは改善の幅が小さく出るので、改善の検出には向きません。リランカのように段落の選び方を変える部品は、SQuAD が段落を最初から渡す以上そのままでは評価できず、別の評価設計が必要です。
もう 1 つは無回答判定の検証です。RAG で「参照した文書に答えが書かれていなければ答えない」挙動は、2.0 の無回答設問と同じ構造をしています。ただし SQuAD は答えを含む段落を最初から渡す前提なので、検索工程の精度は測れません。工程の分け方は RAGパイプラインとは?取り込み系と推論系に分ける工程設計と再索引の実装判断 を、社内文書に答えが無いときに黙る対話システムを業務に組み込む場合は AIチャットボット開発 の支援内容も参照してください。
よくある質問
SQuADの読み方は何ですか?
公式のカナ表記はありません。由来の英単語 squad(分隊・班)に沿って、日本語では「スクワッド」「スクアッド」の両方が使われます。文書では初出で Stanford Question Answering Dataset と綴り、以降を SQuAD と略すのが無難です。
SQuAD 1.1と2.0はどちらを使えばよいですか?
段落に答えが無いことを見抜く力まで測るなら 2.0、抜き出しの精度だけを見るなら 1.1 です。学習用は 1.1 の 99.1%(86,821 問)が 2.0 に残るので、2.0 から無回答を除けば 1.1 にほぼ相当します。検証用は 1.1 の 10,570 問のうち 5,928 問しか残らないため、両者の検証スコアは比べられません。
SQuADはRAGの評価に使えますか?
読解工程と無回答判定の評価には使えますが、検索工程は測れません。答えを含む段落が最初から与えられる前提のデータだからです。検索まで含めて測るなら、自社文書から検索評価用のデータを別に作る必要があります。
SQuADのライセンスで商用利用はできますか?
CC BY-SA 4.0 なので、作成者やライセンスの表示などの条件を満たせば商用利用できます。改変した派生データセットを配布する場合は、CC BY-SA 4.0、同じ要素を持つ後継版、または BY-SA 互換ライセンスでの公開が必要です。社内で評価に使うだけなら継承条項の問題は生じません。
公式リーダーボードに今からスコアを掲載できますか?
受付の終了は告知されておらず、可否は確認できません。確かなのは、掲載データが 2023年10月12日を最後に更新されておらず、最も新しい掲載が 2023年9月29日の提出だという点です。現実的には、公式スコアラーをローカルで実行して検証用のスコアを出し、社内の比較指標として使います。テストセットは非公開なので、その数字はリーダーボードのテストスコアとは直接比べられません。