🚀 免费试用 Zilliz Cloud,完全托管的 Milvus,体验 10 倍的性能提升!立即试用>

milvus-logo
LFAI

用 ONNX 处理模型

  • Engineering
September 26, 2021

开放神经网络交换(ONNX)是一种用于表示机器学习模型的开放格式。自 2017 年开源以来,ONNX 已发展成为人工智能的标准,为机器学习和深度学习模型提供了构建模块。ONNX 定义了一种通用文件格式,使人工智能开发人员能够使用各种框架、工具、运行时和编译器来使用模型,有助于提高人工智能界的创新速度。

Milvus 是一个开源向量数据库,具有高度灵活性、可靠性和极快的速度。它支持矢量的添加、删除、更新和近乎实时的搜索。Milvus 拥有一整套直观的应用程序接口,支持多个广泛采用的索引库(如 Faiss、NMSLIB 和 Annoy),简化了特定场景的索引选择。Milvus 使用简单,已在全球数百家组织和机构中得到应用,包括图像、音频和视频搜索、推荐、聊天机器人、新药搜索等。

本文将介绍如何基于 ONNX 和 Milvus 使用多种模型进行图像搜索。它以 VGG16 和 ResNet50 模型为例,利用 ONNX 运行不同的人工智能模型生成特征向量,最后在 Milvus 中执行特征向量检索,返回相似图像。

用 ONNX 处理模型

人工智能模型之间可以轻松交换 ONNX 格式。例如,TensorFlow 模型可以转换为 ONNX 格式,并在 Caffe 环境中运行。在本例中,我们将 Keras 框架下预训练的 ResNet50 模型转换为 ONNX 格式,然后调用 ONNX 格式的 VGG16 模型来分析不同的模型。

from keras.applications.resnet50 import ResNet50
import tensorflow as tf

# load keras-resnet50 model and save as a floder
model_resnet50 = ResNet50(include_top=False, pooling='max', weights='imagenet')
tf.saved_model.save(model_resnet50, "keras_resnet50_model")

# convert resnet50 model to 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' 。然后,我们可以根据 Stack Overflow 上的解决方案,使用 Python 的 Bash 命令进行转换。

使用模型提取特征向量

将 ResNet50 模型转换为 ONNX 格式后,可以直接通过推理提取图片的特征向量。注意:提取后需要对特征向量进行归一化处理。

# get the image vectors with onnx model
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 模型处理图像数据:

# generate vectors with ResNet50 and VGG16 ONNX model
2vec_resnet = get_onnx_vectors("onnx_resnet50.onnx", "./pic/example.jpg")
3vec_vgg = get_onnx_vectors("onnx_vgg16.onnx", "./pic/example.jpg")

存储向量数据

图片等非结构化数据无法直接由计算机处理,但可以通过人工智能模型转换成向量,然后由计算机进行分析。Milvus 向量数据库旨在为海量非结构化数据分析提供动力。它可以存储向量数据,并进行近乎实时的分析。首先,在 Milvus 中创建相应模型的 Collections,然后插入图像向量。

from milvus import *

# create collections in Milvus
milvus.create_collection(resnet_collection_param)
milvus.create_collection(vgg_collection_param)

# insert data to Milvus and return ids
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 对应的图像。

# search in Milvus and return the similarly results with ids
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]]
    re_distance = [x.distance for x in results[0]]
    return re_ids, re_distance
    
# get the images according the result ids
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 结合进行相似向量检索,从而得到相似图像。以上两个模型基于 Keras 框架,可以快速提取特征向量。从 Notebook 中可以看到,虽然 Milvus 基于这两个模型在 COCO 数据集上搜索图片的结果相似,但它们的欧氏距离并不相同。您还可以尝试使用其他数据集来比较这两种模型的搜索结果。

Milvus 是一个高性能、高可用性的向量数据库,可用于处理从海量非结构化数据中生成的特征向量。有关更多解决方案,请参阅Milvus Bootcamp

参考资料

  1. https://github.com/onnx/onnx
  2. https://onnx.ai/
  3. https://milvus.io/cn/
  4. https://github.com/milvus-io/bootcamp

关于作者

陈诗雨,Zilliz数据工程师,毕业于西安电子科技大学计算机专业。加入 Zilliz 后,她一直在探索 Milvus 在各个领域的解决方案,如音视频分析、分子式检索等,极大地丰富了社区的应用场景。目前,她正在探索更多有趣的解决方案。业余时间,她喜欢运动和阅读。

Try Managed Milvus for Free

Zilliz Cloud is hassle-free, powered by Milvus and 10x faster.

Get Started

Like the article? Spread the word

扩展阅读