ONNX와 Milvus를 사용하여 이미지 검색을 위한 AI 모델 결합하기
오픈 신경망 교환(ONNX)은 머신러닝 모델을 표현하기 위해 만들어진 개방형 형식입니다. 2017년 오픈소스화된 이후, ONNX는 머신러닝 및 딥러닝 모델을 위한 빌딩 블록을 제공하는 AI 표준으로 발전해 왔습니다. ONNX는 AI 개발자가 다양한 프레임워크, 도구, 런타임, 컴파일러에서 모델을 사용할 수 있도록 공통 파일 형식을 정의하며, 인공지능 커뮤니티의 혁신 속도를 높이는 데 도움을 줍니다.
Milvus는 유연성과 안정성이 뛰어나고 속도가 매우 빠른 오픈 소스 벡터 데이터베이스입니다. 벡터의 추가, 삭제, 업데이트 및 거의 실시간에 가까운 검색을 지원합니다. Milvus는 포괄적인 직관적인 API 세트와 널리 채택된 여러 인덱스 라이브러리(예: Faiss, NMSLIB, Annoy)를 지원하여 주어진 시나리오에 대한 인덱스 선택을 간소화합니다. Milvus는 사용이 간편하며 이미지, 오디오, 비디오 검색, 추천, 챗봇, 신약 검색 등 전 세계 수백 개의 조직과 기관에서 사용되고 있습니다.
이 글에서는 ONNX와 Milvus를 기반으로 이미지 검색에 여러 모델을 사용하는 방법을 소개합니다. VGG16과 ResNet50 모델을 예로 들어, ONNX를 사용해 다양한 AI 모델을 실행하여 특징 벡터를 생성하고, 마지막으로 Milvus에서 특징 벡터 검색을 수행하여 유사한 이미지를 반환하는 방법을 설명합니다.
ONNX로 모델 처리하기
ONNX 형식은 AI 모델 간에 쉽게 교환할 수 있습니다. 예를 들어, 텐서플로우 모델을 ONNX 포맷으로 변환하여 카페 환경에서 실행할 수 있습니다. 이 예제에서는 Keras 프레임워크에서 사전 학습된 ResNet50 모델을 ONNX 형식으로 변환한 다음, VGG16 모델을 ONNX 형식으로 호출하여 다른 모델을 분석합니다.
keras.applications.resnet50에서 ResNet50을 가져옵니다.
tensorflow를 tf로 가져옵니다.
# keras-resnet50 모델을 로드하고 플로더로 저장하기
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' 객체에 'graph' 속성이 없습니다'라는 오류가 반환됩니다. 그런 다음 Python의 Bash 명령을 사용하여 스택 오버플로의 솔루션에 따라 변환할 수 있습니다.
모델을 사용하여 특징 벡터 추출하기
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(None, feed)[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")
벡터 데이터 저장
사진과 같은 비정형 데이터는 컴퓨터가 직접 처리할 수 없지만, 인공지능 모델을 통해 벡터로 변환한 후 컴퓨터로 분석할 수 있습니다. 밀버스 벡터 데이터베이스는 대용량 비정형 데이터 분석이 가능하도록 설계되었습니다. 벡터 데이터를 저장하고 실시간에 가까운 분석을 수행할 수 있습니다. 먼저 Milvus에서 해당 모델의 컬렉션을 생성한 다음 이미지 벡터를 삽입합니다.
에서 밀버스 가져오기 *'
# 밀버스에서 컬렉션 생성
milvus.create_collection(resnet_collection_param)
milvus.create_collection(vgg_collection_param)
# 밀버스에 데이터를 삽입하고 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와 이미지 경로의 키-값을 저장합니다.
import 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를 반환한 다음 Redis에서 해당 ID에 해당하는 이미지를 찾습니다.
# 밀버스에서 검색하고 유사한 ID를 가진 결과를 반환합니다.
def search_in_milvus(collection_name, search_vector):
status, results = milvus.search(collection_name, TOP_K, [search_vector])
print(status)
re_ids = [results[0] 중 x.id for x]]
re_distance = [results[0]에서 x에 대한 x.distance]]
반환 re_ids, re_distance
# 결과 ID에 따라 이미지 가져오기
def get_sim_imgs(collection_name, search_vector):
ids, distance = search_in_milvus(collection_name, search_vector)
img = [ids의 i에 대해 red.get(i).decode("utf-8")]
반환 ids, distance, img
이 문서에서는 VGG16과 ResNet50 모델을 예로 들어 ONNX를 통해 여러 모델을 처리하고 유사한 벡터 검색을 위해 여러 모델을 Milvus와 결합하여 유사한 이미지를 얻는 방법을 보여줍니다. 위의 두 모델은 특징 벡터를 빠르게 추출할 수 있는 Keras 프레임워크를 기반으로 합니다. 노트북에서 이 두 모델을 기반으로 Milvus가 COCO 데이터 세트에서 사진을 검색한 결과는 비슷하지만 유클리드 거리는 같지 않다는 것을 알 수 있습니다. 다른 데이터 집합을 사용하여 두 모델의 검색 결과를 비교해 볼 수도 있습니다.
Milvus는 대규모 비정형 데이터에서 생성된 특징 벡터를 처리하는 데 사용할 수 있는 고성능, 고가용성 벡터 데이터베이스입니다. 더 많은 솔루션은 Milvus 부트캠프를 참조하세요.
참고 자료
- https://github.com/onnx/onnx
- https://onnx.ai/
- https://milvus.io/cn/
- https://github.com/milvus-io/bootcamp
저자 소개
질리즈의 데이터 엔지니어인 시유 첸은 시디안 대학교에서 컴퓨터 공학을 전공했습니다. 질리즈에 입사한 이후 오디오 및 비디오 분석, 분자식 검색 등 다양한 분야에서 밀버스의 솔루션을 연구해 왔으며, 이를 통해 커뮤니티의 적용 시나리오를 크게 풍성하게 만들었습니다. 그녀는 현재 더 흥미로운 솔루션을 모색하고 있습니다. 여가 시간에는 스포츠와 독서를 좋아합니다.
계속 읽기

Storage Cost Isn’t the Whole Story: Why We Disagree with Turbopuffer’s Trade-offs
A real-world benchmark comparing Turbopuffer and Zilliz Cloud on cost, latency, recall, and consistency for production-scale vector search workloads.

Introducing Zilliz Cloud Global Cluster: Region-Level Resilience for Mission-Critical AI
Zilliz Cloud Global Cluster delivers multi-region resilience, automatic failover, and fast global AI search with built-in security and compliance.

Zilliz Cloud BYOC Upgrades: Bring Enterprise-Grade Security, Networking Isolation, and More
Discover how Zilliz Cloud BYOC brings enterprise-grade security, networking isolation, and infrastructure automation to vector database deployments in AWS
