PaliGemma-Modelle haben multimodale Funktionen, mit denen Sie sowohl Text- als auch Bilddaten als Eingabe verwenden können, um eine Ausgabe zu generieren. Sie können Bilddaten mit diesen Modellen verwenden, um Ihren Anfragen zusätzlichen Kontext zu verleihen, oder das Modell verwenden, um den Inhalt von Bildern zu analysieren. In dieser Anleitung erfahren Sie, wie Sie PaliGemma mit Keras verwenden, um Bilder zu analysieren und Fragen zu ihnen zu beantworten.
Inhalt dieses Notizbuchs
In diesem Notebook wird PaliGemma mit Keras verwendet. Sie erfahren, wie Sie:
- Keras und die erforderlichen Abhängigkeiten installieren
PaliGemmaCausalLM
herunterladen, eine vortrainierte PaliGemma-Variante für die kausale Modellierung visueller Sprache, und damit ein Modell erstellen- Fähigkeit des Modells testen, Informationen zu bereitgestellten Bildern abzuleiten
Hinweis
Bevor Sie dieses Notebook durchgehen, sollten Sie mit Python-Code und der Funktionsweise von Large Language Models (LLMs) vertraut sein. Sie müssen nicht mit Keras vertraut sein, aber grundlegende Kenntnisse über Keras sind hilfreich, wenn Sie sich den Beispielcode ansehen.
Einrichtung
In den folgenden Abschnitten werden die Vorabschritte beschrieben, die erforderlich sind, damit ein Notebook ein PaliGemma-Modell verwenden kann. Dazu gehören der Modellzugriff, das Abrufen eines API-Schlüssels und die Konfiguration der Notebook-Laufzeit.
Zugriff auf PaliGemma erhalten
Bevor Sie PaliGemma zum ersten Mal verwenden, müssen Sie über Kaggle Zugriff auf das Modell anfordern. Gehen Sie dazu so vor:
- Melden Sie sich bei Kaggle an oder erstellen Sie ein neues Kaggle-Konto, falls Sie noch keines haben.
- Rufen Sie die Modellkarte für PaliGemma auf und klicken Sie auf Zugriff anfordern.
- Füllen Sie das Einwilligungsformular aus und akzeptieren Sie die Nutzungsbedingungen.
API-Schlüssel konfigurieren
Wenn Sie PaliGemma verwenden möchten, müssen Sie Ihren Kaggle-Nutzernamen und einen Kaggle API-Schlüssel angeben.
Wenn Sie einen Kaggle API-Schlüssel generieren möchten, öffnen Sie in Kaggle die Seite Einstellungen und klicken Sie auf Neues Token erstellen. Dadurch wird der Download einer kaggle.json
-Datei mit Ihren API-Anmeldedaten ausgelöst.
Wählen Sie dann in Colab im linken Bereich Secrets (🔑) aus und fügen Sie Ihren Kaggle-Nutzernamen und Ihren Kaggle-API-Schlüssel hinzu. Speichern Sie Ihren Nutzernamen unter dem Namen KAGGLE_USERNAME
und Ihren API-Schlüssel unter dem Namen KAGGLE_KEY
.
Laufzeit auswählen
Für diese Anleitung benötigen Sie eine Colab-Laufzeit mit ausreichenden Ressourcen, um das PaliGemma-Modell auszuführen. In diesem Fall können Sie eine T4-GPU verwenden:
- Klicken Sie rechts oben im Colab-Fenster auf das Drop-down-Menü ▾ (Zusätzliche Verbindungsoptionen).
- Wählen Sie Laufzeittyp ändern aus.
- Wähle unter Hardwarebeschleuniger die Option T4-GPU aus.
Umgebungsvariablen festlegen
Legen Sie die Umgebungsvariablen für KAGGLE_USERNAME
, KAGGLE_KEY
und KERAS_BACKEND
fest.
import os
from google.colab import userdata
# Set up environmental variables
os.environ["KAGGLE_USERNAME"] = userdata.get('KAGGLE_USERNAME')
os.environ["KAGGLE_KEY"] = userdata.get('KAGGLE_KEY')
os.environ["KERAS_BACKEND"] = "jax"
Keras installieren
Führen Sie die folgende Zelle aus, um Keras zu installieren.
pip install -U -q keras-nlp keras-hub kagglehub
Abhängigkeiten importieren und Keras konfigurieren
Installieren Sie die für dieses Notebook erforderlichen Abhängigkeiten und konfigurieren Sie das Keras-Backend. Außerdem legen Sie fest, dass Keras bfloat16
verwenden soll, damit das Framework weniger Arbeitsspeicher benötigt.
import keras
import keras_hub
import numpy as np
import PIL
import requests
import io
import matplotlib
import re
import matplotlib.pyplot as plt
import matplotlib.patches as patches
from PIL import Image
keras.config.set_floatx("bfloat16")
Modell laden
Nachdem Sie alles eingerichtet haben, können Sie das vortrainierte Modell herunterladen und einige Dienstmethoden erstellen, mit denen das Modell seine Antworten generieren kann.
In diesem Schritt laden Sie ein Modell mit PaliGemmaCausalLM
von Keras Hub herunter. In diesem Kurs erfahren Sie, wie Sie die kausale visuelle Sprachmodellstruktur von PaliGemma verwalten und ausführen. Ein kausales visuelles Sprachmodell sagt das nächste Token anhand der vorherigen Tokens voraus. Keras Hub bietet Implementierungen vieler beliebter Modellarchitekturen.
Erstellen Sie das Modell mit der Methode from_preset
und drucken Sie die Zusammenfassung aus. Dieser Vorgang dauert etwa eine Minute.
paligemma = keras_hub.models.PaliGemmaCausalLM.from_preset("kaggle://keras/paligemma2/keras/pali_gemma2_mix_3b_224")
paligemma.summary()
Dienstprogrammmethoden erstellen
Erstellen Sie zwei Dienstmethoden, um Antworten aus Ihrem Modell zu generieren:
crop_and_resize
:Hilfsmethode fürread_img
. Bei dieser Methode wird das Bild zugeschnitten und auf die übergebene Größe angepasst, sodass die Größe des Endbilds geändert wird, ohne die Proportionen des Bilds zu verzerren.read_img
:Hilfsmethode fürread_img_from_url
. Mit dieser Methode wird das Bild geöffnet, so zugeschnitten, dass es in die Einschränkungen des Modells passt, und in ein Array eingefügt, das vom Modell interpretiert werden kann.read_img_from_url
:Nimmt ein Bild über eine gültige URL auf. Mit dieser Methode übergeben Sie das Bild an das Modell.
Sie verwenden read_img_from_url
im nächsten Schritt dieses Notizbuchs.
def crop_and_resize(image, target_size):
width, height = image.size
source_size = min(image.size)
left = width // 2 - source_size // 2
top = height // 2 - source_size // 2
right, bottom = left + source_size, top + source_size
return image.resize(target_size, box=(left, top, right, bottom))
def read_image(url, target_size):
contents = io.BytesIO(requests.get(url).content)
image = PIL.Image.open(contents)
image = crop_and_resize(image, target_size)
image = np.array(image)
# Remove alpha channel if necessary.
if image.shape[2] == 4:
image = image[:, :, :3]
return image
def parse_bbox_and_labels(detokenized_output: str):
matches = re.finditer(
'<loc(?P<y0>\d\d\d\d)><loc(?P<x0>\d\d\d\d)><loc(?P<y1>\d\d\d\d)><loc(?P<x1>\d\d\d\d)>'
' (?P<label>.+?)( ;|$)',
detokenized_output,
)
labels, boxes = [], []
fmt = lambda x: float(x) / 1024.0
for m in matches:
d = m.groupdict()
boxes.append([fmt(d['y0']), fmt(d['x0']), fmt(d['y1']), fmt(d['x1'])])
labels.append(d['label'])
return np.array(boxes), np.array(labels)
def display_boxes(image, boxes, labels, target_image_size):
h, l = target_size
fig, ax = plt.subplots()
ax.imshow(image)
for i in range(boxes.shape[0]):
y, x, y2, x2 = (boxes[i]*h)
width = x2 - x
height = y2 - y
# Create a Rectangle patch
rect = patches.Rectangle((x, y),
width,
height,
linewidth=1,
edgecolor='r',
facecolor='none')
# Add label
plt.text(x, y, labels[i], color='red', fontsize=12)
# Add the patch to the Axes
ax.add_patch(rect)
plt.show()
def display_segment_output(image, bounding_box, segment_mask, target_image_size):
# Initialize a full mask with the target size
full_mask = np.zeros(target_image_size, dtype=np.uint8)
target_width, target_height = target_image_size
for bbox, mask in zip(bounding_box, segment_mask):
y1, x1, y2, x2 = bbox
x1 = int(x1 * target_width)
y1 = int(y1 * target_height)
x2 = int(x2 * target_width)
y2 = int(y2 * target_height)
# Ensure mask is 2D before converting to Image
if mask.ndim == 3:
mask = mask.squeeze(axis=-1)
mask = Image.fromarray(mask)
mask = mask.resize((x2 - x1, y2 - y1), resample=Image.NEAREST)
mask = np.array(mask)
binary_mask = (mask > 0.5).astype(np.uint8)
# Place the binary mask onto the full mask
full_mask[y1:y2, x1:x2] = np.maximum(full_mask[y1:y2, x1:x2], binary_mask)
cmap = plt.get_cmap('jet')
colored_mask = cmap(full_mask / 1.0)
colored_mask = (colored_mask[:, :, :3] * 255).astype(np.uint8)
if isinstance(image, Image.Image):
image = np.array(image)
blended_image = image.copy()
mask_indices = full_mask > 0
alpha = 0.5
for c in range(3):
blended_image[:, :, c] = np.where(mask_indices,
(1 - alpha) * image[:, :, c] + alpha * colored_mask[:, :, c],
image[:, :, c])
fig, ax = plt.subplots()
ax.imshow(blended_image)
plt.show()
Ausgabe generieren
Nachdem Sie das Modell geladen und Dienstmethoden erstellt haben, können Sie dem Modell Bild- und Textdaten zur Verfügung stellen, um Antworten zu generieren. PaliGemma-Modelle werden mit einer bestimmten Prompt-Syntax für bestimmte Aufgaben trainiert, z. B. answer
, caption
und detect
. Weitere Informationen zur Syntax von PaliGemma-Aufgaben finden Sie in der Anleitung für Prompts und das System in PaliGemma.
Laden Sie mit dem folgenden Code ein Testbild in ein Objekt, um ein Bild für die Verwendung in einem Generierungs-Prompt vorzubereiten:
target_size = (224, 224)
image_url = 'https://storage.googleapis.com/keras-cv/models/paligemma/cow_beach_1.png'
cow_image = read_image(image_url, target_size)
matplotlib.pyplot.imshow(cow_image)
In einer bestimmten Sprache antworten
Im folgenden Beispielcode wird gezeigt, wie Sie das PaliGemma-Modell um Informationen zu einem Objekt bitten, das in einem bereitgestellten Bild zu sehen ist. In diesem Beispiel wird die answer {lang}
-Syntax verwendet und es werden zusätzliche Fragen in anderen Sprachen angezeigt:
prompt = 'answer en where is the cow standing?\n'
# prompt = 'svar no hvor står kuen?\n'
# prompt = 'answer fr quelle couleur est le ciel?\n'
# prompt = 'responda pt qual a cor do animal?\n'
output = paligemma.generate(
inputs={
"images": cow_image,
"prompts": prompt,
}
)
print(output)
detect
-Prompt verwenden
Im folgenden Beispielcode wird die Prompt-Syntax detect
verwendet, um ein Objekt im bereitgestellten Bild zu finden. Der Code verwendet die zuvor definierten Funktionen parse_bbox_and_labels()
und display_boxes()
, um die Modellausgabe zu interpretieren und die generierten Begrenzungsboxen anzuzeigen.
prompt = 'detect cow\n'
output = paligemma.generate(
inputs={
"images": cow_image,
"prompts": prompt,
}
)
boxes, labels = parse_bbox_and_labels(output)
display_boxes(cow_image, boxes, labels, target_size)
segment
-Prompt verwenden
Im folgenden Beispielcode wird die Prompt-Syntax segment
verwendet, um den Bereich eines Bildes zu ermitteln, der von einem Objekt belegt ist. Dabei wird die big_vision
-Bibliothek von Google verwendet, um die Modellausgabe zu interpretieren und eine Maske für das segmentierte Objekt zu generieren.
Bevor Sie beginnen, installieren Sie die big_vision
-Bibliothek und ihre Abhängigkeiten, wie in diesem Codebeispiel gezeigt:
import os
import sys
# TPUs with
if "COLAB_TPU_ADDR" in os.environ:
raise "It seems you are using Colab with remote TPUs which is not supported."
# Fetch big_vision repository if python doesn't know about it and install
# dependencies needed for this notebook.
if not os.path.exists("big_vision_repo"):
!git clone --quiet --branch=main --depth=1 \
https://github.com/google-research/big_vision big_vision_repo
# Append big_vision code to python import path
if "big_vision_repo" not in sys.path:
sys.path.append("big_vision_repo")
# Install missing dependencies. Assume jax~=0.4.25 with GPU available.
!pip3 install -q "overrides" "ml_collections" "einops~=0.7" "sentencepiece"
Laden Sie für dieses Segmentierungsbeispiel ein anderes Bild mit einer Katze hoch und bereiten Sie es vor.
cat = read_image('https://big-vision-paligemma.hf.space/file=examples/barsik.jpg', target_size)
matplotlib.pyplot.imshow(cat)
Hier ist eine Funktion, mit der Sie die Segmentausgabe von PaliGemma parsen können.
import big_vision.evaluators.proj.paligemma.transfers.segmentation as segeval
reconstruct_masks = segeval.get_reconstruct_masks('oi')
def parse_segments(detokenized_output: str) -> tuple[np.ndarray, np.ndarray]:
matches = re.finditer(
'<loc(?P<y0>\d\d\d\d)><loc(?P<x0>\d\d\d\d)><loc(?P<y1>\d\d\d\d)><loc(?P<x1>\d\d\d\d)>'
+ ''.join(f'<seg(?P<s{i}>\d\d\d)>' for i in range(16)),
detokenized_output,
)
boxes, segs = [], []
fmt_box = lambda x: float(x) / 1024.0
for m in matches:
d = m.groupdict()
boxes.append([fmt_box(d['y0']), fmt_box(d['x0']), fmt_box(d['y1']), fmt_box(d['x1'])])
segs.append([int(d[f's{i}']) for i in range(16)])
return np.array(boxes), np.array(reconstruct_masks(np.array(segs)))
PaliGemma abfragen, um die Katze im Bild zu segmentieren
prompt = 'segment cat\n'
output = paligemma.generate(
inputs={
"images": cat,
"prompts": prompt,
}
)
Die von PaliGemma generierte Maske visualisieren
bboxes, seg_masks = parse_segments(output)
display_segment_output(cat, bboxes, seg_masks, target_size)
Batch-Prompts
Sie können mehrere Promptbefehle in einem einzigen Prompt als Befehlssatz angeben. Das folgende Beispiel zeigt, wie Sie Ihren Prompt-Text so strukturieren, dass mehrere Anweisungen enthalten sind.
prompts = [
'answer en where is the cow standing?\n',
'answer en what color is the cow?\n',
'describe en\n',
'detect cow\n',
'segment cow\n',
]
images = [cow_image, cow_image, cow_image, cow_image, cow_image]
outputs = paligemma.generate(
inputs={
"images": images,
"prompts": prompts,
}
)
for output in outputs:
print(output)