CLIP - 画像分類(ラベルごとにスコア付け)

CLIPは、OpenAIが開発した画像とテキストの関連性をランク付けするニューラルネットワークです。

CLIPでは、自由にラベルを指定して画像分類を行うことができます。

Huggingface Transformersのインストール

CLIPは、Huggingface Transformersをインストールすることで使用できるようになります。

[Google Colaboratory]

1
!pip install transformers==4.6.0

Huggingface Transformersでは、以下のビジョンタスクのモデルアーキテクチャを使用できます。

  • Vision Transformer(Google AI)
  • DeiT(Facebook)
  • CLIP(OpenAI)

画像の準備

分類する画像として下記のものを使います。

この画像をGoogle Colaboratoryアップロードしておきます。

CLIPの準備

CLIPのモデルとプロセッサを準備し、判定用の画像を読み込みます。

[Google Colaboratory]

1
2
3
4
5
6
7
8
9
10
11
import torch
from transformers import CLIPProcessor, CLIPModel

# モデルとプロセッサの準備
model = CLIPModel.from_pretrained('openai/clip-vit-base-patch32')
processor = CLIPProcessor.from_pretrained('openai/clip-vit-base-patch32')

from PIL import Image

# 画像の読み込み
image = Image.open('cat.png')

動物名ラベルでの画像分類

ラベルを定義し、どのラベルのスコアが高いのか判定します。

ラベルは以下の3つを定義してみました。

  • cat
  • dog
  • human

[Google Colaboratory]

1
2
3
4
5
6
7
8
9
10
11
12
# ラベルの準備
labels = ['cat', 'dog', 'human']

# ラベルと画像をテンソルに変換
inputs = processor(text=labels, images=image, return_tensors='pt', padding=True)

# 推論
outputs = model(**inputs)
probs = outputs.logits_per_image.softmax(dim=1) # 3クラスのスコアの配列
predicted_class_idx = probs.argmax(-1).item() # スコアが最大のインデックス
print('class:', labels[predicted_class_idx]) # ラベルの表示
print('score:', probs) # スコアの表示

[実行結果]

class: cat
score: tensor([[0.9811, 0.0098, 0.0091]], grad_fn=)

catのスコアが1番高くなっており、きちんと画像判定できています。

色ラベルでの画像分類

色のラベルを準備し、再度スコアを出してみます。

  • black
  • white
  • red
  • brown

[Google Colaboratory]

1
2
3
4
5
6
7
8
9
10
11
12
# 色のラベルの準備
labels = ['black', 'white', 'red', 'brown']

# ラベルと画像をテンソルに変換
inputs = processor(text=labels, images=image, return_tensors='pt', padding=True)

# 推論
outputs = model(**inputs)
probs = outputs.logits_per_image.softmax(dim=1) # 3クラスのスコアの配列
predicted_class_idx = probs.argmax(-1).item() # スコアが最大のインデックス
print('class:', labels[predicted_class_idx]) # ラベルの表示
print('score:', probs) # スコアの表示

[実行結果]

class: red
score: tensor([[0.0249, 0.1160, 0.5005, 0.3586]], grad_fn=)

redのスコアが一番高いのですが、私の眼には茶色の猫に見えます。

もしかして背景色の赤がredのスコアを高めてしまったのでしょうか。

雰囲気ラベルでの画像分類

最後に雰囲気のラベルでスコア付けをします。

  • pampered
    甘やかされた
  • docile
    従順
  • tsundere
    ツンデレ
  • smart
    頭がいい
  • gentle
    優しい
  • sociable
    社交的

[Google Colaboratory]

1
2
3
4
5
6
7
8
9
10
11
12
# 雰囲気のラベルの準備
labels = ['pampered', 'docile', 'tsundere', 'smart', 'gentle', 'sociable']

# ラベルと画像をテンソルに変換
inputs = processor(text=labels, images=image, return_tensors='pt', padding=True)

# 推論
outputs = model(**inputs)
probs = outputs.logits_per_image.softmax(dim=1) # 3クラスのスコアの配列
predicted_class_idx = probs.argmax(-1).item() # スコアが最大のインデックス
print('class:', labels[predicted_class_idx]) # ラベルの表示
print('score:', probs) # スコアの表示

[実行結果]

class: docile
score: tensor([[0.0451, 0.7161, 0.0311, 0.0363, 0.1571, 0.0144]],
grad_fn=)

docile(従順)のスコアが一番高くなっているのですが、正直この写真の猫の雰囲気を判断するのは困難かと思います(;^_^A

Vision Transformer(Google AI)やDeiT(Facebook)のように、なんの画像かを判定するのとは違い、用意したラベルそれぞれのスコア(合致率)を導き出すのもなかなか興味深いですね。