アンケートの自由回答や問い合わせ文を AI に分類させて、その件数や割合をレポートに載せたい方向けの記事です。正解が分かっている公開データ 200 件で AI の分類を採点し、「1 件ごとにどれだけ当たったか」と「集計した割合がどれだけずれたか」を検算しました。読み終わると、自分のデータでも同じ検算の仕組みを作れるようになります。
この記事で分かること
- AI の分類が正解と何 % 一致したか(200 件で 97.0%)
- 1 件ごとに外れても、集計した割合はどれくらいずれるのか(全体で +1.0 ポイント)
- どんな文章で外れやすかったか(評価点が中間寄りの、長所と短所が両方書かれたレビュー)
- 正解ラベルが無い自分の日本語データで、同じ検算をする手順
ざっくり言うと:1 件ごとの正解率と、集計した割合のずれは別の数字
AI に文章を分類させたとき、確かめるべき数字は 2 つあります。1 つは 正解率(1 件ずつ見て、AI の答えが正解と一致した割合)です。もう 1 つは 割合のずれ(AI の答えで集計した割合から、正解で集計した割合を引いた差)です。
この 2 つは同じではありません。今回の 200 件では AI が 6 件外しましたが、外れ方が「否定を肯定と誤る」4 件と「肯定を否定と誤る」2 件に分かれました。逆向きの誤りが打ち消し合ったので、集計した肯定の割合は 2 件分、つまり 1.0 ポイントしかずれませんでした。
| 確かめる数字 | 何に効くか | 今回の値 |
|---|---|---|
| 正解率 | 1 件ずつの判定を使う場面(例: 否定の声だけを担当者に回す) | 97.0%(194 / 200) |
| 割合のずれ | 集計した割合をレポートに載せる場面 | +1.0 ポイント(正解 49.0%、AI 50.0%) |
レポートに「肯定的な声は 50%」と載せるなら、後者のずれが大事です。ただし、打ち消し合いは偶然にも左右されます。仮に 6 件すべてが同じ向きの誤りだったら、ずれは 3.0 ポイントになっていた計算です(筆者の仮定計算)。
使うデータ:正解ラベル付きの公開レビューと、200 件の決定的な抽出
なぜ英語の映画レビューなのか
AI の分類を採点するには、正解ラベル(人やルールで付けた「本当の答え」)が付いたデータが必要です。BigQuery の 一般公開データセット(Google が保存費用を負担し、誰でもクエリできるデータ)には、正解ラベル付きの日本語テキストが見つかりませんでした。そこで、読者が同じ結果を出せることを優先し、英語の映画レビューを使いました。
使ったのは bigquery-public-data.imdb.reviews です。このデータは、Maas らの論文「Learning Word Vectors for Sentiment Analysis」(ACL 2011)に由来するデータとして引用されています。一般公開データセットは、クエリの処理量にだけ料金がかかり、毎月 1 TB まで無料です(Google Cloud:BigQuery の一般公開データセット)。
テーブルの中身
主な列は、review(レビュー本文)、label(Positive / Negative / Unsupervised)、reviewer_rating(書いた人の評価点)、split(train / test)、movie_id です。調査担当が bq show --schema と集計クエリで確かめた件数は次のとおりです(2026-11-07 実行)。
| label | 件数 | 評価点の範囲 |
|---|---|---|
| Negative | 25,000 件 | 1〜4 |
| Positive | 25,000 件 | 7〜10 |
| Unsupervised | 50,000 件 | なし |
評価点 5 と 6 のレビューはありません。つまり、このデータは「はっきり肯定」と「はっきり否定」だけで作られています。実際のアンケートには、どちらとも言えない声が混ざる点が大きな違いです。
200 件を決まった手順で抜く
ラベルの無い Unsupervised を除き、FARM_FINGERPRINT(文字列から決まった整数を作る BigQuery の関数)の値の順に並べて、先頭 200 件を取りました。この関数は、同じ入力なら実行のたびに同じ値を返すと公式ドキュメントに書かれています。そのため、誰が何回実行しても同じ 200 件になります(Google Cloud:ハッシュ関数)。
-- 正解ラベル付きのレビューから、決まった 200 件を取り出す
SELECT
ROW_NUMBER() OVER (ORDER BY FARM_FINGERPRINT(CONCAT(movie_id, review))) AS id,
label,
reviewer_rating,
review
FROM `bigquery-public-data.imdb.reviews`
WHERE label IN ('Positive', 'Negative')
ORDER BY FARM_FINGERPRINT(CONCAT(movie_id, review))
LIMIT 200;
抜き出した 200 件は、Negative が 102 件、Positive が 98 件でした。本文は合計 284,377 文字(1 件平均 1,422 文字、最長 7,984 文字)です。
レシピ:データ → 質問 → AI の答え → 検算
検算の流れは図 1 のとおりです。ポイントは、正解ラベルを AI に見せず、AI の答えとは別の表として持っておくことです。
質問(プロンプト)
今回の実行では、調査担当の AI(Claude Sonnet 5.5)が、正解ラベルと評価点を見せない状態でレビュー本文だけを 40 件ずつ読みました。指示は「レビュー本文だけを見て、Positive か Negative の二択で答える」というもので、答えは「ID と P/N」の形で保存しています。
ただし、この調査担当の AI は、正解ラベル付きの 200 件を抽出した担当と同じです。ラベルが本当に見えていなかったかを後から確かめる記録はありません。この点は「英語データで試した限界」の表にも書きました。
自分で同じ実験をする場合は、API などで 20 件ずつ渡す次の形を使うと、答えを表に戻しやすくなります。これは筆者が再現用に整えた文面で、今回の実行で使った文面そのものではありません。
次の映画レビューを 1 件ずつ読み、書き手がその映画を肯定しているか否定しているかを判定してください。
答えは Positive か Negative のどちらか 1 つだけにしてください。
出力は 1 行に 1 件、「ID 半角スペース P または N」の形だけにし、説明は書かないでください。
[001] (レビュー本文)
[002] (レビュー本文)
...
[020] (レビュー本文)
AI の答え
AI の答えは「001 P」「002 N」のような 200 行のテキストになります。これを ai_answers という表(列は id と answer)として BigQuery に読み込めば、正解と突き合わせられます。今回の答えは、検算 3 の表に載せた外れた 6 件以外の 194 件が、すべて正解と一致しました。
なお、この記事の SQL は答えを BigQuery に読み込んだ場合の形です。今回の数字は、保存したファイル同士を突き合わせて出しました。
labels の id は ROW_NUMBER が返す整数(INT64)です。一方、ai_answers の id を「001」のような文字列のまま読み込むと、型が違うので JOIN でエラーになります。そのため、下の SQL では CAST(a.id AS INT64) で整数に直してからつないでいます。
検算 1:正解率と混同行列
正解と AI の答えを ID でつなぎ、混同行列(正解と AI の答えの組み合わせごとに件数を数えた表)を作ります。正解ラベルは抽出クエリの結果を labels という表にしておきます。
-- 混同行列: 正解 × AI の答え の件数
SELECT
l.label AS true_label,
a.answer AS ai_answer,
COUNT(*) AS n
FROM labels AS l
JOIN ai_answers AS a ON l.id = CAST(a.id AS INT64)
GROUP BY true_label, ai_answer
ORDER BY true_label, ai_answer;
-- 正解率
SELECT
COUNTIF(SUBSTR(l.label, 1, 1) = a.answer) AS correct,
COUNT(*) AS total,
ROUND(100 * COUNTIF(SUBSTR(l.label, 1, 1) = a.answer) / COUNT(*), 1) AS accuracy_pct
FROM labels AS l
JOIN ai_answers AS a ON l.id = CAST(a.id AS INT64);
調査担当が Python で、筆者が node で、保存したファイルを別々に数え直しました。どちらも次の表と同じ件数になりました。
| 正解 \ AI の答え | AI: Positive | AI: Negative | 合計 |
|---|---|---|---|
| 正解 Positive | 96(98.0%) | 2(2.0%、誤り) | 98 |
| 正解 Negative | 4(3.9%、誤り) | 98(96.1%) | 102 |
| 合計 | 100 | 100 | 200 |
図 2 のとおり、正解 Positive は 98.0%、正解 Negative は 96.1% を当てています(筆者が混同行列から計算)。正解率は (96 + 98) / 200 = 97.0% です。
否定のレビューを肯定と誤る向きの方が、少しだけ多く出ました。肯定の割合を集計すると、この偏りの分だけ上にずれます。
200 件でどこまで言えるか
200 件は統計的には小さな標本です。正解率 97.0% について、Wilson の 95% 区間(同じ実験を何度も繰り返したときに、本当の正解率が入ると考えられる幅の計算方法)を筆者が計算すると、93.6%〜98.6% でした。「97% ちょうど」ではなく「9 割台半ば以上」くらいに受け止めるのが安全です。
検算 2:集計した肯定の割合は何ポイントずれたか
次に、レポートに載せる数字そのものを比べます。AI の答えで数えた Positive の割合から、正解で数えた Positive の割合を引きます。
-- 割合のずれ(AI の集計 − 正解の集計)を、全体と評価点の帯ごとに出す
SELECT
CASE
WHEN l.reviewer_rating IN (3, 4, 7, 8) THEN '中間寄り'
ELSE '両端寄り'
END AS band,
COUNT(*) AS n,
ROUND(100 * COUNTIF(l.label = 'Positive') / COUNT(*), 1) AS true_pos_pct,
ROUND(100 * COUNTIF(a.answer = 'P') / COUNT(*), 1) AS ai_pos_pct,
ROUND(100 * (COUNTIF(a.answer = 'P') - COUNTIF(l.label = 'Positive')) / COUNT(*), 1) AS gap_pt
FROM labels AS l
JOIN ai_answers AS a ON l.id = CAST(a.id AS INT64)
GROUP BY ROLLUP(band); -- band が NULL の行が 200 件全体の合計
結果は次の表と図 3 のとおりです(筆者が保存済みの答えから計算)。
| 範囲 | 件数 | 正解の Positive | AI の Positive | 正解の割合 | AI の割合 | ずれ |
|---|---|---|---|---|---|---|
| 200 件全体 | 200 | 98 件 | 100 件 | 49.0% | 50.0% | +1.0 ポイント |
| 中間寄り(3・4・7・8 点) | 85 | 40 件 | 43 件 | 47.1% | 50.6% | +3.5 ポイント |
| 両端寄り(1・2・9・10 点) | 115 | 58 件 | 57 件 | 50.4% | 49.6% | -0.9 ポイント |
全体のずれは 1.0 ポイントでしたが、中間寄りの帯だけで集計すると 3.5 ポイントに広がりました。中間寄りの帯では、誤り 5 件のうち 4 件が「否定を肯定と誤る」向きで、打ち消し合いが起きにくかったためです。
つまり、全体のずれが小さくても、細かく分けた集計ではずれが大きくなりうるのです。「年代別」「商品別」のように分けて割合を出すときは、分けた単位ごとに検算する必要があります。
検算 3:評価点が中間に近いレビューほど外れるか
評価点ごとの正解率は、次の表と図 4 のとおりです。
| 評価点 | 件数 | 正解 | 正解率 |
|---|---|---|---|
| 1 | 41 | 41 | 100.0% |
| 2 | 16 | 16 | 100.0% |
| 3 | 23 | 22 | 95.7% |
| 4 | 22 | 19 | 86.4% |
| 7 | 24 | 23 | 95.8% |
| 8 | 16 | 16 | 100.0% |
| 9 | 17 | 17 | 100.0% |
| 10 | 41 | 40 | 97.6% |
件数を足すと 200 件、正解を足すと 194 件で、検算 1 の数字と一致します。帯でまとめると、中間寄り(3・4・7・8 点)は 85 件中 80 件で 94.1%、両端寄り(1・2・9・10 点)は 115 件中 114 件で 99.1% でした。
外れた 6 件の内訳は次のとおりです。調査担当が本文を読んだところ、どれも長所と短所が両方書かれた文章か、皮肉を含む文章でした。
| レビュー ID | 正解 | 評価点 | AI の答え |
|---|---|---|---|
| 037 | Negative | 4 | Positive |
| 045 | Negative | 4 | Positive |
| 101 | Negative | 4 | Positive |
| 103 | Negative | 3 | Positive |
| 119 | Positive | 10 | Negative |
| 162 | Positive | 7 | Negative |
ただし、4 点の 86.4% は 22 件中 3 件の誤りです。Wilson の 95% 区間を筆者が計算すると 66.7%〜95.3% と広く、偶然のぶれの可能性が残ります。
中間寄りの帯(87.0%〜97.5%)と両端寄りの帯(95.2%〜99.8%)の区間も重なっています。「中間寄りで外れやすい傾向が見えた」までは言えますが、200 件で確定はできません。
費用の目安:200 件の分類はいくらかかるか
今回は API 経由で実行していないため、実際の トークン(AI が文章を処理する単位)数は測っていません。英語 1 トークン約 4 文字の仮定で概算すると、入力は約 71,000、出力は約 1,000 トークンです。これを 2026-11-07 時点の Anthropic の料金表 の単価(100,000 トークン以下のプロンプト)に当てはめました。
| モデル | 入力の単価(100 万トークンあたり) | 出力の単価 | 200 件の概算 |
|---|---|---|---|
| Claude Haiku 5.5 | 0.10 ドル | 0.50 ドル | 約 0.008 ドル |
| Claude Sonnet 5.5 | 2 ドル | 10 ドル | 約 0.15 ドル |
| Claude Opus 5.5 | 4 ドル | 20 ドル | 約 0.30 ドル |
料金表では、Haiku 5.5 は分類や抽出のような大量の処理向けとされています。ただし今回の 97.0% は Sonnet 5.5 の結果で、Haiku 5.5 で同じ正解率になるかは確かめていません。安いモデルに変えるときこそ、同じ検算をし直す必要があります。
自分の日本語データに移す手順:人がラベルを付ける 100 件の作り方
自分のアンケートや問い合わせには正解ラベルがありません。そこで、一部だけ人がラベルを付けて「正解の表」を作り、上の検算をそのまま当てはめます。
- 分類の選択肢と、その定義を 1 行ずつ書き出す(例: 「肯定 = 商品やサービスを評価する声」)
- FARM_FINGERPRINT の順で、全体から 100 件を決まった手順で抜く
- AI の答えを見る前に、人が 100 件にラベルを付け、
labels表にする - 迷った回答には「迷った」の印を付け、どちらで迷ったかをメモする
- 同じ 100 件を AI に分類させ、答えを
ai_answers表にする - 検算 1〜3 の SQL で、正解率・混同行列・割合のずれを出す
- レポートで分けて集計する単位(年代別など)ごとに、ずれを確かめる
人がラベルを付けるのを AI の答えより先にするのは、AI の答えを見てから付けると、人の判断が AI に引っ張られやすいと考えられるためです。また、100 件では 1 件の誤りが 1 ポイントに当たるので、細かく分けた単位の結果は幅をもって読んでください。
つまずきやすい点
AI が「どちらでもない」と答えた件の扱い
今回は二択で答えさせたので、「どちらでもない」は出ていません。実際のアンケートでは、肯定とも否定とも言えない声が混ざります。二択を強制すると、そうした声が無理にどちらかへ入り、割合のずれの原因になると考えられます。
選択肢に「判断できない」を加える場合は、その件数と割合を別に数えてレポートにも書くのが安全です。「判断できない」を集計から黙って外すと、分母が変わって割合が動くためです。今回の実験では、この選択肢を許したときの件数は測っていません。
英語データで試した限界
今回の数字は、そのまま自分のデータには当てはまりません。理由は次の 6 つです。
| 限界 | 何が起きうるか |
|---|---|
| 評価点 5・6 のレビューが無い | はっきりした声だけなので、実際のアンケートより当てやすい |
| 本文に「7/10」のような評価点が書かれたレビューがある | AI がそれを手がかりにした可能性があり、正解率は高めに出ている可能性がある |
| 英語のデータ | 日本語での正解率は確かめていない |
| 1 回だけの実行 | 同じ AI に何度も答えさせたときのばらつきや、他のモデルとの差は確かめていない |
| 分類した AI は、ラベル付きデータを抽出した担当と同じ | ラベルが本当に見えていなかったかを後から確かめられず、正解率は高めに出ている可能性がある |
| 公開データなので、AI の学習データに含まれている可能性がある | AI が答えを覚えていた可能性を否定できず、正解率は高めに出ている可能性がある |
特に 2 つ目は見落としやすい点です。自分のデータで、答えのヒントになる語(「満足度 5」など)が本文に入っていないかを先に確かめてください。
最後の 2 つは、自分のデータで試すときに避けられます。正解ラベルを付ける作業と AI に分類させる作業を別々に行い、AI には本文だけを渡してください。社内のアンケートのような公開されていない文章なら、AI が学習で見ている心配は小さくなります。
まとめ
- 正解ラベル付きの公開レビュー 200 件で、AI の分類の正解率は 97.0%(95% 区間 93.6%〜98.6%)でした。
- 1 件ごとの正解率と、集計した割合のずれは別の数字です。全体のずれは +1.0 ポイントでしたが、評価点が中間寄りの帯では +3.5 ポイントに広がりました。
- 自分のデータでは、人が 100 件にラベルを付けて正解の表を作り、レポートで分けて集計する単位ごとに同じ検算をしてから割合を載せます。
次にやること
検算した割合をどう見せるかの参考には、ダッシュボードの一覧で、このサイトが公開データから作ったダッシュボードの例をご覧ください。検算に使う SQL が定義どおりか、第三者の目で確かめたい場合は、BigQuery SQL レビューパックもご利用いただけます。