画像類似性比較 CLIP または DINOv2

画像類似性比較 CLIP または DINOv2

人工知能の分野において、コンピューター ビジョンの 2 大巨頭は CLIP と DINOv2 です。 CLIP は画像理解の方法を変え、DINOv2 は自己教師学習に新しい方法をもたらしました。この記事では、CLIP と DINOv2 の強みと繊細さを定義する経緯を探ります。私たちの目的は、これらのモデルのうちどれが画像類似性タスクの世界で本当に優れているかを明らかにすることです。これら 2 つの巨人の戦いを目の当たりにし、どちらのモデルが勝利するかを見てみましょう。

CLIPにおける画像の類似性

CLIP を使用して 2 つの画像間の類似度を計算するのは、2 つのステップのみを必要とする簡単なプロセスです。最初に 2 つの画像の特徴を抽出し、次にそれらのコサイン類似度を計算します。

まず、必要なパッケージがインストールされていることを確認します。仮想環境をセットアップして使用することをお勧めします。

 #Start by setting up a virtual environment virtualenv venv-similarity source venv-similarity/bin/activate #Install required packages pip install transformers Pillow torch

次に、画像の類似性を計算し続けます。

 import torch from PIL import Image from transformers import AutoProcessor, CLIPModel import torch.nn as nn device = torch.device('cuda' if torch.cuda.is可用else "cpu") processor = AutoProcessor.from_pretrained("openai/clip-vit-base-patch32") model = CLIPModel.from_pretrained("openai/clip-vit-base-patch32").to(device) #Extract features from image1 image1 = Image.open('img1.jpg') with torch.no_grad(): inputs1 = processor(images=image1, return_tensors="pt").to(device) image_features1 = model.get_image_features(**inputs1) #Extract features from image2 image2 = Image.open('img2.jpg') with torch.no_grad(): inputs2 = processor(images=image2, return_tensors="pt").to(device) image_features2 = model.get_image_features(**inputs2) #Compute their cosine similarity and convert it into a score between 0 and 1 cos = nn.CosineSimilarity(dim=0) sim = cos(image_features1[0],image_features2[0]).item() sim = (sim+1)/2 print('Similarity:', sim)

類似画像 2 件

2 つの類似画像を例にすると、達成された類似度スコアは驚異的な 96.4% でした。

DINOv2における画像の類似性

DINOv2 を使用して 2 つの画像間の類似度を計算するプロセスは、CLIP と似ています。同じパッケージセットが必要であり、追加のインストールは必要ありません。

 from transformers import AutoImageProcessor, AutoModel from PIL import Image import torch.nn as nn device = torch.device('cuda' if torch.cuda.is_available() else "cpu") processor = AutoImageProcessor.from_pretrained('facebook/dinov2-base') model = AutoModel.from_pretrained('facebook/dinov2-base').to(device) image1 = Image.open('img1.jpg') with torch.no_grad(): inputs1 = processor(images=image1, return_tensors="pt").to(device) outputs1 = model(**inputs1) image_features1 = outputs1.last_hidden_state image_features1 = image_features1.mean(dim=1) image2 = Image.open('img2.jpg') with torch.no_grad(): inputs2 = processor(images=image2, return_tensors="pt").to(device) outputs2 = model(**inputs2) image_features2 = outputs2.last_hidden_state image_features2 = image_features2.mean(dim=1) cos = nn.CosineSimilarity(dim=0) sim = cos(image_features1[0],image_features2[0]).item() sim = (sim+1)/2 print('Similarity:', sim)

CLIP の例と同じ画像ペアを使用した場合、DINOv2 を使用して 93% の類似度スコアが得られました。

COCOデータセットを使用してテスト済み

パフォーマンスの評価に入る前に、COCO データセットの検証セットの画像を使用して、CLIP と DINOv2 の結果を比較してみましょう。私たちが使用するプロセスは次のとおりです。

  • データセットを反復処理して、すべての画像の特徴を抽出します。
  • 埋め込みを FAISS インデックスに保存します。
  • 入力画像の特徴を抽出します。
  • 最も類似した 3 つの画像を取得します。

FAISS について詳しく知りたい方は、こちらの記事をご覧ください。最初に、pip install faiss-[gpu|cpu] コマンドを使用してインストールしてください。

パート 1: 特徴抽出と 2 つのインデックスの作成:

 import torch from PIL import Image from transformers import AutoProcessor, CLIPModel, AutoImageProcessor, AutoModel import faiss import os import numpy as np device = torch.device('cuda' if torch.cuda.is_available() else "cpu") #Load CLIP model and processor processor_clip = AutoProcessor.from_pretrained("openai/clip-vit-base-patch32") model_clip = CLIPModel.from_pretrained("openai/clip-vit-base-patch32").to(device) #Load DINOv2 model and processor processor_dino = AutoImageProcessor.from_pretrained('facebook/dinov2-base') model_dino = AutoModel.from_pretrained('facebook/dinov2-base').to(device) #Retrieve all filenames images = [] for root, dirs, files in os.walk('./val2017/'): for file in files: if file.endswith('jpg'): images.append(root + '/'+ file) #Define a function that normalizes embeddings and add them to the index def add_vector_to_index(embedding, index): #convert embedding to numpy vector = embedding.detach().cpu().numpy() #Convert to float32 numpy vector = np.float32(vector) #Normalize vector: important to avoid wrong results when searching faiss.normalize_L2(vector) #Add to index index.add(vector) def extract_features_clip(image): with torch.no_grad(): inputs = processor_clip(images=image, return_tensors="pt").to(device) image_features = model_clip.get_image_features(**inputs) return image_features def extract_features_dino(image): with torch.no_grad(): inputs = processor_dino(images=image, return_tensors="pt").to(device) outputs = model_dino(**inputs) image_features = outputs.last_hidden_state return image_features.mean(dim=1) #Create 2 indexes. index_clip = faiss.IndexFlatL2(512) index_dino = faiss.IndexFlatL2(768) #Iterate over the dataset to extract features X2 and store features in indexes for image_path in images: img = Image.open(image_path).convert('RGB') clip_features = extract_features_clip(img) add_vector_to_index(clip_features,index_clip) dino_features = extract_features_dino(img) add_vector_to_index(dino_features,index_dino) #store the indexes locally faiss.write_index(index_clip,"clip.index") faiss.write_index(index_dino,"dino.index")

パート2: 画像の類似性検索:

 import faiss import numpy as np import torch from transformers import AutoImageProcessor, AutoModel, AutoProcessor, CLIPModel from PIL import Image import os #Input image source='laptop.jpg' image = Image.open(source) device = torch.device('cuda' if torch.cuda.is_available() else "cpu") #Load model and processor DINOv2 and CLIP processor_clip = AutoProcessor.from_pretrained("openai/clip-vit-base-patch32") model_clip = CLIPModel.from_pretrained("openai/clip-vit-base-patch32").to(device) processor_dino = AutoImageProcessor.from_pretrained('facebook/dinov2-base') model_dino = AutoModel.from_pretrained('facebook/dinov2-base').to(device) #Extract features for CLIP with torch.no_grad(): inputs_clip = processor_clip(images=image, return_tensors="pt").to(device) image_features_clip = model_clip.get_image_features(**inputs_clip) #Extract features for DINOv2 with torch.no_grad(): inputs_dino = processor_dino(images=image, return_tensors="pt").to(device) outputs_dino = model_dino(**inputs_dino) image_features_dino = outputs_dino.last_hidden_state image_features_dino = image_features_dino.mean(dim=1) def normalizeL2(embeddings): vector = embeddings.detach().cpu().numpy() vector = np.float32(vector) faiss.normalize_L2(vector) return vector image_features_dino = normalizeL2(image_features_dino) image_features_clip = normalizeL2(image_features_clip) #Search the top 5 images index_clip = faiss.read_index("clip.index") index_dino = faiss.read_index("dino.index") #Get distance and indexes of images associated d_dino,i_dino = index_dino.search(image_features_dino,5) d_clip,i_clip = index_clip.search(image_features_clip,5)

結果

4 つの異なる画像を入力として使用して検索すると、次の結果が生成されました。

CLIP と DINOv2

この小さなサブセットでは、DINOv2 がわずかに優れたパフォーマンスを示しているようです。

DISC21データセットのベンチマーク

それぞれのパフォーマンスを比較するために、この記事で説明されているのと同じ方法論に従います: https://medium.com/aimonks/image-similarity-with-dinov2-and-faiss-741744bc5804。上記のスクリプトを繰り返して特徴を抽出し、画像の類似性を計算します。

データセット

CLIP と DINOv2 を比較するために、画像類似性検索用に特別に作成された DISC21 データセットを選択しました。サイズが 350 GB と大きいため、150,000 枚の画像のサブセットを使用します。

使用される指標

指標に関しては、次のことを計算します。

  • 精度: 正しく予測された画像の数と画像の総数の比率。
  • トップ 3 精度: 類似する上位 3 つの画像に正しい画像が見つかった回数と画像の総数の比率。
  • 計算時間: データセット全体を処理するために必要な時間。

ベンチマーク結果

(1)特徴抽出

  • CLIP: 1 秒あたり 70.7 枚の画像を処理
  • DINOv2: 1秒あたり69.7枚の画像を処理

(2)精度とトップ3の精度

精度とトップ3の精度

(3)分析結果

どちらのモデルも画像を正しく予測しました。

すべてのモデルが正しい画像を見つけることができませんでした:

CLIP のみが正しく画像を予測し、DINOv2 は上位 3 つを予測しました。

DINOv2 のみが正しく画像を予測しました:

分析する

DINOv2 は明らかにリードしており、明らかに難しいデータセットで 64% という驚異的な精度を達成しました。対照的に、CLIP は 28.45% というより控えめな精度を示しました。

計算効率の点では、両方のモデルは非常に類似した特徴抽出時間を示します。このバランスにより、この点でいずれかのモデルに明確な優位性がもたらされるわけではありません。

制限

このベンチマークは貴重な洞察を提供しますが、その限界を認識する必要があります。評価は、150,000 枚の画像のプールと比較した 1,448 枚の画像のサブセットに対して実行されます。データセット全体のサイズが 210 万枚の画像であることを考えると、リソースを節約するには焦点を絞る必要があります。

MetaAI が DISC21 データセットをモデルのベンチマークとして使用したことは注目に値します。これが DINOv2 に有利な点を与えた可能性があります。しかし、COCO データセットでのテストでは興味深い詳細が明らかになりました。DINOv2 は画像内の主要な要素を識別する機能が強化されており、CLIP は入力画像内の特定の詳細に焦点を当てる機能を示しています (バス画像を参照)。

最後に、CLIP と DINOv2 の埋め込み次元の違いを考慮する必要があります。 CLIP は 512 の埋め込み次元を使用しますが、DINOv2 は 768 を使用します。別のオプションとして、埋め込み寸法が一致するより大きな CLIP モデルを使用することがありますが、速度が犠牲になることに注意してください。小さなサブセットでの簡単なテストでは、わずかなパフォーマンスの向上が見られましたが、DINOv2 で実証されたパフォーマンス レベルには達しませんでした。

<<:  製造業における AI 活用事例 10 選

>>:  AIがデータ分析を拡張し、効率化する方法

ブログ    
ブログ    

推薦する

ビッグモデルが明らかに:ユーザーレビューから金脈を抽出する方法

著者 | 崔昊レビュー | Chonglouまとめこの論文では、大規模な言語モデルと LangCha...

大学生が、1時間で600本の鉄筋を結束できる鉄筋結束ロボットを発明。建設労働者は再び失業することになるのだろうか?

人工知能の発展により、肉体労働のみに頼っている労働者の中には、徐々に失業に直面している者もいる。例え...

C# データ構造のソートアルゴリズム

C# データ構造ソート アルゴリズム (バブル ソートを含む) では、Lao Zhao の Code...

研究機関が新しいレポートでAIの売り手側と買い手側の成功への道筋を定義

調査会社ストラテジー・アナリティクスは新たな報告書の中で、人工知能製品のベンダーとそのユーザーの両方...

...

...

2019 年の IT およびビッグデータ業界のトレンドを理解する

2018年ももうすぐ終わりです。今年は、ブロックチェーン、5G、チップ、量子コンピューティングが、誰...

マルチタスクでSOTA、UBCを実現 Googleなどが3Dポイントクラウド向けの教師なしカプセルネットワークを提案

これは、3D ポイント クラウド用に提案された教師なしカプセル アーキテクチャであり、3D ポイント...

...

Toutiaoのアルゴリズムロジックを使用してMacOSを再設計しました

仕事以外では、私はほとんどの時間を2つの状態で過ごしています。1つは見出しを閲覧している状態で、もう...

ディープラーニングを使って夢に現れる物体を分析する(完全版)

[[197493]]この記事の主な内容は機械学習と神経科学を組み合わせたものであり、読者にはこれら...

国内大学がSORA型VDTを開発、汎用ビデオ拡散トランスフォーマーがICLR2024に採択

2月16日のOpenAI Soraのリリースは、間違いなくビデオ生成の分野における大きな進歩を示しま...

スマート農業は収穫アシスタントとなる新しいアップグレードロボットを歓迎する

「農業」は国家の基盤です。基盤がしっかりしていれば国家は平和になります。農業は国民経済の建設と発展を...

1 つの記事で RNN (リカレント ニューラル ネットワーク) の基礎を理解する

[[211628]] 1. ニューラルネットワークの基礎ニューラル ネットワークは、あらゆる関数に適...