Combinare modelli di intelligenza artificiale per la ricerca di immagini con ONNX e Milvus
Open Neural Network Exchange (ONNX) è un formato aperto costruito per rappresentare modelli di apprendimento automatico. Da quando è stato reso open source nel 2017, ONNX si è trasformato in uno standard per l'IA, fornendo elementi costitutivi per i modelli di machine learning e deep learning. ONNX definisce un formato di file comune per consentire agli sviluppatori di IA di utilizzare i modelli con vari framework, strumenti, runtime e compilatori e contribuisce ad aumentare la velocità dell'innovazione nella comunità dell'intelligenza artificiale.
Milvus è un database vettoriale open-source altamente flessibile, affidabile e velocissimo. Supporta l'aggiunta, la cancellazione, l'aggiornamento e la ricerca di vettori quasi in tempo reale. Milvus dispone di una serie completa di API intuitive e del supporto per diverse librerie di indici ampiamente adottate (ad esempio Faiss, NMSLIB e Annoy), che semplificano la selezione degli indici per un determinato scenario. Milvus è semplice da usare ed è stato utilizzato in centinaia di organizzazioni e istituzioni in tutto il mondo, tra cui ricerca di immagini, audio e video, raccomandazioni, chatbot, ricerca di nuovi farmaci, ecc.
Questo articolo illustra come utilizzare modelli multipli per la ricerca di immagini basati su ONNX e Milvus. Prende come esempio i modelli VGG16 e ResNet50, utilizza ONNX per eseguire diversi modelli AI per generare vettori di caratteristiche e infine esegue il recupero dei vettori di caratteristiche in Milvus per restituire immagini simili.
Elaborare i modelli con ONNX
Il formato ONNX può essere facilmente scambiato tra i modelli di intelligenza artificiale. Ad esempio, il modello TensorFlow può essere convertito in formato ONNX ed eseguito nell'ambiente Caffe. In questo esempio, convertiamo il modello ResNet50 pre-addestrato nell'ambito del framework Keras nel formato ONNX e poi richiamiamo il modello VGG16 in formato ONNX per analizzare modelli diversi.
da keras.applications.resnet50 importare ResNet50
importare tensorflow come tf
# carica il modello keras-resnet50 e lo salva come floder
model_resnet50 = ResNet50(include_top=False, pooling='max', weights='imagenet')
tf.saved_model.save(model_resnet50, "keras_resnet50_model")
# convertire il modello resnet50 in onnx
python -m tf2onnx.convert --saved-model "keras_resnet50_model" --output "onnx_resnet50.onnx"
Nota: quando abbiamo usato l'interfaccia keras2onnx.convert_keras(model, model.name) per convertire il modello, questa restituirà l'errore AttributeError: KerasTensor' object has no attribute'graph'. Si può quindi usare il comando Bash di Python per convertire secondo la soluzione su Stack Overflow.
Estrarre i vettori di caratteristiche usando i modelli
Dopo aver convertito il modello ResNet50 in formato ONNX, è possibile estrarre il vettore di caratteristiche dell'immagine direttamente attraverso l'inferenza. Nota: i vettori di caratteristiche devono essere normalizzati dopo l'estrazione.
# ottenere i vettori immagine con il modello 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]) per 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]
restituire norm_feat
Utilizzare il modello VGG16 formattato ONNX per elaborare i dati delle immagini:
# genera vettori con ResNet50 e il modello VGG16 ONNX
2vec_resnet = get_onnx_vectors("onnx_resnet50.onnx", "./pic/example.jpg")
3vec_vgg = get_onnx_vectors("onnx_vgg16.onnx", "./pic/esempio.jpg")
Memorizzare i dati vettoriali
I dati non strutturati come le immagini non possono essere elaborati direttamente dal computer, ma possono essere convertiti in vettori attraverso un modello di intelligenza artificiale e quindi analizzati da un computer. Il database vettoriale Milvus è progettato per l'analisi massiva di dati non strutturati. È in grado di memorizzare dati vettoriali e di eseguire analisi quasi in tempo reale. Per prima cosa, creare una raccolta del modello corrispondente in Milvus, quindi inserire i vettori delle immagini.
da milvus importare *
# crea collezioni in Milvus
milvus.create_collection(resnet_collection_param)
milvus.create_collection(vgg_collection_param)
# inserire i dati in Milvus e restituire gli ids
stato, resnet_ids = milvus.insert(resnet_collection_name, resnet_vectors)
status, vgg_ids = milvus.insert(vgg_collection_name, vgg_vectors)
Dopo aver inserito i dati con successo, Milvus restituirà l'ID corrispondente al vettore e quindi si potrà trovare l'immagine in base all'ID. Poiché Milvus 1.1 utilizzato in questo caso non supporta il filtraggio scalare (che ora Milvus 2.0 supporta), si utilizza Redis per memorizzare l'ID del vettore e il valore-chiave del percorso dell'immagine.
importare redis
def img_ids_to_redis(img_directory, res_ids):
per img, ids in zip(immagini, res_ids):
redis.set(ids, img)
Ricerca di immagini simili
Dopo aver memorizzato i dati, possiamo recuperare il vettore. Milvus supporta diversi metodi di calcolo delle distanze, tra cui la distanza euclidea, il prodotto interno e la distanza di Hamming. La ricerca di immagini simili in questo articolo adotta il calcolo della distanza euclidea tra i vettori in Milvus, restituisce l'ID del vettore simile e quindi trova l'immagine corrispondente all'ID in Redis.
# cerca in Milvus e restituisce i risultati simili con gli 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]]
re_distance = [x.distance for x in results[0]]
return re_ids, re_distance
# ottenere le immagini in base agli id dei risultati
def get_sim_imgs(nome_raccolta, vettore_ricerca):
ids, distance = search_in_milvus(collection_name, search_vector)
img = [red.get(i).decode("utf-8") for i in ids]
return ids, distance, img
Prendendo come esempio i modelli VGG16 e ResNet50, questo articolo mostra l'elaborazione di più modelli tramite ONNX e la combinazione di più modelli con Milvus per il recupero di vettori simili per ottenere immagini simili. I due modelli di cui sopra sono basati sul framework Keras, che può estrarre rapidamente vettori di caratteristiche. Dal Quaderno si può notare che, sebbene i risultati della ricerca di immagini da parte di Milvus sul set di dati COCO basati su questi due modelli siano simili, le loro distanze euclidee non sono le stesse. Si può anche provare a confrontare i risultati di ricerca dei due modelli utilizzando altri insiemi di dati.
Milvus è un database vettoriale ad alte prestazioni e altamente disponibile che può essere utilizzato per elaborare vettori di caratteristiche generati da enormi dati non strutturati. Per ulteriori soluzioni, è possibile consultare Milvus bootcamp.
Riferimenti
- https://github.com/onnx/onnx
- https://onnx.ai/
- https://milvus.io/cn/
- https://github.com/milvus-io/bootcamp
Informazioni sull'autore
Shiyu Chen, ingegnere dei dati presso Zilliz, si è laureata in informatica presso la Xidian University. Da quando è entrata a far parte di Zilliz, ha esplorato soluzioni per Milvus in vari campi, come l'analisi di audio e video, il recupero di formule di molecole, ecc. Attualmente sta esplorando altre soluzioni interessanti. Nel tempo libero, ama lo sport e la lettura.
Continua a leggere

Introducing Customer-Managed Encryption Keys (CMEK) on Zilliz Cloud
We're announcing the general availability of Customer-Managed Encryption Keys (CMEK) on Zilliz Cloud.

How Zilliz Saw the Future of Vector Databases—and Built for Production
Zilliz anticipated vector databases early, building Milvus to bring scalable, reliable vector search from research into production AI systems.

Optimizing Embedding Model Selection with TDA Clustering: A Strategic Guide for Vector Databases
Discover how Topological Data Analysis (TDA) reveals hidden embedding model weaknesses and helps optimize vector database performance.
