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

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

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

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

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

قبل از شروع

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

راه اندازی

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

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

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

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

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

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

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

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

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

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

  1. در سمت راست بالای پنجره Colab، روی منوی کشویی ▾ (گزینه های اتصال اضافی) کلیک کنید.
  2. تغییر نوع زمان اجرا را انتخاب کنید.
  3. در بخش شتاب دهنده سخت افزار ، GPU T4 را انتخاب کنید.

تنظیم متغیرهای محیطی

متغیرهای محیطی را برای 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 و 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 استفاده کنید

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

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)