あらゆる電子商取引プラットフォームの。ユーザーは関連性の高い結果が表示されることを期待しており、すぐに結果が得られることを望んでいます。このため、e コマース チームは、ユーザーの満足度を維持し、離脱を防ぐために、パフォーマンスと検索品質の両方を向上させるために常に取り組んでいます。
次の3枚の画像をご覧ください。

視覚的には同じように見えますが、これらの画像内のアイテムはまったく関係ありません。このコントラストは、画像検索の機能と固有の欠点の両方を示しています。
この記事で使用されているすべての画像は、実験やテストに使用する内部データベースからのものです。
画像検索の使用例の 1 つは、重複した商品を検出することです。製品のタイトルと説明は確かに重複を見つけるために使用できますが、一部のリストではまったく同じ画像を使用しながらわずかに (または完全に) タイトルが異なります。これらのリストを見つけることも非常に重要です。
通常、電子商取引プラットフォームでは何百万もの商品が提供されるため、あらゆる種類の検索を大規模に実行するには効率的なツールと方法が必要です。
この記事では、画像ベクトル埋め込みのベクトル データベースをセットアップする方法と、このデータベース内で検索する方法を説明します。また、ベクトルベースの画像検索の利点と制限についても詳しく説明します。
記事の大まかな概要は次のとおりです。
- 画像をベクトルに変換します。 ビジュアル データを検索可能な埋め込みに変換します。
- ミルバス コレクションを作成します。 Milvus コレクションをインストールします。これは、Milvus ベクトル データベース内のデータ編成の主要な論理単位です。
- 画像の検索: このコレクションから目的の画像を見つけます。
- 結果を解釈します。 いくつかの例を見て、検索結果を解釈してください。
まずはベクトルを取得しましょう。
画像をベクターに変換する
最初のステップは、画像を視覚データの数値表現であるベクトルに変換することです。ベクトル サイズは重要であり、最適なサイズはアプリケーションによって異なります。 128、512、または 768 次元の長さが一般的に選択されます。サイズを増やすと、より多くの情報が得られ、より正確な結果が期待できますが、その代償として、ストレージ サイズが大きくなり、場合によっては検索の待ち時間が長くなります。
画像をベクトルに変換するには、埋め込みモデルが必要です。独自のモデルをトレーニングすることもできますが、無料と有料の両方で、すぐに使用できるモデルが多数あります。
たとえば、次のコード ブロックは JPEG 画像を取得し、オープンソースの Clip-ViT-B-32 モデルを使用して 512 次元のベクトルに変換します。
from PIL import Image
from sentence_transformers import SentenceTransformer
sku_image = Image.open("sample_image.jpeg")
model = SentenceTransformer('clip-ViT-B-32')
image_vector = model.encode(sku_image)
type(image_vector), image_vector.shape
(numpy.ndarray, (512,))
image_vector 変数は、サイズ 512 の Numpy 配列です。
ミルバスコレクションを構築する
Milvus はベクトル データベースであり、Milvus のコレクションは固定の列と行を持つ 2 次元のテーブルです。各列はフィールドを表し、各行はエンティティ (この場合は画像) を表します。
ID フィールド (製品 SKU など) とその SKU のイメージに対応するベクター フィールドの 2 つのフィールドを持つコレクションを作成します。
コレクションを作成して操作するには、さまざまな方法があります。可能な限り Python を使用したいので、 pymilvus モジュール。
最初のステップは、クライアント オブジェクトを作成することです。これは、Milvus のベクター データベースに接続する方法です。
from pymilvus import MilvusClient, DataType
client = MilvusClient(uri="http://....") # your milvus db uri
次に、コレクションのスキーマを定義します。
schema = client.create_schema(auto_id=False, enable_dynamic_field=True)
# Add fields to schema
schema.add_field(field_name="sku_id", datatype=DataType.VARCHAR, max_length=512, is_primary=True)
schema.add_field(field_name="image_vector", datatype=DataType.FLOAT_VECTOR, dim=512)
スキーマには 2 つのフィールドがあります。 sku_id そして image_vector。
次に、次を使用してコレクションを作成できます create_collection 方法:
collection_name = "test_collection"
client.create_collection(
collection_name=collection_name,
schema=schema,
index_params=index_params
)
これで、フィールドにインデックスを追加できるようになりました。インデックスは、Milvus コレクションやベクター データベースにとって重要です。これにより、特に大規模なベクトル データセットを操作する場合に、検索速度が向上し、クエリのレイテンシが短縮されます。
インデックスを追加する代わりに、次のような方法があります。 create_index お祝い。
index_params = client.prepare_index_params()
# index for the image vector
index_params.add_index(
field_name="image_vector",
index_name="image_vector_idx",
index_type="IVF_FLAT",
metric_type="COSINE", # Using COSINE similarity (common for images). Can also be L2 or IP.
)
# index for "sku_id" (primary key)
index_params.add_index(
field_name="sku_id",
index_name="sku_id_idx",
index_type="INVERTED"
)
collection_name = "test_collection"
client.create_index(
collection_name=collection_name,
index_params=index_params
)
最後のステップでは、アーカイブをロードし、そのステータスを確認します。
client.load_collection(collection_name=collection_name)
# check load status
res = client.get_load_state(
collection_name=collection_name
)
print(res)
{'state': }
アーカイブを作成しましたが、現在は空です。新しいコレクションが正常に作成されたことを確認するには、データベース内のすべてのコレクションをリストします。 list_collections 方法
client.list_collections()
['test_collection']
次のステップは、エンティティ (つまり、sk とイメージ ベクトル) を挿入することです。
エンティティを挿入
これで、データをコレクションにロードできるようになりました。これを行うには、キーがコレクションのフィールド名に対応する辞書としてデータをフォーマットする必要があります。これらの辞書リストを使用して、複数のエンティティを一度に挿入できます。
以下に示すように、ベクトル データを Pandas DataFrame に保存しています。

私たちは使うことができます to_dict この DataFrame を、各辞書がコレクション内のエンティティを表す辞書のリストに変換するメソッド。
df.to_dict(orient='レコード')
[{'sku_id': 'HBCV00009LIR5S',
'image_vector': array([ 0.1206549 , 0.00597879, -0.07224327, 0.02327867, -0.09490156,
0.02150885, 0.10642719, -0.10139938, 0.03159734, 0.05613545,
-0.07615539, -0.15523671, -0.10006154, 0.05045145, 0.07733533,
-0.03749327, -0.02301577, 0.13337888, 0.00096778, 0.05047926,
...
Once we have all the entities as a list of dictionaries, we can use the insert method to load entities into our collection:
# convert dataframe to a list of dictionaries
data = df.to_dict(orient="records")
# insert data into collection
res = client.insert(
collection_name=collection_name,
data=data
)
print(res)
{'insert_count': 10000, 'ids': ['HBCV00009LIR5S', 'HBCV00001U46VH' ...]
先ほど 10,000 個のエンティティをロードしましたが、コレクションには通常、さらに多くのデータ (例: 数百万のエンティティ) が含まれています。何百万ものベクトルを一度にロードすることはできません。このような場合、データをバッチに分割し、それらをコレクションに順番に読み込むことができます。たとえば、以下のループはデータフレーム全体を反復し、バッチごとに 10,000 個のエンティティを挿入します。
batch_size = 10000
for i in range(0, len(df), batch_size):
data = df.iloc[i:i+batch_size,].to_dict(orient="records")
res = client.insert(
collection_name=collection_name,
data=data
)
これで、SKU データとベクター データを含むコレクションができました。次のステップは、このコレクション内の画像を検索することです。
画像検索
画像を検索するには、まず画像をコレクションに保存されているベクトルと同じサイズのベクトルに変換する必要があります。
Milvus には、基本検索、カテゴリ検索、ハイブリッド検索などのさまざまな検索方法があります。基本的な検索を実行します。これは、実際には近似最近傍 (ANN) 検索です。検索で使用されたクエリ ベクトルに基づいてベクトル埋め込みのサブセットを検索し、クエリ ベクトルとサブセット内のベクトルを比較して、最も類似した結果を返します。
次のコード ブロックは、JPEG 画像を読み取り、コレクションの作成時に使用したものと同じモデルを使用してベクトルに変換し、コレクション内でこの画像ベクトルを検索します。
collection_name = "test_collection"
model = SentenceTransformer('clip-ViT-B-32')
search_image = Image.open("image_to_search.jpeg")
search_image_vector = model.encode(search_image)
res = client.search(
collection_name=collection_name,
anns_field="image_vector",
data=[search_image_vector],
limit=3,
search_params={"metric_type": "COSINE"}
)
anns_field このパラメーターは、検索で使用されるベクトル フィールドを指定します。次に、ターゲット画像ベクトルを渡します data パラメータ。 limit このパラメーターは、返す結果の数を Milvus に指示します (つまり、3 番目のコレクションで最も類似した 3 つのベクトルを返します)。
の出力 search メソッド辞書のリストは次のとおりです。
print(res[0])
[{'my_id': 'HBCV0000BLJIBF', 'distance': 0.9814613848423661, 'entity': {}}
{'my_id': 'HBCV00003Z49OT', 'distance': 0.9504563808441162, 'entity': {}}
{'my_id': 'HBCV0000DCK7ML', 'distance': 0.9104360342025757, 'entity': {}}]
結果は確認中です
ベクトルを使用した画像検索は非常に効率的かつ正確です。まったく同じ画像 (またはよく似た画像) がコレクション内に存在する場合、ほぼ確実にそれを見つけることができます。
以下の例では、一番左の画像が検索対象の画像で、残りの画像が上位の検索結果になります。
同じ画像
次の例では、コレクション内に同じ画像が複数存在し、ベクトル検索でそれらを見つけることができました。


類似画像および関連画像
以下の例では、取得された画像が非常に類似しており、ターゲット画像に直接関連していることがはっきりとわかります。


似ているが無関係な画像
場合によっては、ベクトル検索により、視覚的には似ているものの、文脈上はまったく関係のない画像が見つかることがあります。そのような場合の例を次に示します。

検索された画像はバススポンジですが、似たようなぬいぐるみも検索結果に含まれます。
視覚的には似ているが、まったく関係のない画像を含む例をさらにいくつか示します。


ベクトル データベースでの画像検索は、多くの場合に非常に役立ちます。類似した画像や類似した外観を持つ画像を簡単に検出できます。ただし、上記の例に見られるように、視覚的な類似性は、必ずしも製品が類似している、あるいは関連していることを示すわけではありません。
電子商取引プラットフォームの画像検索のもう 1 つの制限は、まったく異なる製品がまったく同じ画像を共有する可能性があることです。たとえば、スマートフォンを考えてみましょう。多くの異なるモデルは、外観はほぼ同じに見えます。製品タイトルやモデル名などの追加のコンテキストを使用せずに画像検索のみに依存すると、誤解を招く結果が簡単に得られる可能性があります。
画像検索の上記の欠点を克服する解決策として、画像ベクトルとテキスト ベクトルを組み合わせたハイブリッド検索を実装できます。ハイブリッド検索により、結果が視覚的に類似しているだけでなく、概念的にも正確であることが保証されます。
次の記事では、複数のベクトル フィールドを含む Milvus コレクションを作成する方法とハイブリッド検索を実行する方法を段階的に説明します。また、この記事の同様の例を使用してこのアプローチをテストし、ハイブリッド検索が無関係な検索結果をどのように排除するかを確認します。
読んでいただきありがとうございます!ご意見がございましたら、お知らせください。








Leave a Reply