🚀 Essayez Zilliz Cloud, la version entièrement gérée de Milvus, gratuitement—découvrez des performances 10x plus rapides ! Essayez maintenant>>

milvus-logo
LFAI

Traiter les modèles avec ONNX

  • Engineering
September 26, 2021

Open Neural Network Exchange (ONNX) est un format ouvert construit pour représenter les modèles d'apprentissage automatique. Depuis son ouverture en 2017, ONNX est devenu une norme pour l'IA, fournissant des blocs de construction pour les modèles d'apprentissage automatique et d'apprentissage profond. ONNX définit un format de fichier commun pour permettre aux développeurs d'IA d'utiliser des modèles avec différents frameworks, outils, runtimes et compilateurs, et contribue à augmenter la vitesse d'innovation dans la communauté de l'intelligence artificielle.

Milvus est une base de données vectorielles open-source très flexible, fiable et extrêmement rapide. Elle prend en charge l'ajout, la suppression, la mise à jour et la recherche en temps quasi réel de vecteurs. Milvus dispose d'un ensemble complet d'API intuitives et prend en charge de nombreuses bibliothèques d'index largement adoptées (par exemple Faiss, NMSLIB et Annoy), ce qui simplifie la sélection de l'index pour un scénario donné. Milvus est simple d'utilisation et a été utilisé dans des centaines d'organisations et d'institutions dans le monde entier, notamment pour la recherche d'images, d'audio et de vidéo, la recommandation, le chatbot, la recherche de nouveaux médicaments, etc.

Cet article vous présentera comment utiliser plusieurs modèles pour la recherche d'images en se basant sur ONNX et Milvus. Il prend les modèles VGG16 et ResNet50 comme exemples, utilise ONNX pour exécuter différents modèles d'IA afin de générer des vecteurs de caractéristiques, et enfin effectue une recherche de vecteurs de caractéristiques dans Milvus pour renvoyer des images similaires.

Traiter les modèles avec ONNX

Le format ONNX peut être facilement échangé entre les modèles d'IA. Par exemple, le modèle TensorFlow peut être converti au format ONNX et exécuté dans l'environnement Caffe. Dans cet exemple, nous convertissons le modèle ResNet50 pré-entraîné sous le cadre Keras au format ONNX, puis nous appelons le modèle VGG16 au format ONNX pour analyser différents modèles.

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"

Remarque : lorsque nous avons utilisé l'interface keras2onnx.convert_keras(model, model.name) pour convertir le modèle, elle renvoie l'erreur AttributeError:'KerasTensor' object has no attribute'graph'. Nous pouvons alors utiliser la commande Bash de Python pour convertir le modèle en suivant la solution proposée par Stack Overflow.

Extraction des vecteurs de caractéristiques à l'aide des modèles

Après avoir converti le modèle ResNet50 au format ONNX, vous pouvez extraire le vecteur de caractéristiques de l'image directement par l'inférence. Remarque : les vecteurs de caractéristiques doivent être normalisés après l'extraction.

# 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

Utilisez le modèle VGG16 au format ONNX pour traiter les données d'image :

# 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")

Stocker les données vectorielles

Les données non structurées telles que les images ne peuvent pas être traitées directement par un ordinateur, mais elles peuvent être converties en vecteurs par le biais d'un modèle d'IA, puis analysées par un ordinateur. La base de données vectorielles Milvus est conçue pour l'analyse massive de données non structurées. Elle peut stocker des données vectorielles et effectuer des analyses en temps quasi réel. Tout d'abord, créez une collection du modèle correspondant dans Milvus, puis insérez les vecteurs d'image.

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)

Après avoir inséré les données avec succès, Milvus renvoie l'ID correspondant au vecteur, ce qui permet de trouver l'image par ID. Étant donné que Milvus 1.1 utilisé dans ce cas ne prend pas en charge le filtrage scalaire (que Milvus 2.0 prend désormais en charge), Redis est utilisé pour stocker l'ID du vecteur et la clé-valeur du chemin d'accès à l'image.

import redis
def img_ids_to_redis(img_directory, res_ids):
  for img, ids in zip(images, res_ids):
    redis.set(ids, img)

Recherche d'images similaires

Après avoir stocké les données, nous pouvons récupérer le vecteur. Milvus prend en charge plusieurs méthodes de calcul de la distance, notamment la distance euclidienne, le produit intérieur et la distance de Hamming. La recherche de similarité d'images dans cet article adopte le calcul de la distance euclidienne entre les vecteurs dans Milvus, renvoie l'ID du vecteur similaire, puis trouve l'image correspondant à l'ID dans Redis.

# 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

En prenant les modèles VGG16 et ResNet50 comme exemples, cet article montre le traitement de plusieurs modèles par ONNX et la combinaison de plusieurs modèles avec Milvus pour la recherche de vecteurs similaires afin d'obtenir des images similaires. Les deux modèles ci-dessus sont basés sur le cadre Keras, qui peut rapidement extraire des vecteurs de caractéristiques. Le carnet de notes montre que, bien que les résultats de la recherche d'images par Milvus sur l'ensemble de données COCO basée sur ces deux modèles soient similaires, leurs distances euclidiennes ne sont pas les mêmes. Vous pouvez également essayer de comparer les résultats de recherche des deux modèles en utilisant d'autres ensembles de données.

Milvus est une base de données vectorielles hautement performante et disponible qui peut être utilisée pour traiter les vecteurs de caractéristiques générés à partir de données massives non structurées. Pour plus de solutions, vous pouvez vous référer à Milvus bootcamp.

Références

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

À propos de l'auteur

Shiyu Chen, ingénieur en données chez Zilliz, est diplômée en informatique de l'université de Xidian. Depuis qu'elle a rejoint Zilliz, elle a exploré des solutions pour Milvus dans divers domaines, tels que l'analyse audio et vidéo, la recherche de formules de molécules, etc. Elle explore actuellement d'autres solutions intéressantes. Pendant son temps libre, elle aime le sport et la lecture.

Like the article? Spread the word

Continuer à Lire