Dans les applications réelles de correspondance texte-image, il est fréquent de devoir tester un grand nombre d'images et de textes de manière groupée, et non pas seulement via des interactions individuelles. Par exemple, dans un système de modération de contenu, il est nécessaire de vérifier la pertinence de milliers d'images avec leurs descriptions textuelles ; sur une plateforme e-commerce, il faut faire correspondre en masse les images de produits avec les titres les plus appropriés.
Bien que l'outil GME-Qwen2-VL-2B-Instruct offre une excellente fonction de correspondance unitaire, il manque d'une capacité de traitement par lots. Télécharger manuellement chaque image et saisir chaque texte est clairement irréaliste. C'est pourquoi le développement d'un script de test batch et d'une fonction d'export CSV est essentiel.
Besoins principaux :
- Traitement groupé de multiples tâches de correspondance entre plusieurs images et plusieurs groupes de textes.
- Exécution automatisée des calculs de correspondance, sans intervention humaine.
- Export des résultats sous forme de données structurées pour une analyse ultérieure.
- Maintien de la sécurité et de la confidentialité des données en environnement local.
2. Préparation de l'environnement et installation des dépendances
Avant de commencer à écrire le script batch, assurez-vous de disposer de l'environnement suivant :
# Environnement Python de base
python>=3.8
pip>=20.0
# Bibliothèques principales
torch>=1.10
transformers>=4.30
Pillow>=9.0
numpy>=1.20
pandas>=1.3
tqdm>=4.60 # Pour l'affichage des barres de progression
Installation des dépendances requises :
# Contenu du fichier requirements.txt
torch>=1.10.0
transformers>=4.30.0
Pillow>=9.0.0
numpy>=1.20.0
pandas>=1.3.0
tqdm>=4.60.0
Installation via pip :
pip install -r requirements.txt
3. Code principal du script de test batch
3.1 Classe de base pour le traitement par lots
Créons d'abord une classe de base pour le traitement par lots, encapsulant le chargement du modèle et les calculs de similarité :
import torch
from transformers import AutoModel, AutoTokenizer
from PIL import Image
import numpy as np
import pandas as pd
from tqdm import tqdm
import os
class BatchProcessorGME:
def __init__(self, model_path=None, device=None):
"""
Initialise le processeur batch.
:param model_path: Chemin du modèle, None pour utiliser le modèle par défaut.
:param device: Périphérique d'exécution, None pour une sélection automatique.
"""
self.device = device or ('cuda' if torch.cuda.is_available() else 'cpu')
self.model_path = model_path or "GME-Qwen2-VL-2B-Instruct"
# Chargement du modèle et du tokenizer
self.model = AutoModel.from_pretrained(
self.model_path,
torch_dtype=torch.float16,
trust_remote_code=True
).to(self.device).eval()
self.tokenizer = AutoTokenizer.from_pretrained(
self.model_path,
trust_remote_code=True
)
# Configuration du mode d'inférence
self.model.config.use_cache = True
def embed_image(self, image_path):
"""Génère le vecteur d'une image."""
try:
image = Image.open(image_path).convert('RGB')
image_tensor = self.processor(images=image, return_tensors="pt")['pixel_values']
image_tensor = image_tensor.to(self.device, dtype=torch.float16)
with torch.no_grad():
image_features = self.model.get_image_features(
pixel_values=image_tensor,
is_query=False
)
return image_features.cpu().numpy()
except Exception as e:
print(f"Erreur lors du traitement de l'image {image_path} : {str(e)}")
return None
def embed_text(self, text):
"""Génère le vecteur d'un texte."""
try:
# Ajout du préfixe d'instruction
formatted_text = f"Find an image that matches the given text. {text}"
inputs = self.tokenizer(
formatted_text,
return_tensors="pt",
padding=True,
truncation=True
)
inputs = {k: v.to(self.device) for k, v in inputs.items()}
with torch.no_grad():
text_features = self.model.get_text_features(**inputs)
return text_features.cpu().numpy()
except Exception as e:
print(f"Erreur lors du traitement du texte '{text}' : {str(e)}")
return None
3.2 Fonction de calcul de similarité en batch
Implémentons ensuite la fonctionnalité de correspondance par lots :
def compute_similarity_batch(self, image_paths, text_candidates_list):
"""
Calcule les similarités entre des images et des textes par lots.
:param image_paths: Liste des chemins d'images.
:param text_candidates_list: Liste de listes de textes candidats (une par image).
:return: DataFrame contenant tous les résultats.
"""
all_results = []
pbar = tqdm(total=len(image_paths), desc="Traitement des images")
for img_idx, image_path in enumerate(image_paths):
image_embedding = self.embed_image(image_path)
if image_embedding is None:
pbar.update(1)
continue
text_candidates = text_candidates_list[img_idx]
for text_idx, text in enumerate(text_candidates):
text_embedding = self.embed_text(text)
if text_embedding is None:
continue
similarity = np.dot(image_embedding, text_embedding.T)[0][0]
norm_score = self._normalize_score(similarity)
all_results.append({
'image_path': image_path,
'image_index': img_idx,
'text': text,
'text_index': text_idx,
'raw_score': round(similarity, 4),
'normalized_score': round(norm_score, 4)
})
pbar.update(1)
pbar.close()
return pd.DataFrame(all_results)
def _normalize_score(self, raw_score):
"""Normalise le score brut selon les caractéristiques du modèle GME."""
if raw_score < 0.1:
return 0.0
elif raw_score > 0.5:
return 1.0
else:
return (raw_score - 0.1) / 0.4
3.3 Fonction d'export CSV
Implémentation de l'export des résultats, avec plusieurs options de format :
def export_to_csv(self, dataframe, output_file,
sort_by_score=True,
include_raw_scores=True,
columns_to_export=None):
"""
Exporte les résultats vers un fichier CSV.
:param dataframe: DataFrame des résultats.
:param output_file: Chemin du fichier de sortie.
:param sort_by_score: Trier par score.
:param include_raw_scores: Inclure les scores bruts.
:param columns_to_export: Liste des colonnes à exporter.
"""
export_df = dataframe.copy()
if sort_by_score:
export_df = export_df.sort_values(['image_index', 'normalized_score'],
ascending=[True, False])
default_columns = ['image_path', 'image_index', 'text', 'text_index',
'normalized_score', 'raw_score']
selected_columns = columns_to_export or default_columns
if not include_raw_scores:
selected_columns = [col for col in selected_columns if col != 'raw_score']
export_df = export_df[selected_columns]
export_df.to_csv(output_file, index=False, encoding='utf-8')
print(f"Résultats exportés vers : {output_file}")
print(f"Nombre d'enregistrements exportés : {len(export_df)}")
4. Exemple d'utilisation complet
4.1 Exemple de traitement batch de base
Voici un exemple complet illustrant le traitement groupé de plusieurs images :
def exemple_traitement_batch():
"""Exemple de traitement batch."""
processeur = BatchProcessorGME()
chemins_images = [
"images/chat.jpg",
"images/chien.jpg",
"images/voiture.jpg"
]
textes_candidats = [
["Un chat mignon", "Un chat qui dort", "Un chien brun"],
["Un chien qui court", "Un golden retriever", "Un chat noir"],
["Une voiture rouge", "Une voiture de sport", "Un vélo"]
]
print("Début du calcul de similarité en batch...")
df_resultats = processeur.compute_similarity_batch(chemins_images, textes_candidats)
fichier_sortie = "resultats_batch.csv"
processeur.export_to_csv(df_resultats, fichier_sortie)
print("\n=== Statistiques du traitement batch ===")
print(f"Nombre d'images traitées : {len(chemins_images)}")
print(f"Nombre total de calculs de similarité : {len(df_resultats)}")
print(f"Score de similarité max : {df_resultats['normalized_score'].max():.4f}")
print(f"Score de similarité min : {df_resultats['normalized_score'].min():.4f}")
print(f"Score moyen : {df_resultats['normalized_score'].mean():.4f}")
if __name__ == "__main__":
exemple_traitement_batch()
4.2 Lecture des données batch depuis un fichier
Pour les traitements à grande échelle, il est recommandé de lire les données depuis un fichier :
def traiter_depuis_csv(fichier_config, fichier_sortie):
"""
Traite les tâches batch à partir d'un fichier CSV de configuration.
:param fichier_config: Chemin du fichier CSV contenant les chemins d'images et textes.
:param fichier_sortie: Chemin du fichier de sortie.
"""
df_config = pd.read_csv(fichier_config)
groupes = df_config.groupby('image_path')['text_candidate'].apply(list).reset_index()
chemins_images = groupes['image_path'].tolist()
textes_candidats = groupes['text_candidate'].tolist()
processeur = BatchProcessorGME()
df_resultats = processeur.compute_similarity_batch(chemins_images, textes_candidats)
processeur.export_to_csv(df_resultats, fichier_sortie)
return df_resultats
4.3 Exemple de fichier de configuration CSV
Créez un fichier CSV de configuration (batch_config.csv) :
image_path,text_candidate
images/chat.jpg,Un chat mignon
images/chat.jpg,Un chat qui dort
images/chat.jpg,Un chien brun
images/chien.jpg,Un chien qui court
images/chien.jpg,Un golden retriever
images/chien.jpg,Un chat noir
images/voiture.jpg,Une voiture rouge
images/voiture.jpg,Une voiture de sport
images/voiture.jpg,Un vélo
5. Fonctionnalités avancées et recommandations d'optimisation
5.1 Optimisation mémoire et traitement par lots
Pour les jeux de données volumineux, il est nécessaire d'optimiser l'utilisation de la mémoire :
def traitement_batch_optimise(chemins_images, textes_candidats, taille_lot=8):
"""Version optimisée du traitement batch, réduisant les échanges mémoire GPU."""
tous_resultats = []
for i in tqdm(range(0, len(chemins_images), taille_lot), desc="Traitement par lots"):
lot_images = chemins_images[i:i+taille_lot]
lot_textes = textes_candidats[i:i+taille_lot]
embeddings_images = []
for chemin in lot_images:
embedding = self.embed_image(chemin)
embeddings_images.append(embedding)
for idx_img, (emb_img, textes) in enumerate(zip(embeddings_images, lot_textes)):
if emb_img is None:
continue
for texte in textes:
emb_texte = self.embed_text(texte)
if emb_texte is None:
continue
similarite = np.dot(emb_img, emb_texte.T)[0][0]
score_normalise = self._normalize_score(similarite)
tous_resultats.append({
'image_path': lot_images[idx_img],
'text': texte,
'raw_score': round(similarite, 4),
'normalized_score': round(score_normalise, 4)
})
return pd.DataFrame(tous_resultats)
5.2 Analyse et visualisation des résultats
Ajoutez une fonction d'analyse des résultats :
def analyser_resultats(df_resultats, dossier_sortie="analyse_resultats"):
"""Analyse les résultats du traitement batch et génère un rapport."""
import matplotlib.pyplot as plt
import os
os.makedirs(dossier_sortie, exist_ok=True)
# Histogramme de distribution des scores
plt.figure(figsize=(10, 6))
plt.hist(df_resultats['normalized_score'], bins=20, alpha=0.7, color='lightgreen')
plt.xlabel('Score de similarité normalisé')
plt.ylabel('Fréquence')
plt.title('Distribution des scores de similarité')
plt.savefig(f"{dossier_sortie}/distribution_scores.png")
plt.close()
# Rapport statistique
rapport = {
'total_enregistrements': len(df_resultats),
'score_moyen': df_resultats['normalized_score'].mean(),
'score_max': df_resultats['normalized_score'].max(),
'score_min': df_resultats['normalized_score'].min(),
'nombre_correspondances_elevees': len(df_resultats[df_resultats['normalized_score'] > 0.7]),
'nombre_correspondances_moyennes': len(df_resultats[(df_resultats['normalized_score'] >= 0.3) &
(df_resultats['normalized_score'] <= 0.7)]),
'nombre_correspondances_faibles': len(df_resultats[df_resultats['normalized_score'] < 0.3])
}
df_rapport = pd.DataFrame([rapport])
df_rapport.to_csv(f"{dossier_sortie}/rapport_synthese.csv", index=False)
return rapport
6. Cas d'utilisation concrets
6.1 Correspondance de produits e-commerce
def correspondance_produits_ecommerce(images_produits, titres_produits):
"""
Scénario e-commerce : Vérification de la pertinence entre images de produits et titres.
:param images_produits: Liste des chemins d'images de produits.
:param titres_produits: Liste des titres de produits (correspondant un-à-un aux images).
"""
liste_textes_candidats = []
for titre in titres_produits:
candidats = [
titre,
f"Produit : {titre}",
f"Photo de {titre}",
f"Image montrant {titre}"
]
liste_textes_candidats.append(candidats)
processeur = BatchProcessorGME()
resultats = processeur.compute_similarity_batch(images_produits, liste_textes_candidats)
analyse = processeur.analyser_resultats(resultats)
return resultats, analyse
6.2 Vérification de modération de contenu
def verification_moderation_contenu(images, descriptions_attendues):
"""
Scénario de modération de contenu : Vérifier si les images correspondent aux descriptions attendues.
:param images: Liste des chemins d'images à modérer.
:param descriptions_attendues: Liste des descriptions attendues.
"""
processeur = BatchProcessorGME()
df_resultats = processeur.compute_similarity_batch(
images,
[[desc] for desc in descriptions_attendues]
)
seuil = 0.6
df_resultats['correspond'] = df_resultats['normalized_score'] >= seuil
fichier_sortie = "resultats_moderation.csv"
processeur.export_to_csv(df_resultats, fichier_sortie)
return df_resultats
7. Conclusion
Grâce au script de test batch et à la fonction d'export CSV présentés dans cet article, vous pouvez étendre la capacité de correspondance texte-image du modèle GME-Qwen2-VL-2B-Instruct à des applications à grande échelle. Les avantages clés incluent :
Valeur principale :
- Capacité de traitement par lots : Gère simultanément des centaines d'images et des milliers de textes.
- Automatisation : Exécution sans intervention humaine pour tous les calculs de correspondance.
- Sortie structurée : Format CSV facilitant l'analyse et le traitement ultérieurs.
- Optimisation des performances : Mécanisme de lots réduisant les échanges mémoire GPU et améliorant l'efficacité.
- Configuration flexible : Support de multiples formats d'entrée et options de sortie.
Scénarios d'application :
- Vérification de la correspondance entre images de produits et titres sur les plateformes e-commerce.
- Contrôle de cohérence texte-image dans les systèmes de modération de contenu.
- Annotation et recherche automatiques dans les bibliothèques de médias.
- Expériences de correspondance texte-image à grande échelle en recherche académique.
Recommandations pour la suite :
- Ajustez le seuil de correspondance en fonction des besoins métiers spécifiques.
- Concevez des stratégies de génération de textes candidats plus complexes en fonction des règles métier.
- Mettez en place des tâches de traitement batch régulières pour une automatisation de l'exploitation.
- Combinez avec d'autres modèles ou moteurs de règles pour construire un système de vérification de correspondance à plusieurs niveaux.
Avec cette solution de traitement par lots, vous pouvez exploiter pleinement la puissance du modèle GME-Qwen2-VL-2B-Instruct dans le domaine de la correspondance texte-image, offrant ainsi un support technique fiable pour divers scénarios d'application réels.