Keras की मदद से PaliGemma का आउटपुट जनरेट करना

ai.google.dev पर देखें Google Colab में चलाएं Vertex AI में खोलें GitHub पर सोर्स देखें

PaliGemma मॉडल में मल्टीमोडल क्षमताएं होती हैं. इनकी मदद से, टेक्स्ट और इमेज, दोनों तरह के इनपुट डेटा का इस्तेमाल करके आउटपुट जनरेट किया जा सकता है. इन मॉडल के साथ इमेज डेटा का इस्तेमाल किया जा सकता है. इससे अपने अनुरोधों के लिए ज़्यादा जानकारी दी जा सकती है. इसके अलावा, इमेज के कॉन्टेंट का विश्लेषण करने के लिए भी मॉडल का इस्तेमाल किया जा सकता है. इस ट्यूटोरियल में, Keras के साथ PaliGemma का इस्तेमाल करने का तरीका बताया गया है. इससे इमेज का विश्लेषण किया जा सकता है और उनके बारे में पूछे गए सवालों के जवाब दिए जा सकते हैं.

इस नोटबुक में क्या है

यह नोटबुक, Keras के साथ PaliGemma का इस्तेमाल करती है. इसमें आपको यह जानकारी मिलेगी:

  • Keras और ज़रूरी डिपेंडेंसी इंस्टॉल करना
  • PaliGemmaCausalLM डाउनलोड करें. यह विज़ुअल लैंग्वेज मॉडलिंग के लिए, पहले से ट्रेन किया गया PaliGemma का एक वैरिएंट है. इसका इस्तेमाल करके एक मॉडल बनाएं
  • यह टेस्ट करें कि मॉडल, दी गई इमेज के बारे में जानकारी का अनुमान लगा सकता है या नहीं

शुरू करने से पहले

इस नोटबुक को पढ़ने से पहले, आपको Python कोड के साथ-साथ बड़े लैंग्वेज मॉडल (एलएलएम) को ट्रेन करने के तरीके के बारे में भी जानकारी होनी चाहिए. आपको Keras के बारे में जानकारी होना ज़रूरी नहीं है. हालांकि, उदाहरण के तौर पर दिए गए कोड को पढ़ते समय, Keras के बारे में बुनियादी जानकारी होना मददगार होता है.

सेटअप

यहां दिए गए सेक्शन में, PaliGemma मॉडल का इस्तेमाल करने के लिए नोटबुक पाने का तरीका बताया गया है. इसमें मॉडल का ऐक्सेस पाना, एपीआई कुंजी पाना, और नोटबुक रनटाइम को कॉन्फ़िगर करना शामिल है.

PaliGemma का ऐक्सेस पाना

पहली बार PaliGemma का इस्तेमाल करने से पहले, आपको Kaggle के ज़रिए मॉडल के ऐक्सेस का अनुरोध करना होगा. इसके लिए, यह तरीका अपनाएं:

  1. Kaggle में लॉग इन करें. अगर आपके पास पहले से कोई Kaggle खाता नहीं है, तो एक नया खाता बनाएं.
  2. PaliGemma मॉडल कार्ड पर जाएं और ऐक्सेस का अनुरोध करें पर क्लिक करें.
  3. सहमति वाला फ़ॉर्म भरें और नियम और शर्तें स्वीकार करें.

एपीआई पासकोड कॉन्फ़िगर करना

PaliGemma का इस्तेमाल करने के लिए, आपको अपना Kaggle उपयोगकर्ता नाम और Kaggle API कुंजी देनी होगी.

Kaggle API पासकोड जनरेट करने के लिए, Kaggle में सेटिंग पेज खोलें. इसके बाद, नया टोकन बनाएं पर क्लिक करें. इससे, आपके एपीआई क्रेडेंशियल वाली kaggle.json फ़ाइल डाउनलोड हो जाती है.

इसके बाद, Colab में बाईं ओर मौजूद पैनल में Secrets (🔑) को चुनें. इसके बाद, अपना Kaggle उपयोगकर्ता नाम और Kaggle API कुंजी जोड़ें. अपने उपयोगकर्ता नाम को KAGGLE_USERNAME नाम से और अपने एपीआई पासकोड को KAGGLE_KEY नाम से सेव करें.

रनटाइम चुनें

इस ट्यूटोरियल को पूरा करने के लिए, आपके पास Colab रनटाइम होना चाहिए. साथ ही, इसमें PaliGemma मॉडल को चलाने के लिए ज़रूरी संसाधन होने चाहिए. इस मामले में, T4 GPU का इस्तेमाल किया जा सकता है:

  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 इंस्टॉल करना

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")

मॉडल लोड करना

अब सब कुछ सेट अप हो गया है. इसलिए, पहले से ट्रेन किए गए मॉडल को डाउनलोड किया जा सकता है. साथ ही, कुछ ऐसे यूटिलिटी तरीके बनाए जा सकते हैं जिनसे मॉडल को जवाब जनरेट करने में मदद मिले. इस चरण में, Keras Hub से PaliGemmaCausalLM का इस्तेमाल करके मॉडल डाउनलोड किया जाता है. इस क्लास की मदद से, 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: यह एक मान्य यूआरएल के ज़रिए इमेज लेता है. मॉडल को इमेज भेजने के लिए, आपको इस तरीके का इस्तेमाल करना होगा.

इस नोटबुक के अगले चरण में, 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 प्रॉम्प्ट सिंटैक्स का इस्तेमाल किया गया है. यह कोड, पहले से तय किए गए 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)