こんにちは、ユニファで機械学習エンジニアをしている藤塚です。
昨今の生成AIの進展が目まぐるしいですが、ユニファでも例にもれず生成AI活用が進んでいます。特に、保育園で日々撮影される写真データの活用は主要テーマの1つであり、写真データにおける生成AI活用の検討が進められています。
従来の機械学習モデルと比較すると、LLM(Large Language Model)という名前の通りすでに大規模データを事前に学習していることからチューニングがなくとも十分な性能のモデルとして利用できる場合も多く(また今後の性能向上も十分期待できる)、専用のタスクに特化した大量のデータの用意から、モデルを学習するための環境構築、またモデル学習や学習にかかる試行錯誤など従来かかっていたコストを鑑みると、LLMをまず利用してみるというのが強力な選択肢の1つになるかと思います。
ただし、例えば画像から物体検出するようなタスクをLLMに大量に捌いてもらうようなサービスを作る場合、チャットのようなやり取りは基本的には出来ないため、想定されるケースを処理できるかどうかを事前に確認しておく必要があります。特に、LLMの性能はプロンプトによって大きく変化するため、プロンプトエンジアニリングはLLMをサービスとして利用する上で必須な要素として挙げられます。このブログでは、特に画像を入力とした場合のプロンプトエンジニアリングに焦点を当てて話そうと思います。
Note
この記事では、主にGoogleのgeminiのAPIを用いています。モデルとしては
gemini-2.0-flash-001
を利用しており、ここでの知見も主にそれを利用して得られたものになります。そのため他モデルや今後の最新のモデルでは異なることもあるということには注意してください。使用している画像は、写真素材なら「写真AC」無料(フリー)ダウンロードOK からダウンロードしたもの、また生成AIに生成してもらったものを使用しています。
画像のプロンプトエンジニアリング
CoT(Chain of Thought)プロンプト
まず複雑な推論が必要となるタスクに対しては、CoTプロンプトが効果的であるということはよく言われていることだと思います。しかし、人にとっては簡単で複雑ではないと考えられるタスクだとしても単純なプロンプトでは間違った回答をしてしまうことがよくあります。例えば、下記画像を例に見てみます。
プロンプト) {上記画像}, ジャケットを着ている人の人数を教えてください。それぞれの特徴を教えてください。 LLMの回答) 画像にはジャケットを着ている人が4人います。 - 左側の女性の隣に立っている男性は、ダークグリーンのジャケットを着ています。 - 中央に立っている男性は、黒いジャケットを着ており、腕を組んでいます。 - 中央に座っている男性は、ダークグレーのジャケットを着ています。 - 右側の女性は、白いブラウスを着ています。
上記のような一見簡単に見えるタスクだとしても間違いが起こってしまいます。ではどうするのかというと、CoTプロンプトの考え方を利用して下記のように変更してみます。
プロンプト) {上記画像}, 1. 写っている人それぞれの服の特徴を教えてください。 2. その中でジャケットを着ている人を教えてください。 3. ジャケットを着ている人の人数を教えてください。 LLMの回答) はい、承知いたしました。 1. 写っている人それぞれの服の特徴: - 左側の女性: 青と白のストライプのシャツを着ています。 - 中央の男性: 紫色のシャツの上に黒いジャケットを着ています。 - 左奥の男性: 白いシャツの上に緑色のジャケットを着ています。 - 右奥の男性: 白いシャツの上に黒いジャケットを着ています。 - 右側の女性: 白いシャツを着ています。 2. ジャケットを着ている人: - 中央の男性 - 左奥の男性 - 右奥の男性 3. ジャケットを着ている人の人数: - 3人
上記は簡単な例ではありますが、画像入力の場合でもステップに分けて段階的に推論させていくことはLLMの性能を発揮させるためにはかなり効果的で、間違った推論を防ぐためにも重要なテクニックであると考えられます。
指示の明確化
これもよく言われることですが、自然言語は曖昧性をたぶんに含むため、指示を与える場合は内容を明確にすることが必要です。例えば、画像を与えた時に「若者を検出してください」という指示をしたとしても、若者の定義は人によっても、LLMによっても異なります。なので、そこを明確にするために下記のようなプロンプトに変更したとします。
若者を検出してください。 ### 若者の定義 - 年齢の範囲: ... - 顔の特徴: ... - 服装の特徴: ...
これで一見問題なさそうにも思いますし、実際これでうまくいくケースも多くあるとは思います。ただ、様々なケースで実験してみると、「こういう場合には若者である可能性があるため、若者と判断しました」のように「若者」というワードをLLMが持つ知識から拡大解釈してプロンプトの定義から外れたものまで含めてしまうというケースが出てくることがよくあります。1つの解決策としては、「若者」というワードは一切出さずに下記のようにこちらで対象としたい特徴を持つ人物を検出するような形でプロンプトを書くことが挙げられます。
下記の特徴を持つ人を検出してください。 ### 特徴 - 年齢の範囲: ... - 顔の特徴: ... - 服装の特徴: ...
特化モデルの併用
LLMは特に画像に特化しているわけではないので、画像に特化したモデルを併用するという選択肢もあります。例えば、下記の例で見てみます。
プロンプト) 何人の人が写っていますか?それぞれの人の特徴を教えてください。 LLMの回答) 写真には10人の人が写っています。 最前列には、左から、濃い青色のシャツを着た男性、スーツを着て眼鏡をかけた男性、白いジャケットを着た女性がいます。 2列目には、左から、薄い青色のシャツを着た男性、白いシャツを着た男性、薄い青色のシャツを着た男性がいます。 3列目には、左から、濃い色のシャツを着た男性、濃い色のジャケットを着た女性、白いシャツを着た男性がいます。 一番後ろには、濃い色のシャツを着た男性がいます。
写真を見てもらうと分かるように11人写っているので間違えていることが分かります。実際に人数が多い場合など間違えてしまうケースがよくあります。この時には、物体検出に特化したモデルを利用した方がよいことが多く、実際下記のように正確に人物を捉えることができます(ここではDETRを使用)。
人数だけ知りたいなら物体検出モデルだけ利用すればよいですが、人物が持つ何かの特徴や対象物を検出したいというタスクであれば、物体検出した結果をさらにLLMに渡すことによって、着目してほしい場所を明示的に伝えることができ、より効果的な利用を考えることができます。
試行錯誤する上で
プロンプトエンジニアリングを試行錯誤する上で、LLMがどの程度の性能を持っているのかを把握しておくことは非常に重要だと考えられます。LLMがうまくやってくれない原因は、そもそもLLMが持つ画像理解や検出能力に問題があるのか、それともプロンプトで調整可能な推論部分による問題なのかを切り分けて考えることで、どの程度の性能が期待できるのか、またプロンプトのどこを修正していけば性能を出すことが出来るのかの見極めにつなげることができます。
例えば上記のジャケットを着ている人を検出するタスクを要素に分解してみると
そもそも人物を検出できるのか?
着ている衣服の区別はできるのか?
となり、これらの要素ごとの性能を踏まえた上でプロンプトを調整することが大事になってきます。例えば、人物検出の時点で期待している性能を達成できていないということが分かってしまえば、そこに無駄なプロンプトエンジアニリングのコストをかける必要はなくなります。その際に、上記で記載した人物検出に特化したモデルを別途利用するなどの選択肢が出てくるかもしれません。
さらに、各社が提供しているLLMを利用する場合はモデルのライフサイクルも考慮しておく必要があります。例えばgeminiで言えば、各モデルは1年で提供は終わってしまうので(Model versions and lifecycle | Generative AI | Google Cloud)、モデル更新を必ず念頭においてサービス設計をする必要があります。当然プロンプトもモデルに合わせて挙動を変えてしまうので、その度にプロンプトエンジアニリングが必要となります。その時に、タスクを行う上での要素ごとの基本的なモデル性能を把握しておくことで、更新の際に新しいモデルとの性能の違いを踏まえて、どのように変更すればよいかというところが検討しやすくなるのかなと思います。
最後に
画像におけるプロンプトエンジアニリングについてみてきました。画像におけるプロンプトエンジアニリングのエッセンスは下記のGoogleの記事にも記載されています。自分自身は実践する前はたしかにそうだな程度で理解はしていたものの、実際に試行錯誤してみて改めてこれらの重要性を認識しています。
Design multimodal prompts | Generative AI | Google Cloud
少しでも皆さんの参考になればと思います。
ユニファでは一緒に働く仲間を募集しています。 ご興味を持っていただけましたらぜひ採用情報をチェックしてみてください!