0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ローカルLLMで画像分類 Ollamaとqwen3 - ゼロから始めるAIシステム開発 #27

0
Posted at

ローカルLLMが話題

Claude CodeならびにCodex、Antigravityなどのバイブコーディングが全盛期だが、使用制限の問題が常につきまとう。聞いた話では、とある企業のエンジニアは週ごとに利用可能トークンが割り振られて、それが尽きたら「店じまい」らしい。そんなケースへの抵抗としてなのか、クラウドLLMサービスに頼らないローカルLLMに注目が集まっているようだ。

ローカルLLMのメリット

メリットは無料で使えることの他にも、情報漏洩のリスクがないことなどが挙げられる。とある成人漫画家が、自分の原稿をアップロードしただけでそのクラウドストレージの関係サービス全体からBANされたという話もあり、そのようなリスクを避けられるのも大きい。また、エネルギー問題やAI企業の収益性の観点から、現在のクラウドLLMサービスの持続性自体を疑う向きもある。手元にLLMを確保しておきたい欲求は自然なものだろう。

ローカルLLMのデメリット

いい話だけではなく、大きなデメリットとしては最新型のモデルに比べて知能が見劣りすることだろう。10か月ほど前にOpenAIのgpt-oss-20bを使用してみたが、当時のクラウドLLMと比較しても論理的思考に難ありの印象だった。とはいえ今のqwen3.6などは飛躍的に性能が上がっているらしく、性能向上も注目が集まっている理由かもしれない。
また、結構なマシンスペックが求められるのも難点だろう。今回は自身のPC(RTX3060搭載・VRAM12GB・メモリ32GB)で動かしたときの快適さなども見てみる。

画像分類に使ってみる

画像分類は機械学習の得意分野だがそれには当然データが必要になる。じゃあデータがない場合はLLMにやらせるか、となるとコストがかかるし先述のようにデータの流出やBANの可能性もある。ということでローカルLLMの出番である。

Ollamaの導入

10か月前にLM studioでgpt-oss-20bを試したときはマルチモーダルに対応してなかったので、今回はOllamaを新規導入してみる。
Ollama
image.png
右のDownloadからダウンロードする。CLIにコマンドを入れる形式でもいい
image.png
image.png
クラウドLLMのようにチャット形式で使えるアプリがインストールされる。メッセージウィンドウ右下から使うモデルを選べ、未ダウンロードならDLする。上4つのようにクラウド型モデルもある。今回はqwen3.6を選択。qwenの中にも画像やコーディングなどそれぞれに特化した種類があるはずだが、チャットアプリからだと選べないようだ。これを選ぶと容量23GBのqwen3.6:35b-a3b-q4_K_Mがダウンロードされるっぽい(2026年6月現在)

画像認識精度

チャッピーに適当にキャラクター画像を作ってもらい、これに何が描かれているかを認識できるか確認する。
image.png
image.png
さらに、この画像を再現するStable Diffusion向けのプロンプトを出力させた結果がこちら

プロンプト
masterpiece, best quality, ultra-detailed, 1girl, solo, long flowing red hair, red eyes, confident expression, gold earrings and choker, black and red corset-style dress, high-slit skirt with white ruffled layers, golden embroidery and trim on outer coat, thigh-high armored boots with metal details and heels, holding an ornate sword in right hand, left hand on hip, standing on a stone balcony, bright blue sky with fluffy clouds, distant castle spires and cathedrals, red flags with gold crests, potted red roses, falling red petals, dramatic sunlight, cinematic lighting, anime style

いい感じ。この精度なら画像分類するには十分すぎる。しかし…

メモリの使用量・動作感

質問した瞬間からRTX3060のVRAMがほぼMAXで使われ、GPUで追い付かない分通常メモリも97%まで使用されて非常に重くなった。
image.png
1枚2枚ならいいが、大量に分類させた場合PCが悲鳴を上げて途中でフリーズするのが目に見える。もう少し軽量のモデル、GPUの12GB内で収まるモデルのほうがよさそう。

qwen3-vl:4b に変更

vlとついているモデルは画像関係に強いらしい。ということで軽めのvl系モデルも試してみる。モデルの容量は3GB。CLIからは以下のコマンドでインストールでき、チャットでも選択可能になる。

コマンドプロンプト
ollama pull qwen3-vl:4b

以下の画像を認識させてみる。
image.png
image.png
瞳の色など若干怪しい所もあるがだいたい合っている感じ。

image.png
12GBの6割くらいで収まっており、回答も早め。個人用途ならこれで十分そう。

Pythonに組み込む

OllamaチャットではPCのファイルには触れない。AIエージェントで使うLLMをローカルにする方法もあるが、Codexの場合は切り替えが煩わしいようなので、今回はPythonでOllamaを呼ぶバッチ処理をする。以下のような階層のフォルダを作り、どこに分類するのが相応しいかの判定部分をローカルLLMに任せる。

フォルダ階層
img/
├─ photo/
│  ├─ male/
│  ├─ female/
│  ├─ animal/
│  └─ others/
└─ illust/
    ├─ male/
    ├─ female/
    ├─ animal/
    └─ others/

この階層で固定なら、第一階層分類(写真/イラスト)と第二階層分類(男/女/動物/その他)を合成してフォルダパスを作る方法でもいいが、複雑化する可能性もあるのでJSONに記述する方法をとる。分類や階層を追加したい場合はこれを編集する。

categories.json
{
  "categories": [
    {
      "path": "photo/male",
      "description": "実写写真で、男性または男性に見える人物が主対象"
    },
    {
      "path": "photo/female",
      "description": "実写写真で、女性または女性に見える人物が主対象"
    },
    {
      "path": "photo/animal",
      "description": "実写写真で、動物が主対象"
    },
    {
      "path": "photo/others",
      "description": "実写写真だが、男性・女性・動物のどれにも明確に当てはまらない"
    },
    {
      "path": "illust/male",
      "description": "イラスト、漫画、アニメ絵、CG、生成AI画像などで、男性キャラクターが主対象"
    },
    {
      "path": "illust/female",
      "description": "イラスト、漫画、アニメ絵、CG、生成AI画像などで、女性キャラクターが主対象"
    },
    {
      "path": "illust/animal",
      "description": "イラスト、漫画、アニメ絵、CG、生成AI画像などで、動物キャラクターが主対象"
    },
    {
      "path": "illust/others",
      "description": "イラスト系だが、男性・女性・動物のどれにも明確に当てはまらない"
    }
  ]
}

Pythonコードは長いので割愛。Ollamaに渡すプロンプトの部分だけ記述する。

def build_prompt(categories: list[dict[str, str]]) -> str:
    category_lines = []

    for item in categories:
        category_lines.append(
            f"- {item['path']}: {item.get('description', '')}"
        )

    categories_text = "\n".join(category_lines)

    return f"""
画像を確認して、最も近い分類を1つ選んでください。

分類は category_path として、以下の候補から必ず1つだけ選んでください。

{categories_text}

判断ルール:
- 実写写真は photo 系に分類してください。
- イラスト、漫画、アニメ絵、CG、生成AI画像は illust 系に分類してください。
- 人物が複数いる場合は、最も目立つ対象で判断してください。
- 性別がはっきりしない人物、風景、建物、食べ物、物体、UI、文字だけの画像は others 系にしてください。
- 判断が難しい場合は、最も近い分類を選び、confidenceを低めにしてください。
- 出力はJSONのみ。JSONの外に説明を書かないでください。
"""

実行

以下の6枚の画像を分類させてみる。
image.png

LOG
found images: 6
[1/6] D:\Pictures\img\ChatGPT Image 2026年6月19日 19_21_45.png
  -> illust/female confidence=0.95
[2/6] D:\Pictures\img\ChatGPT Image 2026年6月20日 23_21_33.png
  -> illust/male confidence=0.95
[3/6] D:\Pictures\img\ChatGPT Image 2026年6月22日 19_28_11.png
  -> illust/animal confidence=0.95
[4/6] D:\Pictures\img\ChatGPT Image 2026年6月22日 19_30_25.png
  -> photo/animal confidence=0.95
[5/6] D:\Pictures\img\生成画像1.png
  -> photo/others confidence=0.7
[6/6] D:\Pictures\img\生成画像3.png
  -> illust/animal confidence=0.9
saved: classification_result.csv

分類結果

photoフォルダ
image.png
illustフォルダ
image.png
ほぼばっちり!写実風の生成AI画像はphotoとして、ikaMarketのロゴはanimalとして認識されたようだ。写実風AI画像と実写画像を区別できるほどの精度はなさそう。(これはチャッピーのImage2.0を褒めるべきか)ただ、かなり写真っぽい犬の写実画像は精度0.95、若干嘘っぽい兼六園の写実画像は0.7と差があるので、精度でプロンプトを工夫したらいけるかもしれない。
かかった時間は一枚3秒~10秒くらい。精度0.7の兼六園画像が一番長くかかった。

まとめ

今のモデルであれば画像分類はそこそこのスペックがあれば十分可能。これから性能向上とサイズ縮小も見込めるだろうし、ぜひ活用していきたい。用途についても、例えばRAGでは実現が難しいサービスのために教師ありデータをローコストで作ってファインチューニング、あるいは機械学習に利用したりといろいろやれることが多そうである。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?