Visualiser des embeddings
Objectifs
- Réduire des vecteurs haute dimension pour les visualiser en 2D/3D
- Utiliser t-SNE et UMAP pour la visualisation
- Interpréter les clusters visuels
Le défi : 3 072 dimensions
Les embeddings vivent dans un espace à 3 072 dimensions. Pour les visualiser, il faut projeter cet espace en 2D ou 3D tout en préservant les relations de proximité.
Réduction de dimension avec t-SNE
t-SNE (t-distributed Stochastic Neighbor Embedding) est la méthode classique pour visualiser des données haute dimension :
from openai import OpenAI
from sklearn.manifold import TSNE
import matplotlib.pyplot as plt
import numpy as np
client = OpenAI()
# Corpus d'exemple
textes = [
# Cluster IA
"L'apprentissage profond utilise des réseaux de neurones",
"Le machine learning transforme la data science",
"Les transformers ont révolutionné le NLP",
"GPT-5 est un grand modèle de langage",
# Cluster cuisine
"La recette du gâteau au chocolat",
"Comment préparer une ratatouille",
"Les bases de la pâtisserie française",
"Techniques de cuisson au four",
# Cluster sport
"Le marathon de Paris attire des milliers de coureurs",
"Entraînement fractionné pour la course à pied",
"Les règles du football expliquées",
"Nutrition sportive et performance",
]
categories = (["IA"] * 4 + ["Cuisine"] * 4 + ["Sport"] * 4)
# Générer les embeddings
response = client.embeddings.create(
input=textes,
model="text-embedding-3-large"
)
embeddings = np.array([d.embedding for d in response.data])
# Réduction t-SNE en 2D
tsne = TSNE(n_components=2, random_state=42, perplexity=4)
coords = tsne.fit_transform(embeddings)
# Visualisation
couleurs = {"IA": "#2563eb", "Cuisine": "#dc2626", "Sport": "#16a34a"}
fig, ax = plt.subplots(figsize=(10, 8))
for cat in couleurs:
mask = [c == cat for c in categories]
ax.scatter(
coords[mask, 0], coords[mask, 1],
c=couleurs[cat], label=cat, s=100, alpha=0.8
)
for i, (x, y) in enumerate(coords[mask]):
idx = [j for j, m in enumerate(mask) if m][i]
ax.annotate(
textes[idx][:30] + "...",
(x, y), fontsize=7, alpha=0.7
)
ax.legend()
ax.set_title("Visualisation t-SNE des embeddings")
plt.tight_layout()
plt.savefig("tsne_embeddings.png", dpi=150)
plt.show()
Paramètres clés de t-SNE
- perplexity : contrôle l’équilibre entre structure locale et globale. Valeurs typiques : 5–50
- n_iter : nombre d’itérations d’optimisation. Minimum 250, idéalement 1 000+
- random_state : pour la reproductibilité
Réduction avec UMAP
UMAP (Uniform Manifold Approximation and Projection) est souvent préféré à t-SNE car il est plus rapide et préserve mieux la structure globale :
import umap
# Réduction UMAP en 2D
reducer = umap.UMAP(n_components=2, random_state=42, n_neighbors=5)
coords_umap = reducer.fit_transform(embeddings)
fig, ax = plt.subplots(figsize=(10, 8))
for cat in couleurs:
mask = [c == cat for c in categories]
ax.scatter(
coords_umap[mask, 0], coords_umap[mask, 1],
c=couleurs[cat], label=cat, s=100, alpha=0.8
)
ax.legend()
ax.set_title("Visualisation UMAP des embeddings")
plt.tight_layout()
plt.savefig("umap_embeddings.png", dpi=150)
plt.show()
t-SNE vs UMAP
| Critère | t-SNE | UMAP |
|---|---|---|
| Vitesse | Lent (O(n²)) | Rapide |
| Structure globale | Mal préservée | Bien préservée |
| Reproductibilité | Variable | Stable |
| Paramètres | perplexity | n_neighbors, min_dist |
Visualisation 3D interactive
Pour une exploration interactive, utilisez Plotly :
import plotly.express as px
import pandas as pd
# Réduction en 3D
reducer_3d = umap.UMAP(n_components=3, random_state=42, n_neighbors=5)
coords_3d = reducer_3d.fit_transform(embeddings)
df = pd.DataFrame({
"x": coords_3d[:, 0],
"y": coords_3d[:, 1],
"z": coords_3d[:, 2],
"catégorie": categories,
"texte": [t[:50] for t in textes]
})
fig = px.scatter_3d(
df, x="x", y="y", z="z",
color="catégorie",
hover_data=["texte"],
title="Embeddings en 3D"
)
fig.write_html("embeddings_3d.html")
fig.show()
Visualiser l’effet de la réduction de dimensions
Comparez la qualité de séparation selon le nombre de dimensions demandées à l’API :
dimensions_a_tester = [256, 512, 1536, 3072]
fig, axes = plt.subplots(1, 4, figsize=(24, 5))
for ax, dim in zip(axes, dimensions_a_tester):
resp = client.embeddings.create(
input=textes,
model="text-embedding-3-large",
dimensions=dim
)
embs = np.array([d.embedding for d in resp.data])
tsne = TSNE(n_components=2, random_state=42, perplexity=4)
coords = tsne.fit_transform(embs)
for cat in couleurs:
mask = [c == cat for c in categories]
ax.scatter(coords[mask, 0], coords[mask, 1],
c=couleurs[cat], label=cat, s=60)
ax.set_title(f"{dim} dimensions")
ax.legend(fontsize=7)
plt.tight_layout()
plt.savefig("comparaison_dimensions.png", dpi=150)
plt.show()
Résumé
- t-SNE et UMAP projettent les embeddings en 2D/3D pour la visualisation
- UMAP est généralement préféré pour sa vitesse et sa fidélité
- Plotly permet des visualisations 3D interactives
- La visualisation aide à valider la qualité de vos embeddings et à détecter des anomalies