|   |   Запустить в Google Colab |   Просмотреть исходный код на GitHub | 
Модели PaliGemma обладают многомодальными возможностями, что позволяет вам генерировать выходные данные с использованием как текстовых, так и графических входных данных. Вы можете использовать графические данные с этими моделями для предоставления дополнительного контекста для ваших запросов или использовать модель для анализа содержимого изображений. В этом руководстве показано, как использовать PaliGemma с Keras для анализа изображений и ответа на вопросы о них.
Что в этой тетради?
В этом блокноте используется PaliGemma с Keras, и он показывает, как:
- Установите Keras и необходимые зависимости
 -  Загрузите 
PaliGemmaCausalLM, предварительно обученный вариант PaliGemma для моделирования визуального языка каузальных связей, и используйте его для создания модели. - Проверьте способность модели делать выводы о предоставленных изображениях.
 
Прежде чем начать
Прежде чем читать этот блокнот, вы должны быть знакомы с кодом Python, а также с тем, как обучаются большие языковые модели (LLM). Вам не обязательно быть знакомым с Keras, но базовые знания о Keras будут полезны при чтении кода примера.
Настраивать
В следующих разделах описываются предварительные шаги по настройке блокнота для использования модели PaliGemma, включая доступ к модели, получение ключа API и настройку среды выполнения блокнота.
Получить доступ к PaliGemma
Перед первым использованием PaliGemma необходимо запросить доступ к модели через Kaggle, выполнив следующие шаги:
- Войдите в Kaggle или создайте новую учетную запись Kaggle, если у вас ее еще нет.
 - Перейдите на карточку модели PaliGemma и нажмите «Запросить доступ» .
 - Заполните форму согласия и примите положения и условия.
 
Настройте свой ключ API
Чтобы использовать PaliGemma, вам необходимо указать свое имя пользователя Kaggle и ключ API Kaggle.
 Чтобы сгенерировать ключ API Kaggle, откройте страницу настроек в Kaggle и нажмите «Создать новый токен» . Это запустит загрузку файла kaggle.json , содержащего ваши учетные данные API.
 Затем в Colab выберите Secrets (🔑) на левой панели и добавьте свое имя пользователя Kaggle и ключ API Kaggle. Сохраните свое имя пользователя под именем KAGGLE_USERNAME , а свой ключ API — под именем KAGGLE_KEY .
Выберите среду выполнения
Для завершения этого руководства вам понадобится среда выполнения Colab с достаточными ресурсами для запуска модели PaliGemma. В этом случае вы можете использовать T4 GPU:
- В правом верхнем углу окна Colab щелкните раскрывающееся меню ▾ (Дополнительные параметры подключения) .
 - Выберите Изменить тип среды выполнения .
 - В разделе «Аппаратный ускоритель» выберите T4 GPU .
 
Установить переменные среды
 Задайте переменные среды для KAGGLE_USERNAME , KAGGLE_KEY и KERAS_BACKEND .
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
Запустите указанную ниже ячейку, чтобы установить Keras.
pip install -U -q keras-nlp keras-hub kagglehubИмпорт зависимостей и настройка Keras
 Установите зависимости, необходимые для этого блокнота, и настройте бэкенд Keras. Вы также настроите Keras на использование bfloat16 , чтобы фреймворк использовал меньше памяти.
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")
Загрузить модель
 Теперь, когда вы все настроили, вы можете загрузить предварительно обученную модель и создать несколько вспомогательных методов, которые помогут вашей модели генерировать ответы. На этом этапе вы загружаете модель с помощью PaliGemmaCausalLM из Keras Hub. Этот класс помогает вам управлять и запускать структуру модели каузального визуального языка PaliGemma. Модель каузального визуального языка предсказывает следующий токен на основе предыдущих токенов. Keras Hub предоставляет реализации многих популярных архитектур моделей .
 Создайте модель с помощью метода from_preset и распечатайте ее сводку. Этот процесс займет около минуты.
paligemma = keras_hub.models.PaliGemmaCausalLM.from_preset("kaggle://keras/paligemma2/keras/pali_gemma2_mix_3b_224")
paligemma.summary()
Создать вспомогательные методы
Чтобы помочь вам генерировать ответы на основе вашей модели, создайте два служебных метода:
-  
crop_and_resize: Вспомогательный метод дляread_img. Этот метод обрезает и изменяет размер изображения до переданного размера, так что размер конечного изображения изменяется без искажения пропорций изображения. -  
read_img: Вспомогательный метод дляread_img_from_url. Этот метод фактически открывает изображение, изменяет его размер так, чтобы оно соответствовало ограничениям модели, и помещает его в массив, который может быть интерпретирован моделью. -  
read_img_from_url: принимает изображение через действительный URL. Этот метод нужен для передачи изображения в модель. 
 Вы будете использовать read_img_from_url на следующем этапе этого блокнота.
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()
Сгенерировать вывод
 После загрузки модели и создания методов утилиты вы можете запросить модель с данными изображений и текста для генерации ответов. Модели PaliGemma обучаются с определенным синтаксисом подсказок для определенных задач, таких как answer , caption , and detect . Для получения дополнительной информации о синтаксисе задач подсказок PaliGemma см. инструкции по подсказкам и системе PaliGemma .
Подготовьте изображение для использования в приглашении на генерацию, используя следующий код для загрузки тестового изображения в объект:
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)
Ответьте на определенном языке
 Следующий пример кода показывает, как запросить у модели PaliGemma информацию об объекте, появляющемся на предоставленном изображении. В этом примере используется синтаксис answer {lang} и показаны дополнительные вопросы на других языках:
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
 В следующем примере кода используется синтаксис подсказки detect для поиска объекта на предоставленном изображении. Код использует ранее определенные функции parse_bbox_and_labels() и display_boxes() для интерпретации выходных данных модели и отображения сгенерированных ограничивающих рамок.
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 подсказку
 Следующий пример кода использует синтаксис подсказки segment для поиска области изображения, занимаемой объектом. Он использует библиотеку Google big_vision для интерпретации выходных данных модели и генерации маски для сегментированного объекта.
 Прежде чем начать, установите библиотеку big_vision и ее зависимости, как показано в этом примере кода:
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"
Для этого примера сегментации загрузите и подготовьте другое изображение, на котором изображена кошка.
cat = read_image('https://big-vision-paligemma.hf.space/file=examples/barsik.jpg', target_size)
matplotlib.pyplot.imshow(cat)
Вот функция, которая поможет проанализировать сегментный вывод из PaliGemma
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 для сегментации кота на изображении
prompt = 'segment cat\n'
output = paligemma.generate(
    inputs={
        "images": cat,
        "prompts": prompt,
    }
)
Визуализируйте сгенерированную маску из PaliGemma
bboxes, seg_masks = parse_segments(output)
display_segment_output(cat, bboxes, seg_masks, target_size)
Пакетные запросы
Вы можете предоставить более одной команды подсказки в рамках одной подсказки в виде пакета инструкций. Следующий пример демонстрирует, как структурировать текст подсказки для предоставления нескольких инструкций.
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)
Запустить в Google Colab
Просмотреть исходный код на GitHub