はじめに
以前に、Transformers 、Gemma 、Diffusers などを使って、生成 AI プログラミングを試してみました。
文章の入力に対して文章や画像を生成して出力できました。
これに対して、OpenAI の ChatGPT や Google の Gemini などのサービスでは、画像を入力して文章を出力することができます。
生成 AI プログラムは、モデルを参照して入力内容から出力内容を生成します。モデルは、どんな入力内容に対して、どんな出力内容を生成するか、学習させたものです。
上記のサービスで利用している AI モデルは、画像の入力と文章の出力を学習させているのですね。
同様のモデルを使えば、自分でも画像から文章を生成するプログラムが書けるはずです。
画像認識 AI モデルを試してみる
画像を認識する AI プログラムを試してみます。
以下の記事を参考にしました。
実行環境を用意する
以前と同様に Google Colab を使ってみます。別の環境でも構いません。
参考:生成 AI プログラムを試してみた #LLM - Qiita
以下のコード例は、Google Colab あるいは Jupyter Notebook で実行するものです。
ライブラリをインストールする
Transformers
ライブラリを使うのでインストールします。
! pip install transformers accelerate
モデルを用意する
モデルはリポジトリサービスから入手します。以前と同様に Hugging Face
を使用します。
参考:生成 AI プログラムを試してみた #LLM - Qiita
LLaVA 、PaliGemma を使ってみる
画像を入力して文章を生成できるモデルに、LLaVA
があります。画像のエンコーダと LLM の LLaMA を合わせたモデルとのことです。
これを使ってみます。
参考:画像分析機能を持つオープンソースLLM『LLaVA-1.5』登場 | AIDB
LLaVA
だけでなく別のモデル PaliGemma
も使えそうです。Google の PaLI から着想して、画像のエンコーダと LLM の Gemma を合わせたモデルとのことです。
参考:Googleがオープンソースのビジュアル言語モデル「PaliGemma」を公開 - GIGAZINE
画像データを準備する
Hugging Face でチュートリアルのために用意された画像データを使ってみます。
これを参照して画像オブジェクトにします。↓
import requests
import PIL
# 画像を参照
url = "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/tasks/ai2d-demo.jpg"
image = PIL.Image.open(requests.get(url, stream=True).raw)
モデルとプロセッサで処理する
モデルをダウンロードしてプロセッサを準備します。
import transformers
import torch
# モデルとプロセッサの準備
model = transformers.LlavaForConditionalGeneration.from_pretrained(
"llava-hf/llava-1.5-7b-hf",
device_map="auto",
torch_dtype=torch.float16, low_cpu_mem_usage=True,
)
processor = transformers.AutoProcessor.from_pretrained(
"llava-hf/llava-1.5-7b-hf",
)
画像データとプロンプトを入力内容にして推論させて結果を作成させます。
prompt = "これは何の画像ですか。"
# プロセッサとモデルで推論
inputs = processor(
"USER: <image>\n" + prompt + "\nASSISTANT:\n",
image,
return_tensors="pt"
).to(model.device)
outputs = model.generate(
**inputs,
max_new_tokens=200,
do_sample=False
)
作成された結果を出力します。
output = processor.decode(
outputs[0][1:],
skip_special_tokens=True
)
print(output)
結果の例です。↓
この画像は、地質学的な地図であり、地層や地下水の流れなどの情報が表示されています。地図には、地下水の流れや地層の層序、地下の洞窟、地下の溶岩などが含まれており、地質学的な知識を持つ人々にとって有益な情報源となっています。
パイプラインで処理する
上記と同じことをパイプラインで処理してみます。
# パイプラインの準備
pipe = transformers.pipeline(
"image-to-text",
model="llava-hf/llava-1.5-7b-hf"
)
prompt = "これは何の画像ですか。"
# パイプラインで推論
outputs = pipe(
image,
prompt="USER: <image>\n" + prompt + "\nASSISTANT:\n",
generate_kwargs={"max_new_tokens": 200}
)
作成された結果を出力します。
print(outputs[0]["generated_text"])
結果の例です。↓
この画像は、地質学的な地図であり、地層や地下水の流れなどの情報が表示されています。地図には、地下水の流れや地層の層序、地下の洞窟、地下の溶岩などが含まれており、地質学的な知識を持つ人々にとって有益な情報源となっています。
モデルを替えてみる
モデルを LLaVa
から PaliGemma
に替えてみます。
# モデルとプロセッサの準備
model = transformers.PaliGemmaForConditionalGeneration.from_pretrained(
"google/paligemma-3b-mix-224",
device_map="auto",
torch_dtype=torch.float16, low_cpu_mem_usage=True,
)
processor = transformers.AutoProcessor.from_pretrained(
"google/paligemma-3b-mix-224",
)
あるいは
# パイプラインの準備
pipe = transformers.pipeline(
"image-to-text",
model="google/paligemma-3b-mix-224"
)
推論させて結果を出力するプログラムは同じです。出力すると↓
火山 の さまざま な 部分 の 図 。
実行環境を変更してみる
Google Colab は実行環境の GPU/TPU を選択できます。現在は以下のタイプが選択できました。それぞれスペックを確認しました。
CPU | TPU v2 | T4 GPU | L4 GPU | A100 GPU | |
---|---|---|---|---|---|
システム RAM | 13GB | 334GB | 13GB | 53GB | 84GB |
GPU RAM | なし | なし | 15GB | 22GB | 40GB |
ディスク | 108GB | 225GB | 78GB | 78GB | 78GB |
ユニット使用率 | 約0.07/時 | 約1.76 | 約1.76 | 約4.82 | 約11.77 |
前述のプログラムをそれぞれの環境で実行するとどうなるでしょうか。
CPU | TPU v2 | T4 GPU | L4 GPU | A100 GPU | |
---|---|---|---|---|---|
モデルとプロセッサで処理 | 終了しない | クラッシュした | ○ | ○ | ○ |
パイプラインで処理 | クラッシュ | クラッシュ | ○ |
モデル LLaVa
、 PaliGemma
どちらも同じでした。別のサイズの大きいモデルを使うと結果が違うかも知れません。
モデルとプロセッサで処理したときとパイプラインで処理したときで結果が違うのは、前者が torch_dtype=torch.float16, low_cpu_mem_usage=True
のような指定していて後者は指定がないからでしょうか。
UniDiffusers を使ってみる
文章を入力して画像を生成して出力するのに、以前に Stable Diffusion のモデルと Diffusers ライブラリを使いました。
このライブラリに含まれる UniDiffusers
を使うと、文章から画像を生成するだけでなく、画像から文章を生成できるようです。
diffusers v0.17.0 の UniDiffuser を使ってみる - ジャコ Lab
ライブラリをインストールする
Transformers
に加えて、Diffusers
ライブラリを使うのでインストールします。
! pip install diffusers
画像データを準備する
Hugging Face でチュートリアルのために用意された画像データを使ってみます。
これを参照して画像オブジェクトにします。↓
# 画像を参照
url = "https://huggingface.co/datasets/hf-internal-testing/diffusers-images/resolve/main/unidiffuser/unidiffuser_example_image.jpg"
image = diffusers.utils.load_image(url).resize((512, 512))
パイプラインで処理する
パイプラインを準備して処理します。
import diffusers
import torch
# パイプラインの準備
pipe = diffusers.UniDiffuserPipeline.from_pretrained(
"thu-ml/unidiffuser-v1",
torch_dtype=torch.float16, low_cpu_mem_usage=True
).to("cuda")
# パイプラインで推論
output = pipe(
image=image,
# prompt="この画像は何ですか。",
num_inference_steps=20, guidance_scale=7.5
)
このパイプラインは文章のプロンプトは受付けないようです。↑
# 結果を出力
print(output.text[0])
結果の例です。↓
An image of an astronaut flying in space over the earth