خروجی PaliGemma را با Keras ایجاد کنید

مشاهده در ai.google.dev در گوگل کولب اجرا کنید باز کردن در Vertex AI مشاهده منبع در گیت‌هاب

مدل‌های PaliGemma قابلیت‌های چندوجهی دارند و به شما امکان می‌دهند خروجی را با استفاده از داده‌های ورودی متن و تصویر تولید کنید. می‌توانید از داده‌های تصویر با این مدل‌ها برای ارائه زمینه اضافی برای درخواست‌های خود استفاده کنید یا از این مدل برای تجزیه و تحلیل محتوای تصاویر استفاده کنید. این آموزش به شما نشان می‌دهد که چگونه از PaliGemma با Keras برای تجزیه و تحلیل تصاویر و پاسخ به سوالات مربوط به آنها استفاده کنید.

آنچه در این دفترچه یادداشت است

این دفترچه یادداشت از PaliGemma به همراه Keras استفاده می‌کند و به شما نشان می‌دهد که چگونه:

  • نصب Keras و وابستگی‌های مورد نیاز
  • PaliGemmaCausalLM ، یک گونه از پیش آموزش‌دیده PaliGemma برای مدل‌سازی زبان بصری سببی را دانلود کنید و از آن برای ایجاد یک مدل استفاده کنید.
  • توانایی مدل را در استنباط اطلاعات مربوط به تصاویر ارائه شده آزمایش کنید

قبل از اینکه شروع کنی

قبل از مطالعه این دفترچه، باید با کد پایتون و همچنین نحوه آموزش مدل‌های زبانی بزرگ (LLM) آشنا باشید. نیازی به آشنایی با Keras نیست، اما دانش اولیه در مورد Keras هنگام خواندن کد نمونه مفید است.

راه‌اندازی

بخش‌های زیر مراحل اولیه برای استفاده از مدل PaliGemma در یک نوت‌بوک، از جمله دسترسی به مدل، دریافت کلید API و پیکربندی زمان اجرای نوت‌بوک را توضیح می‌دهند.

به PaliGemma دسترسی پیدا کنید

قبل از اولین استفاده از PaliGemma، باید با انجام مراحل زیر، از طریق Kaggle درخواست دسترسی به مدل را بدهید:

  1. وارد حساب کاگل شوید، یا اگر از قبل حساب کاگل ندارید، یک حساب کاگل جدید ایجاد کنید.
  2. به کارت مدل PaliGemma بروید و روی درخواست دسترسی کلیک کنید.
  3. فرم رضایت‌نامه را تکمیل کنید و شرایط و ضوابط را بپذیرید.

کلید API خود را پیکربندی کنید

برای استفاده از PaliGemma، باید نام کاربری Kaggle و یک کلید API Kaggle خود را ارائه دهید.

برای تولید کلید API کاگل، صفحه تنظیمات خود را در کاگل باز کنید و روی ایجاد توکن جدید کلیک کنید. این کار باعث دانلود فایل kaggle.json حاوی اطلاعات احراز هویت API شما می‌شود.

سپس، در Colab، در پنل سمت چپ، گزینه Secrets (🔑) را انتخاب کنید و نام کاربری Kaggle و کلید API Kaggle خود را اضافه کنید. نام کاربری خود را با نام KAGGLE_USERNAME و کلید API خود را با نام KAGGLE_KEY ذخیره کنید.

زمان اجرا را انتخاب کنید

برای تکمیل این آموزش، به یک محیط اجرای Colab با منابع کافی برای اجرای مدل PaliGemma نیاز دارید. در این حالت، می‌توانید از یک پردازنده گرافیکی T4 استفاده کنید:

  1. در سمت راست بالای پنجره Colab، روی منوی کشویی ▾ (گزینه‌های اتصال اضافی) کلیک کنید.
  2. تغییر نوع زمان اجرا را انتخاب کنید.
  3. در قسمت شتاب‌دهنده سخت‌افزاری ، 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، سلول زیر را اجرا کنید.

pip install -U -q keras-nlp keras-hub kagglehub

وارد کردن وابستگی‌ها و پیکربندی Keras

وابستگی‌های مورد نیاز برای این نوت‌بوک را نصب کنید و backend کرس را پیکربندی کنید. همچنین کرس را طوری تنظیم خواهید کرد که از 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 و 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 prompt برای یافتن یک شیء در تصویر ارائه شده استفاده می‌کند. این کد از توابع 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 برای تعیین محل اشغال شده توسط یک شیء در تصویر استفاده می‌کند. این کد از کتابخانه 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)

درخواست‌های دسته‌ای

شما می‌توانید بیش از یک دستور prompt را در یک prompt به عنوان مجموعه‌ای از دستورالعمل‌ها ارائه دهید. مثال زیر نحوه ساختاردهی متن prompt برای ارائه چندین دستورالعمل را نشان می‌دهد.

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)