ONNXとMilvusを使った画像検索のためのAIモデルの組み合わせ

Open Neural Network Exchange(ONNX)は、機械学習モデルを表現するために構築されたオープンフォーマットである。2017年にオープンソース化されて以来、ONNXはAIの標準として発展し、機械学習や深層学習モデルのビルディングブロックを提供している。ONNXは、AI開発者がさまざまなフレームワーク、ツール、ランタイム、コンパイラでモデルを使用できるようにするための共通のファイルフォーマットを定義しており、人工知能コミュニティにおけるイノベーションのスピードアップに貢献しています。
Milvusはオープンソースのベクトルデータベースで、柔軟性、信頼性、高速性に優れています。ベクターの追加、削除、更新、ほぼリアルタイムの検索をサポートしています。Milvusは直感的なAPIの包括的なセットを持ち、広く採用されている複数のインデックスライブラリ(Faiss、NMSLIB、Annoyなど)をサポートしているため、与えられたシナリオに対するインデックスの選択を簡素化することができます。Milvusは使いやすく、画像、音声、動画検索、レコメンデーション、チャットボット、新薬検索など、世界中の何百もの組織や機関で使用されています。
この記事では、ONNXとMilvusをベースに、画像検索に複数のモデルを使う方法を紹介する。VGG16とResNet50モデルを例にとり、ONNXを使って異なるAIモデルを実行し、特徴ベクトルを生成し、最後にMilvusで特徴ベクトル検索を実行し、類似画像を返します。
ONNXでモデルを処理する
ONNXフォーマットはAIモデル間で簡単に交換できる。例えば、TensorFlowモデルをONNX形式に変換し、Caffe環境で実行することができる。この例では、Kerasフレームワークの下で事前に訓練されたResNet50モデルをONNX形式に変換し、異なるモデルを分析するためにONNX形式でVGG16モデルを呼び出します。
from keras.applications.resnet50 import ResNet50
import tensorflow as tf
# keras-resnet50モデルをロードし、floderとして保存する。
model_resnet50 = ResNet50(include_top=False, pooling='max', weights='imagenet')
tf.saved_model.save(model_resnet50, "keras_resnet50_model")
# resnet50モデルをonnxに変換
python -m tf2onnx.convert --saved-model "keras_resnet50_model" --output "onnx_resnet50.onnx"
注意:インターフェイス keras2onnx.convert_keras(model, model.name)
を使ってモデルを変換すると、AttributeError:'KerasTensor' object has no attribute'graph'
というエラーが返ってくる。そこで、PythonのBashコマンドを使って、Stack Overflowの解答に従って変換する。
モデルを使った特徴ベクトルの抽出
ResNet50のモデルをONNX形式に変換した後、推論により画像の特徴ベクトルを直接抽出することができます。 注意:特徴ベクトルは抽出後に正規化する必要があります。
# 画像ベクトルをonnxモデルで取得する。
def get_onnx_vectors(onnx_model, img_path):
img = image.load_img(img_path, target_size=(224, 224))
x = image.img_to_array(img)
x = np.expand_dims(x, axis=0)
x = preprocess_input(x)
sess = onnxruntime.InferenceSession(onnx_model)
x = x if isinstance(x, list) else [x].
feed = dict([(input.name, x[n]) for n, input in enumerate(sess.get_inputs())])
feat = sess.run(なし, フィード)[0].
norm_feat = feat[0] / LA.norm(feat[0])
norm_feat = [i.item() for i in norm_feat].
return norm_feat
ONNX 形式の VGG16 モデルを使って画像データを処理する:
# ResNet50 と VGG16 ONNX モデルでベクトルを生成
2vec_resnet = get_onnx_vectors("onnx_resnet50.onnx", "./pic/example.jpg")
3vec_vgg = get_onnx_vectors("onnx_vgg16.onnx", "./pic/example.jpg")
ベクターデータの保存
写真のような非構造化データはコンピュータで直接処理することはできませんが、AIモデルを通してベクトルに変換し、コンピュータで分析することができます。Milvusベクトルデータベースは、大規模な非構造化データ分析に威力を発揮するように設計されています。ベクトルデータを保存し、ほぼリアルタイムで分析を行うことができる。 まず、Milvusに対応するモデルのコレクションを作成し、画像ベクトルを挿入します。
from milvus import *.
# Milvusでコレクションを作成する
milvus.create_collection(resnet_collection_param)
milvus.create_collection(vgg_collection_param)
# データをMilvusに挿入し、IDを返す
status, resnet_ids = milvus.insert(resnet_collection_name, resnet_vectors)
status, vgg_ids = milvus.insert(vgg_collection_name, vgg_vectors)
データの挿入に成功すると、Milvusはベクターに対応するIDを返すので、IDから画像を探すことができる。今回使用したMilvus 1.1はスカラーフィルタリングをサポートしていないため(Milvus 2.0ではサポートされている)、Redisを使用してベクトルIDと画像パスのkey-valueを保存している。
インポート redis
def img_ids_to_redis(img_directory, res_ids):
for img, ids in zip(images, res_ids):
redis.set(ids, img)
類似画像の検索
データを保存した後、ベクトルを取り出すことができます。Milvusはユークリッド距離、内積距離、ハミング距離など複数の距離計算方法をサポートしています。本記事の類似画像検索では、Milvusのベクトル間のユークリッド距離計算を採用し、類似ベクトルIDを返し、そのIDに対応する画像をRedisから検索します。
# Milvusで検索し、類似した結果をidで返す
def search_in_milvus(collection_name, search_vector):
status, results = milvus.search(collection_name, TOP_K, [search_vector])
print(status)
re_ids = [x.id for x in results[0]] (x.id for x in results[0])
re_distance = [x.distance for x in results[0]] (x.distance for x in results[0])
return re_ids, re_distance
# 結果のidに応じた画像を取得
def get_sim_imgs(collection_name, search_vector):
ids, distance = search_in_milvus(collection_name, search_vector)
img = [red.get(i).decode("utf-8") for i in ids].
return ids, distance, img
VGG16モデルとResNet50モデルを例に、ONNXで複数のモデルを処理し、Milvusで複数のモデルを組み合わせて類似ベクトル検索を行い、類似画像を取得する例を紹介する。上記2つのモデルは、特徴ベクトルを高速に抽出できるKerasフレームワークをベースにしている。この2つのモデルに基づいてCOCOデータセットからMilvusで画像を検索した結果は似ているものの、ユークリッド距離は同じではないことがNotebookからわかります。他のデータセットを使って2つのモデルの検索結果を比較することもできます。
Milvusは、大量の非構造化データから生成された特徴ベクトルを処理するために使用できる、高性能で可用性の高いベクトルデータベースです。より詳しいソリューションについては、Milvus bootcampを参照してください。
参考文献
- https://github.com/onnx/onnx
- https://onnx.ai/
- https://milvus.io/cn/
- https://github.com/milvus-io/bootcamp
##著者について 西安大学コンピューターサイエンス学部卒業。Zillizに入社以来、音声・動画解析、分子式検索など、様々な分野でMilvusのソリューションを探求し、コミュニティの応用シナリオを大いに豊かにしてきた。現在、さらに興味深いソリューションを探求中。趣味はスポーツと読書。
読み続けて

Vector Databases vs. Key-Value Databases
Use a vector database for AI-powered similarity search; use a key-value database for high-throughput, low-latency simple data lookups.

DeepSeek Always Busy? Deploy It Locally with Milvus in Just 10 Minutes—No More Waiting!
Learn how to set up DeepSeek-R1 on your local machine using Ollama, AnythingLLM, and Milvus in just 10 minutes. Bypass busy servers and enhance AI responses with custom data.

Building a RAG Application with Milvus and Databricks DBRX
In this tutorial, we will explore how to build a robust RAG application by combining the capabilities of Milvus, a scalable vector database optimized for similarity search, and DBRX.