見出し画像

OpenAI gpt-4o でzero shotで異常検知(Anomaly Detection)を試してみる

はじめに

こんにちは、Caratの脇山です。
先日 gpt-4o が発表リリースされました。
性能、速度、料金などがアップデートされましたね。

詳細は他の方の記事や公式のドキュメントにまとまっているので触れませんが、特にトークナイザの改善と音声モデルの処理が一つのニューラルネットで完結できる点に感動しました。

具体的にはトークナイザ改善でより高速、高性能、低価格を実現できる点や
音声が 音声 -> テキスト -> 音声 の3つのパイプラインを通って生成されるのではなく、1つのニューラルネットで周囲の音や感情といった情報も踏まえて生成される点がすごいと思っています。

gpt-4oを使った音声出力を試したかったのですが、近日公開ということなので、別の検証をしていきたいと思います。
画像の読み取り精度がアップしたということで、どのくらいの改善がされたのだろうと思い、異常検知のデータセットを使って精度を検証していきます。

zero shot での 異常検知を検証してみる

使用するデータセットはこちら からダウンロードさせていただきました。

ヘーゼルナッツの形に異常があるかどうか検知します。
テストデータには以下のようなデータが入っています。
40件のデータを使って検証を行なっていきます。

検証内容
以下のモデルで、ラベル付タスクを行います。

  • gpt-4o

  • gpt-4-turbo

  • claude-3-opus-20240229

  • gemini-pro-vision (gemini-1.5-flash-latest が安定してなかったので、pro-visionのモデルで) 
    -> レスポンスが安定しないので試して更新します。

それぞれコードは以下となります。

  • 画像を変換する

def to_base64_image(image_path):
  with open(image_path, "rb") as f:
  return base64.b64encode(f.read()).decode("utf-8")
  • OpenAI

openai_client = OpenAI()
def chat_with_image_by_openai(model: str, image_path: str):
    sys_prompt = """
    ユーザーが送信するヘーゼルナッツの画像を評価し、綺麗なものには「good」ラベルを、異常なものには「bad」ラベルをつける。
    ガイドライン
    ユーザーが送信した画像を迅速かつ正確に評価する。
    評価基準を一貫して適用し、ユーザーが期待する結果を提供する。
    個別化
    画像評価の際に丁寧かつプロフェッショナルな言葉遣いを使用する。
    この設定で進めます。画像を送信してください。
    「good」または「bad」というキーワードのみを出力してください。
    """


    image = to_base64_image(image_path)
    response = openai_client.chat.completions.create(
        model=model,
        messages=[
            {
                "role": "system",
                "content": sys_prompt,
            },            
            {
                "role": "user",
                "content": [{"type": "image_url", "image_url": {"url": f"data:image/jpg;base64,{image}"}}],
            },
        ],
        temperature=0,
    )
    return response.choices[0].message.content
  • Claude

anthropic_client = anthropic.Anthropic()
def chat_with_image_by_anthropic(model:str, image_path: str) -> str:
    prompt = """
    ユーザーが送信するヘーゼルナッツの画像を評価し、綺麗なものには「good」ラベルを、異常なものには「bad」ラベルをつける。
    ガイドライン
    ユーザーが送信した画像を迅速かつ正確に評価する。
    評価基準を一貫して適用し、ユーザーが期待する結果を提供する。
    個別化
    画像評価の際に丁寧かつプロフェッショナルな言葉遣いを使用する。
    この設定で進めます。画像を送信してください。
    「good」または「bad」というキーワードのみを出力してください。
    """
    message = anthropic_client.messages.create(
        model=model,
        max_tokens=1024,
        temperature=0,
        system=prompt,
        messages = [
          {
              "role": 'user',
              "content": [
                  {"type": "image", "source": {"type": "base64", "media_type": "image/jpeg", "data": to_base64_image(image_path)}},
              ]
          }
      ]
    )
    return message.content[0].text

実行結果は以下のようになりました。

gpt-4o
False Positive Rate (FPR): 0.0
False Negative Rate (FNR): 0.08
gpt-4-turbo
False Positive Rate (FPR): 0.53
False Negative Rate (FNR): 0.0
claude-3-opus-20240229
False Positive Rate (FPR): 0.6
False Negative Rate (FNR): 0.0

以上の結果から、gpt-4o以外は異常データを正常と見てしまう確率が割とあるようで、異常検知として性能が高くないように思います。一方 gpt-4oは8%で正常データを異常とみなしますが、異常なものを全て正確に推論できているので、結構良い性能なのではないでしょうか。

プロンプトはbadタグを「異常なもの」として曖昧に定義しているので、具体的な要件を盛り込むようチューニングすれば精度が上がるかと思います。
どちらかというと要件が抽象的な状態のプロンプトでモデルがどのように判別するかを見てみたかったので、目的は達成されました。思った以上に正確でびっくりしたと同時に、割と実用的であるなぁと思いいくつかやってみたいことが増えました。

終わりに

改めてすごいなと感じたことは、汎用的な機械学習モデルとしても使えるし、プロトタイプの機械学習モデルを作るのに最適だということです。しかし、性能を考えると値段が安いとはいえ、それでも専用モデルを動かすよりは高価であるため、プロトタイプで検証した結果を元に本格的な機械学習モデルを作るのが良いと考えています。

話は変わりますが、今回のアップデートでOpenAIの強さを改めて実感しました。しかし、翌日のGoogle Geminiのアップデートや、最近の他社モデルとの競合の激しさもあり、オープンソースのLLMを利用することも含めて、LLMアプリケーションを作る上でどのように戦略を立てていくかという難しさを感じています。どのようなモデルが登場しても自社のアプリケーションの価値が落ちないように、LLMに独自のデータをどのように埋め込むか、どのような順序で実行するかなど、モデルに依存しない部分をまずはしっかり作り込む必要があると感じています。

最後に宣伝になります!
私は株式会社Caratで生成AIを使った求人検索サービスの AIジョブサーチ を開発しています!

生成AIを使ってどのように良いプロダクトを作りたいと方を積極的に募集しております!
興味のある方は こちら よりお問い合わせください!
待ってます!

参考記事


この記事が気に入ったらサポートをしてみませんか?