Vertex AIマルチモーダルを用いたミスミ部品の画像検索利用例紹介
はじめに
こんにちは。ミスミグループ本社Gateway推進本部の蘇です。
今回はGoogle CloudのVertex AIの気になっている機能を簡単に試してみましたので、
マルチモーダルエンベディングを使用して
画像やテキストをクエリとして渡し、商品画像を検索する例を紹介します。
インストール
今回はPythonでの実装になりますので、
google-cloud-aiplatform のPython Packageのインストールをする必要があります。
以下のコマンドでインストールを実行します。
pip3 install --upgrade --user "google-cloud-aiplatform>=1.38"
商品画像検索
マルチモーダルモデルの利点の一つとして、
テキスト、画像、ビデオといった異なる形式のデータを統合し、対応できることが挙げられます。
そのため、今回は画像とテキストのエンベディングを利用し、
類似度を計算することでシンプルな画像検索の実現を試みようと思います。
使用するモデル
2024/10/25現在、マルチモーダルエンベディングをサポートしているモデルはmultimodalembeddingとなります。
multimodalembeddingモデルで使用可能なデータについては、
公式ドキュメント-APIの使用
を参照してください。
以下のような関数で、テキスト、画像を簡単にエンベディングできます。
今回はデフォルトの1,408次元を使用しましたが、
model.get_embeddings()の引数にdimensionを追加することで、
128、256、512次元のベクトルにすることも可能です。
入力したデータ型に応じて、レスポンスクラスからの取得変数が異なります。
テキストはembeddings.text_embedding、画像はembeddings.image_embeddingを取得する必要があります。
なお、入力したデータ型と異なる変数には、Noneがセットされます。
from typing import Optional
import vertexai
from vertexai.vision_models import (
Image,
MultiModalEmbeddingModel,
MultiModalEmbeddingResponse,
)
def get_embeddings(
project_id: str,
location: str,
image_path: Optional[str] = None,
contextual_text: Optional[str] = None,
) -> MultiModalEmbeddingResponse:
"""Example of how to generate multimodal embeddings from image and text.
Args:
project_id: Google Cloud Project ID, used to initialize vertexai
location: Google Cloud Region, used to initialize vertexai
image_path: Path to image (local or Google Cloud Storage) to generate embeddings for.
contextual_text: Text to generate embeddings for.
"""
vertexai.init(project=project_id, location=location)
model = MultiModalEmbeddingModel.from_pretrained("multimodalembedding")
if image_path is not None:
image = Image.load_from_file(image_path)
else:
image = None
embeddings = model.get_embeddings(
image=image,
contextual_text=contextual_text,
)
#print(f"Image Embedding: {embeddings.image_embedding}")
#print(f"Text Embedding: {embeddings.text_embedding}")
return embeddings
エンベディング
事前に検索対象商品画像のエンベディングを行います。
以下は指定したフォルダー内の画像ファイルを取得し、エンベディングを行う処理となります。
import os
img_folder_path="xxx/"
img_extensions=[".png",".jpg",".jpeg"]
image_file_names= [f for f in os.listdir(img_folder_path) if os.path.splitext(f)[1].lower() in img_extensions ]
img_embedding_list=list()
for img_path in image_file_names:
embeddings=get_embeddings(PROJECT_ID,LOCATION,img_folder_path+img_path)
img_embedding_list.append( embeddings.image_embedding)
検索を行う際は商品画像をエンベディングした関数で、入力するテキストまたは画像をベクトル化します。
embeddings = model.get_embeddings(
#image=image,
contextual_text="xxx",
)
input_embedding=embeddings.text_embedding
例として、ベクトル化された取手の画像出力が以下となります。
[-0.00184696447, -0.0178980473, 0.0139843896, 0.0371479839, 0.0155481119, -0.00555663323......,
-0.0203117318, 0.00344911916, 0.00393320294, -0.0187874734, 0.0208226312]
類似度の計算
今回は簡単なdot積で入力ベクトルと商品ベクトルリストの類似度を計算し、スコア降順で並び替えました。
def dot_product_distance(
input_embedding: np.ndarray, embeddings: np.ndarray
) -> np.ndarray:
return np.dot(input_embedding, embeddings.T)
以下のように積を計算し、降順で並び替えさせます。
distances = dot_product_distance(
input_embedding=np.array(input_embedding), embeddings=np.array(img_embedding_list)
)
items= list(zip(image_file_names,distances))
sort_items = sorted(items, key= lambda x: x[1],reverse=True)
print(sort_items)
検索結果
ここで実際の検索結果を紹介します。
検索対象として、以下の商品画像を利用します。
入力クエリとして使われたボルト画像は以下となります。
結果の一覧が以下となります。
入力クエリ | 上位1位商品(及び類似度) | 上位2位商品(及び類似度) |
---|---|---|
ボルト(画像) | 六角穴付ボタンボルト(0.8396) | 引張りばね(0.5024) |
ボルト(テキスト) | 引張りばね(0.0770) | 六角穴付ボタンボルト( 0.0669) |
ブロック(テキスト) | スペーサブロック(0.0931) | 引張りばね( 0.0701) |
滑車(テキスト) | 吊り引戸用滑車( 0.0722) | 引張りばね( 0.0615) |
カラー(テキスト) | 樹脂カラー ツバ付タイプ(0.0846) | スペーサブロック( 0.0578) |
テキスト「ボルト」で検索した際に、
想定した「六角穴付ボタンボルト」より「引張りばね」の方が上位に来てしまいましたが、
概ね正しい商品が上位に表示されました。
おわりに
この記事では、Vertex AIマルチモーダルモデルの簡単な利用例をご紹介致しました。
今回展示された例では
商品情報は、商品の文字情報を使わず画像情報だけを使っていますが、
テキストでの検索に対して望む結果を返せていることがわかります。
ただし、今回は形状や色に明確な違いがある商品を使用していますが、
工業部品は機能性を重視すると似たような見た目や色になりがちです。
また、異なる機能を持つ商品でも似た見た目になることもあります。
そのため、一枚の平面画像だけを用いた検索は実用的には難しいかもしれません。
しかし、他の情報との組み合わせにより、
今後よりユーザー様にとって便利なサービスを提供する可能性が十分ありそうです。
なお、実用化する際には、
事前に商品のベクトル情報のインデックスを作成し、
Vertex AIのインデックスエンドポイントにデプロイすることで、精度の高い近似近傍探索を利用できます。
Discussion