Auf ai.google.dev ansehen | In Google Colab ausführen | Quelle auf GitHub ansehen |
Überblick
In dieser Anleitung wird gezeigt, wie Sie das Clustering mit den Einbettungen aus der Gemini API visualisieren und ausführen. Sie visualisieren eine Teilmenge der 20 Newsgroup-Datasets mithilfe von t-SNE und gruppieren diese mit dem KMeans-Algorithmus.
Weitere Informationen zu den ersten Schritten mit Einbettungen, die über die Gemini API generiert wurden, finden Sie in der Python-Kurzanleitung.
Voraussetzungen
Sie können diese Kurzanleitung in Google Colab ausführen.
Um diese Kurzanleitung in Ihrer eigenen Entwicklungsumgebung auszuführen, achten Sie darauf, dass Ihre Umgebung die folgenden Anforderungen erfüllt:
- Python 3.9 oder höher
- Eine Installation von
jupyter
zum Ausführen des Notebooks.
Einrichtung
Laden Sie zuerst die Python-Bibliothek für die Gemini API herunter und installieren Sie sie.
pip install -U -q google.generativeai
import re
import tqdm
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import google.generativeai as genai
# Used to securely store your API key
from google.colab import userdata
from sklearn.datasets import fetch_20newsgroups
from sklearn.manifold import TSNE
from sklearn.cluster import KMeans
from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay
API-Schlüssel abrufen
Bevor Sie die Gemini API verwenden können, müssen Sie zuerst einen API-Schlüssel abrufen. Falls Sie noch keinen Schlüssel haben, können Sie mit einem Klick in Google AI Studio einen Schlüssel erstellen.
Fügen Sie den Schlüssel in Colab im linken Bereich unter „🚀“ zum Secret-Manager hinzu. Geben Sie ihr den Namen API_KEY
.
Sobald Sie den API-Schlüssel haben, übergeben Sie ihn an das SDK. Dafür haben Sie die beiden folgenden Möglichkeiten:
- Fügen Sie den Schlüssel in die Umgebungsvariable
GOOGLE_API_KEY
ein. Das SDK übernimmt ihn dort automatisch. - Schlüssel an
genai.configure(api_key=...)
übergeben
# Or use `os.getenv('API_KEY')` to fetch an environment variable.
API_KEY=userdata.get('API_KEY')
genai.configure(api_key=API_KEY)
for m in genai.list_models():
if 'embedContent' in m.supported_generation_methods:
print(m.name)
models/embedding-001 models/embedding-001
Dataset
Das 20 Newsgroups-Text-Dataset enthält 18.000 Newsgroups-Posts zu 20 Themen,die in Trainings- und Test-Datasets unterteilt sind. Die Aufteilung zwischen den Trainings- und Test-Datasets basiert auf Nachrichten, die vor und nach einem bestimmten Datum gepostet wurden. In dieser Anleitung verwenden Sie die Trainingsteilmenge.
newsgroups_train = fetch_20newsgroups(subset='train')
# View list of class names for dataset
newsgroups_train.target_names
['alt.atheism', 'comp.graphics', 'comp.os.ms-windows.misc', 'comp.sys.ibm.pc.hardware', 'comp.sys.mac.hardware', 'comp.windows.x', 'misc.forsale', 'rec.autos', 'rec.motorcycles', 'rec.sport.baseball', 'rec.sport.hockey', 'sci.crypt', 'sci.electronics', 'sci.med', 'sci.space', 'soc.religion.christian', 'talk.politics.guns', 'talk.politics.mideast', 'talk.politics.misc', 'talk.religion.misc']
Hier ist das erste Beispiel im Trainings-Dataset.
idx = newsgroups_train.data[0].index('Lines')
print(newsgroups_train.data[0][idx:])
Lines: 15 I was wondering if anyone out there could enlighten me on this car I saw the other day. It was a 2-door sports car, looked to be from the late 60s/ early 70s. It was called a Bricklin. The doors were really small. In addition, the front bumper was separate from the rest of the body. This is all I know. If anyone can tellme a model name, engine specs, years of production, where this car is made, history, or whatever info you have on this funky looking car, please e-mail. Thanks, - IL ---- brought to you by your neighborhood Lerxst ----
# Apply functions to remove names, emails, and extraneous words from data points in newsgroups.data
newsgroups_train.data = [re.sub(r'[\w\.-]+@[\w\.-]+', '', d) for d in newsgroups_train.data] # Remove email
newsgroups_train.data = [re.sub(r"\([^()]*\)", "", d) for d in newsgroups_train.data] # Remove names
newsgroups_train.data = [d.replace("From: ", "") for d in newsgroups_train.data] # Remove "From: "
newsgroups_train.data = [d.replace("\nSubject: ", "") for d in newsgroups_train.data] # Remove "\nSubject: "
# Put training points into a dataframe
df_train = pd.DataFrame(newsgroups_train.data, columns=['Text'])
df_train['Label'] = newsgroups_train.target
# Match label to target name index
df_train['Class Name'] = df_train['Label'].map(newsgroups_train.target_names.__getitem__)
# Retain text samples that can be used in the gecko model.
df_train = df_train[df_train['Text'].str.len() < 10000]
df_train
Als Nächstes werden Sie Stichproben einiger Daten ziehen, indem Sie 100 Datenpunkte im Trainings-Dataset erstellen und einige der Kategorien löschen, die Sie in dieser Anleitung ausführen möchten. Wähle die Wissenschaftskategorien aus, die verglichen werden sollen.
# Take a sample of each label category from df_train
SAMPLE_SIZE = 150
df_train = (df_train.groupby('Label', as_index = False)
.apply(lambda x: x.sample(SAMPLE_SIZE))
.reset_index(drop=True))
# Choose categories about science
df_train = df_train[df_train['Class Name'].str.contains('sci')]
# Reset the index
df_train = df_train.reset_index()
df_train
df_train['Class Name'].value_counts()
sci.crypt 150 sci.electronics 150 sci.med 150 sci.space 150 Name: Class Name, dtype: int64
Einbettungen erstellen
In diesem Abschnitt erfahren Sie, wie Sie mithilfe der Einbettungen aus der Gemini API Einbettungen für die verschiedenen Texte im DataFrame generieren.
API-Änderungen für Einbettungen mit Modelleinbettung-001
Für das neue Einbettungsmodell „embedding-001“ gibt es einen neuen Aufgabentypparameter und den optionalen Titel (nur gültig mit „task_type=RETRIEVAL_DOCUMENT
“).
Diese neuen Parameter gelten nur für die neuesten Einbettungsmodelle.Die Aufgabentypen sind:
Aufgabentyp | Beschreibung |
---|---|
RETRIEVAL_QUERY | Gibt an, dass der gegebene Text eine Abfrage in einer Such-/Abrufeinstellung ist. |
RETRIEVAL_DOCUMENT | Gibt an, dass der gegebene Text ein Dokument in einer Such-/Abrufeinstellung ist. |
SEMANTIC_SIMILARITY | Gibt an, dass der angegebene Text für die Bestimmung der semantischen Textähnlichkeit (Semantic Textual Similarity, STS) verwendet wird. |
KLASSIFIZIERUNG | Gibt an, dass die Einbettungen zur Klassifizierung verwendet werden. |
Gruppierung | Gibt an, dass die Einbettungen für das Clustering verwendet werden. |
from tqdm.auto import tqdm
tqdm.pandas()
from google.api_core import retry
def make_embed_text_fn(model):
@retry.Retry(timeout=300.0)
def embed_fn(text: str) -> list[float]:
# Set the task_type to CLUSTERING.
embedding = genai.embed_content(model=model,
content=text,
task_type="clustering")
return embedding["embedding"]
return embed_fn
def create_embeddings(df):
model = 'models/embedding-001'
df['Embeddings'] = df['Text'].progress_apply(make_embed_text_fn(model))
return df
df_train = create_embeddings(df_train)
0%| | 0/600 [00:00<?, ?it/s]
Dimensionalitätsreduktion
Die Länge des Dokumenteinbettungsvektors beträgt 768 Zeichen. Um zu visualisieren, wie die eingebetteten Dokumente gruppiert sind, müssen Sie die Dimensionalitätsreduzierung anwenden, da sich die Einbettungen nur im 2D- oder 3D-Raum visualisieren lassen. Vom Kontext her ähnliche Dokumente sollten im Weltraum näher beieinander sein, im Gegensatz zu Dokumenten, die weniger ähnlich sind.
len(df_train['Embeddings'][0])
768
# Convert df_train['Embeddings'] Pandas series to a np.array of float32
X = np.array(df_train['Embeddings'].to_list(), dtype=np.float32)
X.shape
(600, 768)
Sie wenden den Ansatz „t-Distributed Stochastic Neighbor Embedding“ (t-SNE) an, um die Dimensionalität zu reduzieren. Mit diesem Verfahren wird die Anzahl der Dimensionen reduziert, während Cluster erhalten bleiben (Punkte, die nah beieinander liegen, bleiben nah beieinander). Für die Originaldaten versucht das Modell, eine Verteilung zu konstruieren, über die andere Datenpunkte „Nachbarn“ sind (d.h. sie eine ähnliche Bedeutung haben). Anschließend wird eine Zielfunktion optimiert, um eine ähnliche Verteilung in der Visualisierung beizubehalten.
tsne = TSNE(random_state=0, n_iter=1000)
tsne_results = tsne.fit_transform(X)
df_tsne = pd.DataFrame(tsne_results, columns=['TSNE1', 'TSNE2'])
df_tsne['Class Name'] = df_train['Class Name'] # Add labels column from df_train to df_tsne
df_tsne
fig, ax = plt.subplots(figsize=(8,6)) # Set figsize
sns.set_style('darkgrid', {"grid.color": ".6", "grid.linestyle": ":"})
sns.scatterplot(data=df_tsne, x='TSNE1', y='TSNE2', hue='Class Name', palette='hls')
sns.move_legend(ax, "upper left", bbox_to_anchor=(1, 1))
plt.title('Scatter plot of news using t-SNE');
plt.xlabel('TSNE1');
plt.ylabel('TSNE2');
plt.axis('equal')
(-46.191162300109866, 53.521015357971194, -39.96646995544434, 37.282975387573245)
Ergebnisse mit KMeans vergleichen
Das KMeans-Clustering ist ein beliebter Clustering-Algorithmus und wird häufig für unüberwachtes Lernen verwendet. Sie ermittelt iterativ die besten k Mittelpunkte und weist jedes Beispiel dem nächstgelegenen Schwerpunkt zu. Geben Sie die Einbettungen direkt in den KMeans-Algorithmus ein, um die Visualisierung der Einbettungen mit der Leistung eines Algorithmus für maschinelles Lernen zu vergleichen.
# Apply KMeans
kmeans_model = KMeans(n_clusters=4, random_state=1, n_init='auto').fit(X)
labels = kmeans_model.fit_predict(X)
df_tsne['Cluster'] = labels
df_tsne
fig, ax = plt.subplots(figsize=(8,6)) # Set figsize
sns.set_style('darkgrid', {"grid.color": ".6", "grid.linestyle": ":"})
sns.scatterplot(data=df_tsne, x='TSNE1', y='TSNE2', hue='Cluster', palette='magma')
sns.move_legend(ax, "upper left", bbox_to_anchor=(1, 1))
plt.title('Scatter plot of news using KMeans Clustering');
plt.xlabel('TSNE1');
plt.ylabel('TSNE2');
plt.axis('equal')
(-46.191162300109866, 53.521015357971194, -39.96646995544434, 37.282975387573245)
def get_majority_cluster_per_group(df_tsne_cluster, class_names):
class_clusters = dict()
for c in class_names:
# Get rows of dataframe that are equal to c
rows = df_tsne_cluster.loc[df_tsne_cluster['Class Name'] == c]
# Get majority value in Cluster column of the rows selected
cluster = rows.Cluster.mode().values[0]
# Populate mapping dictionary
class_clusters[c] = cluster
return class_clusters
classes = df_tsne['Class Name'].unique()
class_clusters = get_majority_cluster_per_group(df_tsne, classes)
class_clusters
{'sci.crypt': 1, 'sci.electronics': 3, 'sci.med': 2, 'sci.space': 0}
Rufen Sie die Mehrheit der Cluster pro Gruppe ab und sehen Sie, wie viele der tatsächlichen Mitglieder dieser Gruppe dem Cluster angehören.
# Convert the Cluster column to use the class name
class_by_id = {v: k for k, v in class_clusters.items()}
df_tsne['Predicted'] = df_tsne['Cluster'].map(class_by_id.__getitem__)
# Filter to the correctly matched rows
correct = df_tsne[df_tsne['Class Name'] == df_tsne['Predicted']]
# Summarise, as a percentage
acc = correct['Class Name'].value_counts() / SAMPLE_SIZE
acc
sci.space 0.966667 sci.med 0.960000 sci.electronics 0.953333 sci.crypt 0.926667 Name: Class Name, dtype: float64
# Get predicted values by name
df_tsne['Predicted'] = ''
for idx, rows in df_tsne.iterrows():
cluster = rows['Cluster']
# Get key from mapping based on cluster value
key = list(class_clusters.keys())[list(class_clusters.values()).index(cluster)]
df_tsne.at[idx, 'Predicted'] = key
df_tsne
Um die Leistung der auf Ihre Daten angewendeten KMeans besser zu visualisieren, können Sie eine Wahrheitsmatrix verwenden. Mit der Wahrheitsmatrix können Sie die Leistung des Klassifizierungsmodells über die Genauigkeit hinaus bewerten. Sie können sehen, wie falsch klassifizierte Punkte klassifiziert werden. Sie benötigen die tatsächlichen und die vorhergesagten Werte, die Sie im obigen DataFrame erfasst haben.
cm = confusion_matrix(df_tsne['Class Name'].to_list(), df_tsne['Predicted'].to_list())
disp = ConfusionMatrixDisplay(confusion_matrix=cm,
display_labels=classes)
disp.plot(xticks_rotation='vertical')
plt.title('Confusion Matrix for Actual and Clustered Newsgroups');
plt.grid(False)
Nächste Schritte
Sie haben jetzt Ihre eigene Visualisierung von Einbettungen mit Clustering erstellt! Verwenden Sie eigene Textdaten, um sie als Einbettungen zu visualisieren. Sie können eine Dimensionalitätsreduzierung durchführen, um den Schritt der Visualisierung abzuschließen. Beachten Sie, dass TSNE gut im Clustering von Eingaben ist, aber länger konvergieren kann oder bei lokalen Minima hängen bleibt. Wenn dieses Problem auftritt, können Sie auch die Hauptkomponentenanalyse (Hauptkomponentenanalyse, PCA) in Betracht ziehen.
Außerhalb von KMeans gibt es noch andere Clustering-Algorithmen, zum Beispiel das dichtebasierte räumliche Clustering (DBSCAN).
Weitere Informationen zur Verwendung von Einbettungen finden Sie in diesen anderen Anleitungen: