MENU

問い合わせ


    【YOLOで作る画像認識ツール 第8回】自信の低い結果だけ人が確認する:AIと人の役割分担を設計する

    前回の第7回では、追加学習で「覚えたもの」と「見逃すようになったもの」が混ざる結果を見ました。ここまでの連載で確かめたとおり、画像認識AIは、間違えることを前提に使う必要があります。

    では、どう使うのか。現実的な答えの1つが、AIが自信を持てた結果は自動で採用し、自信がない結果だけ人が確認するという役割分担です。今回は、この「人が確認するフロー」を作ります。

    目次

    この回で作るもの

    • 検出結果を「自動で採用」「人が確認」「捨てる」に振り分ける処理
    • 人の判断(そのまま・却下・種類の修正)を、結果に反映する処理
    • 自動採用の結果から一定の割合を抜き取って確認する仕組み(抜き取り確認)

    仕組み:信頼度で3つに振り分ける

    第1回で学んだ信頼度を使い、2つのしきい値で結果を振り分けます。

    信頼度扱い意味
    0.60以上自動で採用人の手間をかけずに使う
    0.25以上、0.60未満人が確認画面で見て、そのまま・却下・種類の修正を決める
    0.25未満捨てる自信が低すぎるので、結果に出さない

    しきい値の数字は、この連載の練習用の値です。実際は、第6回の方法で測った精度と、人が確認できる件数の余裕を見て決めます。

    実装

    振り分ける app/review.py

    # app/review.py(抜粋)
    ACCEPT_THRESHOLD = 0.60  # これ以上は自動で採用する
    REVIEW_THRESHOLD = 0.25  # これ未満は捨てる。間は人が確認する
    
    
    @dataclass(frozen=True)
    class Triage:
        accepted: list[Detection]  # 自動で採用
        needs_review: list[Detection]  # 人が確認する
        discarded: list[Detection]  # 自信が低すぎるので捨てる
    
    
    def triage(detections, accept=ACCEPT_THRESHOLD, review=REVIEW_THRESHOLD) -> Triage:
        if not 0 <= review <= accept <= 1:
            raise ValueError("しきい値は 0 <= 確認 <= 採用 <= 1 にしてください")
        return Triage(
            accepted=[d for d in detections if d.confidence >= accept],
            needs_review=[d for d in detections if review <= d.confidence < accept],
            discarded=[d for d in detections if d.confidence < review],
        )

    triage は、フランス語の「選別」が語源で、救急医療で患者の緊急度を分ける意味でも使われる言葉です。

    人の判断を反映する

    人が確認した結果は、「そのまま」「却下」「種類の修正」の3つです。

    # app/review.py(抜粋)
    def apply_decisions(detections, decisions) -> list[Detection]:
        """人の判断を反映して、最終的な結果を返す。
    
        decisions の各要素: {"box": [左,上,右,下], "action": "accept" | "reject" | "relabel", "label": "kiwi"}
        判断が付いていない検出は、そのまま残す。
        """
        by_box = {tuple(d["box"]): d for d in decisions}
        final: list[Detection] = []
        for det in detections:
            decision = by_box.get(det.box)
            action = decision["action"] if decision else "accept"
            if action == "reject":
                continue
            if action == "relabel":
                if not decision or not decision.get("label"):
                    raise ValueError(f"relabel には label が必要です: {det.box}")
                det = replace(det, label=str(decision["label"]))
            final.append(det)
        return final

    判断は枠の位置(box)で結びつけます。種類の修正には、新しい種類名が必須です。書き忘れると、間違ったまま通すのではなく、エラーで止めます。

    抜き取り確認

    # app/review.py(抜粋)
    def sample_for_audit(accepted: list[Detection], rate: float, seed: int = 0) -> list[Detection]:
        """自動採用した結果からも、一定の割合を抜き取って人が確認する(自信が高いのに間違う結果を拾うため)。"""
        if not accepted or rate <= 0:
            return []
        count = max(1, round(len(accepted) * rate))
        return random.Random(seed).sample(accepted, min(count, len(accepted)))

    動かして確かめる

    python -m app.review samples/fruits.jpg --decisions samples/decisions_example.json --audit-rate 0.5

    開発環境での結果は次のとおりです(一覧の一部を省略)。

    自動採用 2 件 / 人が確認 2 件 / 捨てる 0 件
    確認待ち: 信頼度0.398(右上の枠)、信頼度0.469(左下の枠)
    抜き取り確認: [('orange', 0.72)]
    人の判断を反映した最終結果:
    - lemon 0.87 (317, 247, 512, 477)
    - orange 0.72 (69, 44, 348, 470)
    - kiwi 0.47 (0, 277, 130, 477)
    - lime 0.40 (321, 121, 512, 305)

    信頼度0.47と0.40の2件は、人の確認に回りました。サンプルの判断(decisions_example.json)では、第6回の正解データに合わせて、それぞれkiwiとlimeに修正しています。

    「自信が高い間違い」は、しきい値だけでは防げない

    ここで重要な点があります。最終結果の1行目、信頼度0.87の枠は、実際にはレモンなのに、AIは「orange」と答え、自動採用に振り分けられました。 人が確認する枠には入りません。

    この例で、レモンがlemonに直っているのは、サンプルの判断ファイルに「この枠はレモン」という修正を、私が入れているためです。実際の運用では、人が見なければ、この間違いは残ります。

    • 信頼度は、正しさの保証ではない:第2回で見たとおり、信頼度が最も高い結果が、間違いでした
    • 抜き取り確認の限界:今回の抜き取りは、たまたま正しい「0.72」の枠を選び、間違いの「0.87」を選びませんでした。抜き取りは、割合を上げるほど間違いを拾えますが、確認の手間も増えます

    つまり、「自信の低い結果だけ人が確認」する設計は、見逃しを減らす助けにはなっても、すべての間違いを防げるわけではありません。 どこまでの間違いを許容するかを、業務の側で決めておく必要があります。

    テスト

    pytest -q      # 31件成功
    ruff check .   # 問題なし

    振り分けの境界値、判断の反映(修正・却下・判断なしはそのまま)、種類名を書き忘れたときのエラー、抜き取りが同じ条件で同じ結果になることを確認しています。

    つまずきやすい点

    • 確認の件数が多すぎる:しきい値の幅を広く取ると、人の確認が追いつきません。1日に確認できる件数を先に見積もります
    • 確認する人によって判断がばらつく:判断基準(何を「正しい」とするか)を文書にして、共有します
    • 確認結果が使われない:人が直した結果を、次の学習用データとして貯めておくと、モデルの改善に使えます(第7回)
    • 画面がないと運用できない:この回は、確認待ちの一覧と判断の反映まで。実際には、第5回のような画面に、確認のボタンを付けます

    発注者向けメモ:AIは「全自動」ではなく「人の作業を減らす道具」

    画像認識の導入を検討するときは、「全部自動で判定できる」という期待を、「人の確認を減らせる」という期待に置き換えると、現実的な設計になります。

    発注者がやること チェックリスト

    • ☐ 確認が必要な件数の目安(1日に何件まで人が確認できるか)を決めた
    • ☐ 確認する人(担当者)と、判断基準を決めた
    • ☐ 自動採用した結果を、一定の割合で抜き取って確認する運用を決めた
    • ☐ 人が直した結果を、記録に残す(監査と再学習に使える)ことを決めた
    • ☐ AIが間違えたときの責任の所在(誰が最終判断をするか)を決めた

    開発会社への質問例

    • 「信頼度のしきい値は、どのデータで、どう決めますか。人の確認に回る件数は、どのくらいになりそうですか」
    • 「確認用の画面は、見積もりに含まれていますか。修正の履歴は残りますか」
    • 「自信が高いのに間違っている結果を、拾う仕組みはありますか」
    • 「人が直した結果を、再学習に使うことはできますか。その作業は保守に含まれますか」

    まとめと次回予告

    第8回では、次のことを行いました。

    • 検出結果を、信頼度で「自動採用・人が確認・捨てる」に振り分けた
    • 人の判断(そのまま・却下・種類の修正)を反映できるようにした
    • 抜き取り確認を用意し、自信が高い間違いを拾う工夫をした
    • しきい値だけでは、自信が高い間違いを防げないことを確認した

    次回の第9回では、認識を速く・軽くするために、モデルをONNXという形式に変換し、速度を比べます。

    この連載の記事一覧

    この記事は連載「YOLOで作る画像認識ツール」の1回です。連載のほかの回は次のとおりです(連載の一覧ページ)。

    システム制作・運用・保守のお問い合わせはこちら


      よかったらシェアしてね!
      • URLをコピーしました!
      • URLをコピーしました!

      この記事を書いた人

      株式会社THIRD HERO代表取締役 朝野貴朗
      Webシステム開発を中心に、toC向けサービスサイトの運営、ツール開発などを行ってまいりました。

      目次