ふくふくHukuhuku Inc.
EP.19Prep 13分公開: 2026-09-01

推定の偏りを測る ── 全体では当たっているのに、特定の群だけ外れる

属性を推定する仕組みは、全体の精度が高くても、特定の集団だけ大きく外していることがあります。平均だけを見ていると気づけない問題を、どう検出するかを扱います。

#前処理#属性推定#評価#Python
執筆 / 監修
松尾 亮合同会社ふくふく 代表社員

データ基盤・データパイプライン構築 / BI / 生成 AI 活用支援を専門とするエンジニア (28 年)。 本記事は AI 利用ポリシーに基づき、生成 AI の補助で執筆 → 人間が監修・編集して公開しています。

プロフィール詳細
シェア

EP.17 で、推論による属性の付与を扱いました。そこで「危ういのは精度が低いからではなく、精度が分からないから」と書きました。

この回は、その精度をどう測るかを扱います。特に、全体では当たっているのに特定の群だけ外れるという、見つけにくい問題に焦点を当てます。

1. 平均は少数派を隠す

精度を1つの数字で表すと、件数の多い群の成績がそのまま全体の成績になります

全体では高精度なのに、特定の群では当たっていない例
Python
import numpy as np
rng = np.random.default_rng(42)
# 群ごとの件数と、その群での的中率GROUPS = {    "A(多数派)": {"n": 9000, "acc": 0.95},    "B":           {"n":  800, "acc": 0.88},    "C(少数派)": {"n":  200, "acc": 0.52},}
total_correct = 0total_n = 0print(f"{'群':14s}{'件数':>7}{'的中率':>9}")for name, g in GROUPS.items():    correct = int(g["n"] * g["acc"])    total_correct += correct    total_n += g["n"]    print(f"{name:14s}{g['n']:7d}{g['acc']:9.1%}")
print(f"\n全体の的中率: {total_correct / total_n:.1%}")print("→ 全体は良好に見えるが、C群は当てずっぽうと大差ない")

実行すると、全体では 93% 前後になります。良好な数字に見えます。しかし C群では 52% ── 2択なら当てずっぽうと大差ありません

そして、この C群に対して推定値を使うと、約半分が誤った値になります。全体の精度だけを見て「使える」と判断すると、この事実を見逃します。

件数が少ない群ほど外れやすい

学習に使えるデータが少ないので、当然といえば当然です。ただし件数が少ないぶん、全体の精度への影響も小さい。つまり外れていても数字に現れないという、二重に見つけにくい構造になっています。

2. 群ごとに測る

対処は単純で、群ごとに分けて測ることです。 と呼ばれる考え方ですが、やることは集計を分けるだけです。

群ごとの精度を出して、差を見る
Python
import numpy as npimport pandas as pd

def accuracy_by_group(df, group_col, true_col, pred_col, min_n=30):    """群ごとの的中率を出す。件数が少ない群は別に示す。"""    rows = []    for name, g in df.groupby(group_col):        n = len(g)        acc = (g[true_col] == g[pred_col]).mean()        rows.append({            "群": name,            "件数": n,            "的中率": acc,            "判定": "件数不足" if n < min_n else "",        })
    out = pd.DataFrame(rows).sort_values("件数", ascending=False)
    # 全体との差を出す    overall = (df[true_col] == df[pred_col]).mean()    out["全体との差"] = out["的中率"] - overall    return out, overall

# 使い方# result, overall = accuracy_by_group(df, "region", "actual", "predicted")# print(f"全体: {overall:.1%}")# print(result.to_string(index=False))

件数が少ない群を明示するのが要点です。件数が30件しかない群の的中率は、それ自体が大きく揺れます統計入門 EP.07 参照)。低く出ても、たまたまかもしれません。

「件数不足で判断できない」という結果も、立派な結果です。「精度が低い」と「精度が分からない」は違います。後者なら、まず件数を増やすか、その群には適用しないという判断になります。

3. どの軸で分けるか

分ける軸の選び方には、優先順位があります。

分ける軸の優先順位
優先度理由
件数に偏りがある軸最高少数派で精度が落ちやすい
扱いに配慮が要る属性最高誤りの影響が大きい
時期高い古いデータで学習していないか
地域・拠点データの取り方が違うことがある
入力の経路経路ごとに品質が違う

3行目は見落とされがちですが重要です。古いデータで学習した仕組みは、新しいデータで精度が落ちます。時期で分けて測ると、いつから劣化しているかが見えます。

2行目については、EP.17 でも触れたとおり扱いそのものに配慮が要ります。推定の対象にしてよいか、という手前の判断があります。測る以前の問題として、その属性を推定する必要が本当にあるかを確認してください。 の観点では、推定してまで持つ必要のない属性は、持たないのが最も安全です。

4. 外れ方の中身を見る

的中率だけでなく、どう外れているかも見ます。同じ精度でも、外れ方によって影響が違います。

外れ方の分類
外れ方何が起きるか
特定の値に寄る多数派の値に全部倒れている(実質推定していない)
ばらばらに外れる情報が足りていない
一方向に偏る系統的な誤り。原因がある
極端な値で外れる外れ値の扱いに問題

1行目が実務で最も多い形です。推定した結果が、全部同じ値になっている。多数派の値を返せば、全体の精度はそれなりに出ます。しかし推定として何もしていません

推定結果の分布が、実際の分布と合っているか
Python
import pandas as pd

def compare_distribution(df, true_col, pred_col):    """実際の分布と、推定結果の分布を比べる。"""    actual = df[true_col].value_counts(normalize=True).sort_index()    pred = df[pred_col].value_counts(normalize=True).sort_index()
    out = pd.DataFrame({"実際": actual, "推定": pred}).fillna(0)    out["差"] = out["推定"] - out["実際"]    return out.sort_values("差", key=abs, ascending=False)

# 推定が特定の値に寄っていれば、その値の「差」が大きく正になる# result = compare_distribution(df, "actual", "predicted")# print(result.to_string())

推定結果の分布が、実際の分布と大きく違うなら、それ自体が警告です。特に、多数派の値だけが増えているなら、1行目の状態を疑ってください。

5. 偏りが見つかったら

対処には段階があります。必ずしも精度を上げる必要はありません

  1. 1その群には適用しない最も安全。欠損のまま残す
  2. 2その群のデータを増やす — 根本的だが時間がかかる
  3. 3群ごとに別の方法を使う — 少数派には単純な規則で
  4. 4推定値に信頼度を付ける — 使う側が判断できるように
  5. 5推定そのものをやめる — 目的に対して手段が合っていない

1番目を最初に挙げたのは、これが見落とされやすいからです。「精度が出ないなら改善しなければ」と考えがちですが、適用しないという選択のほうが正しい場面は多くあります。

EP.17 で書いたとおり、推定値は元のカラムに混ぜず、推定であることを保つ。そうしておけば、特定の群だけ推定しないという運用が自然にできます。

「埋めない」も選択肢

欠損があると気持ち悪いので埋めたくなりますが、誤った値で埋めるより、欠損のままのほうが正確です。下流で「この群はデータがない」と扱えるなら、それが最も誠実な状態です。

6. 継続して測る

一度測って終わりにしないでください。データは変わり、精度は落ちます

  • 定期的に群ごとの精度を出す — 月次など
  • 新しく増えた群を検出する — 想定していなかった値が来る
  • 時期での劣化を見る — 古い学習のまま使っていないか
  • 閾値を決めて通知する — 一定を下回ったら知らせる

2番目が実務で効きます。カテゴリの値が増えることがあります。新しい区分が追加された、新しい地域に展開した。学習時に存在しなかった群は、当然ながら精度が出ません。

この継続的な確認は、LLM時代のテスト戦略 EP.05 で扱ったリグレッションと同じ位置づけです。変わっていないはずのものが変わっていないかを、定期的に確認する。

ここまでのまとめ

全体の精度は多数派の成績であり、少数派の失敗を隠す。しかも件数が少ない群ほど外れやすく、かつ数字に現れにくい。対処は群ごとに測ること。件数不足で判断できないことも結果として扱う。分ける軸は件数の偏り・配慮が要る属性・時期を優先。偏りが見つかったら、その群には適用しないのが最も安全です。

シェア

この記事の感想を教えてください

あなたの 1 クリックで、本当にこの記事は更新されます。「もっと詳しく」「続編希望」が一定数集まった記事は、 ふくふくが 実際に内容を拡充したり続編記事を公開 します。 送信したリアクションはお使いのブラウザに記録され、再カウントされません。

シリーズの外も探す:

まずは、現状を聞かせてください。

要件が固まっていなくて大丈夫です。現状診断と方針提案までを無料でお手伝いします。

無料相談フォームへ hello [at] hukuhuku [dot] co [dot] jp