Rregulloni mirë Gemma për detyrat e Vizionit duke përdorur Transformatorët Hugging Face dhe QLoRA

Ky udhëzues ju tregon se si të rregulloni Gemma në një grup të dhënash me imazhe dhe tekst të personalizuar për një detyrë vizioni (gjenerimi i përshkrimeve të produktit) duke përdorur Transformers Hugging Face dhe TRL . Do të mësoni:

  • Çfarë është përshtatja e kuantizuar me gradë të ulët (QLoRA)
  • Konfiguro mjedisin e zhvillimit
  • Krijoni dhe përgatitni grupin e të dhënave të rregullimit të imët për detyrat e vizionit
  • Rregulloni mirë Gemma duke përdorur TRL dhe SFTTrainer
  • Testoni konkluzionet e modelit dhe gjeneroni përshkrimet e produkteve nga imazhet dhe teksti.

Çfarë është përshtatja e kuantizuar me gradë të ulët (QLoRA)

Ky udhëzues demonstron përdorimin e Përshtatjes së Kuantizuar të Rangut të Ulët (QLoRA) , e cila u shfaq si një metodë popullore për të rregulluar në mënyrë efikase LLM-të pasi redukton kërkesat për burime llogaritëse duke ruajtur performancën e lartë. Në QloRA, modeli i paratrajnuar kuantizohet në 4-bit dhe peshat ngrihen. Më pas janë bashkangjitur shtresat e përshtatësve të trajnueshëm (LoRA) dhe trajnohen vetëm shtresat e përshtatësit. Më pas, peshat e përshtatësit mund të bashkohen me modelin bazë ose të mbahen si një përshtatës i veçantë.

Konfiguro mjedisin e zhvillimit

Hapi i parë është instalimi i Bibliotekave Hugging Face, duke përfshirë TRL, dhe grupet e të dhënave për të rregulluar mirë modelin e hapur.

# Install Pytorch & other libraries
%pip install "torch>=2.4.0" tensorboard torchvision

# Install Gemma release branch from Hugging Face
%pip install "transformers>=4.51.3"

# Install Hugging Face libraries
%pip install  --upgrade \
  "datasets==3.3.2" \
  "accelerate==1.4.0" \
  "evaluate==0.4.3" \
  "bitsandbytes==0.45.3" \
  "trl==0.15.2" \
  "peft==0.14.0" \
  "pillow==11.1.0" \
  protobuf \
  sentencepiece

Përpara se të filloni stërvitjen, duhet të siguroheni që i keni pranuar kushtet e përdorimit për Gemma. Ju mund ta pranoni licencën në Hugging Face duke klikuar në butonin "Pranoj dhe aksesoni depo" në faqen e modelit në: http://huggingface.co/google/gemma-3-4b-pt (ose faqen e duhur të modelit për modelin Gemma me aftësi vizioni që po përdorni).

Pasi të keni pranuar licencën, ju nevojitet një shenjë e vlefshme Hugging Face për të hyrë në model. Nëse po vraponi brenda një Google Colab, mund të përdorni në mënyrë të sigurt Token tuaj Hugging Face duke përdorur sekretet e Colab; përndryshe, ju mund ta vendosni shenjën direkt në metodën login . Sigurohuni që token juaj të ketë gjithashtu akses shkrimi, pasi e shtyni modelin tuaj në Hub gjatë trajnimit.

from google.colab import userdata
from huggingface_hub import login

# Login into Hugging Face Hub
hf_token = userdata.get('HF_TOKEN') # If you are running inside a Google Colab
login(hf_token)

Krijoni dhe përgatitni të dhënat e rregullimit të imët

Kur rregulloni mirë LLM-të, është e rëndësishme të dini rastin tuaj të përdorimit dhe detyrën që dëshironi të zgjidhni. Kjo ju ndihmon të krijoni një grup të dhënash për të rregulluar mirë modelin tuaj. Nëse nuk e keni përcaktuar ende rastin tuaj të përdorimit, mund të dëshironi të ktheheni në tabelën e vizatimit.

Si shembull, ky udhëzues fokusohet në rastin e mëposhtëm të përdorimit:

  • Rregulloni një model Gemma për të gjeneruar përshkrime koncize të produkteve të optimizuara nga SEO për një platformë e-commerce, të përshtatur posaçërisht për kërkimin celular.

Ky udhëzues përdor grupin e të dhënave philschmid/amazon-product-descriptions-vlm , një grup të dhënash të përshkrimeve të produkteve të Amazon, duke përfshirë imazhet dhe kategoritë e produkteve.

Hugging Face TRL mbështet bisedat multimodale. Pjesa e rëndësishme është roli "imazh", i cili i thotë klasës së përpunimit se duhet të ngarkojë imazhin. Struktura duhet të ndjekë:

{"messages": [{"role": "system", "content": [{"type": "text", "text":"You are..."}]}, {"role": "user", "content": [{"type": "text", "text": "..."}, {"type": "image"}]}, {"role": "assistant", "content": [{"type": "text", "text": "..."}]}]}
{"messages": [{"role": "system", "content": [{"type": "text", "text":"You are..."}]}, {"role": "user", "content": [{"type": "text", "text": "..."}, {"type": "image"}]}, {"role": "assistant", "content": [{"type": "text", "text": "..."}]}]}
{"messages": [{"role": "system", "content": [{"type": "text", "text":"You are..."}]}, {"role": "user", "content": [{"type": "text", "text": "..."}, {"type": "image"}]}, {"role": "assistant", "content": [{"type": "text", "text": "..."}]}]}

Tani mund të përdorni bibliotekën e grupeve të të dhënave Hugging Face për të ngarkuar grupin e të dhënave dhe për të krijuar një shabllon të shpejtë për të kombinuar imazhin, emrin e produktit dhe kategorinë dhe për të shtuar një mesazh sistemi. Të dhënat përfshijnë imazhe si objekte Pil.Image .

from datasets import load_dataset
from PIL import Image

# System message for the assistant
system_message = "You are an expert product description writer for Amazon."

# User prompt that combines the user query and the schema
user_prompt = """Create a Short Product description based on the provided <PRODUCT> and <CATEGORY> and image.
Only return description. The description should be SEO optimized and for a better mobile search experience.

<PRODUCT>
{product}
</PRODUCT>

<CATEGORY>
{category}
</CATEGORY>
"""

# Convert dataset to OAI messages
def format_data(sample):
    return {
        "messages": [
            {
                "role": "system",
                "content": [{"type": "text", "text": system_message}],
            },
            {
                "role": "user",
                "content": [
                    {
                        "type": "text",
                        "text": user_prompt.format(
                            product=sample["Product Name"],
                            category=sample["Category"],
                        ),
                    },
                    {
                        "type": "image",
                        "image": sample["image"],
                    },
                ],
            },
            {
                "role": "assistant",
                "content": [{"type": "text", "text": sample["description"]}],
            },
        ],
    }

def process_vision_info(messages: list[dict]) -> list[Image.Image]:
    image_inputs = []
    # Iterate through each conversation
    for msg in messages:
        # Get content (ensure it's a list)
        content = msg.get("content", [])
        if not isinstance(content, list):
            content = [content]

        # Check each content element for images
        for element in content:
            if isinstance(element, dict) and (
                "image" in element or element.get("type") == "image"
            ):
                # Get the image and convert to RGB
                if "image" in element:
                    image = element["image"]
                else:
                    image = element
                image_inputs.append(image.convert("RGB"))
    return image_inputs

# Load dataset from the hub
dataset = load_dataset("philschmid/amazon-product-descriptions-vlm", split="train")

# Convert dataset to OAI messages
# need to use list comprehension to keep Pil.Image type, .mape convert image to bytes
dataset = [format_data(sample) for sample in dataset]

print(dataset[345]["messages"])

Rregulloni mirë Gemma duke përdorur TRL dhe SFTTrainer

Tani jeni gati të rregulloni modelin tuaj. Hugging Face TRL SFTTrainer e bën të thjeshtë mbikëqyrjen e rregullimit të saktë të LLM-ve të hapura. SFTTrainer është një nënklasë e Trainer nga biblioteka transformers dhe mbështet të gjitha të njëjtat veçori, duke përfshirë regjistrimin, vlerësimin dhe pikën e kontrollit, por shton veçori shtesë të cilësisë së jetës, duke përfshirë:

  • Formatimi i grupit të të dhënave, duke përfshirë formatet bisedore dhe udhëzuese
  • Trajnimi vetëm për përfundimet, duke injoruar kërkesat
  • Paketimi i të dhënave për trajnim më efikas
  • Mbështetje për rregullimin e saktë të parametrave (PEFT) duke përfshirë QloRA
  • Përgatitja e modelit dhe shënuesit për rregullimin e mirë të bisedës (si p.sh. shtimi i shenjave speciale)

Kodi i mëposhtëm ngarkon modelin dhe simbolin Gemma nga Hugging Face dhe inicializon konfigurimin e kuantizimit.

import torch
from transformers import AutoProcessor, AutoModelForImageTextToText, BitsAndBytesConfig

# Hugging Face model id
model_id = "google/gemma-3-4b-pt" # or `google/gemma-3-12b-pt`, `google/gemma-3-27-pt`

# Check if GPU benefits from bfloat16
if torch.cuda.get_device_capability()[0] < 8:
    raise ValueError("GPU does not support bfloat16, please use a GPU that supports bfloat16.")

# Define model init arguments
model_kwargs = dict(
    attn_implementation="eager", # Use "flash_attention_2" when running on Ampere or newer GPU
    torch_dtype=torch.bfloat16, # What torch dtype to use, defaults to auto
    device_map="auto", # Let torch decide how to load the model
)

# BitsAndBytesConfig int-4 config
model_kwargs["quantization_config"] = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_use_double_quant=True,
    bnb_4bit_quant_type="nf4",
    bnb_4bit_compute_dtype=model_kwargs["torch_dtype"],
    bnb_4bit_quant_storage=model_kwargs["torch_dtype"],
)

# Load model and tokenizer
model = AutoModelForImageTextToText.from_pretrained(model_id, **model_kwargs)
processor = AutoProcessor.from_pretrained("google/gemma-3-4b-it")

SFTTrainer mbështet një integrim të integruar me peft , gjë që e bën të thjeshtë sintonizimin me efikasitet të LLM-ve duke përdorur QLoRA. Ju duhet vetëm të krijoni një LoraConfig dhe t'ia jepni atë trajnerit.

from peft import LoraConfig

peft_config = LoraConfig(
    lora_alpha=16,
    lora_dropout=0.05,
    r=16,
    bias="none",
    target_modules="all-linear",
    task_type="CAUSAL_LM",
    modules_to_save=[
        "lm_head",
        "embed_tokens",
    ],
)

Përpara se të filloni stërvitjen tuaj, duhet të përcaktoni hiperparametrin që dëshironi të përdorni në një SFTConfig dhe një collate_fn të personalizuar për të trajtuar përpunimin e vizionit. collate_fn konverton mesazhet me tekst dhe imazhe në një format që modeli mund të kuptojë.

from trl import SFTConfig

args = SFTConfig(
    output_dir="gemma-product-description",     # directory to save and repository id
    num_train_epochs=1,                         # number of training epochs
    per_device_train_batch_size=1,              # batch size per device during training
    gradient_accumulation_steps=4,              # number of steps before performing a backward/update pass
    gradient_checkpointing=True,                # use gradient checkpointing to save memory
    optim="adamw_torch_fused",                  # use fused adamw optimizer
    logging_steps=5,                            # log every 5 steps
    save_strategy="epoch",                      # save checkpoint every epoch
    learning_rate=2e-4,                         # learning rate, based on QLoRA paper
    bf16=True,                                  # use bfloat16 precision
    max_grad_norm=0.3,                          # max gradient norm based on QLoRA paper
    warmup_ratio=0.03,                          # warmup ratio based on QLoRA paper
    lr_scheduler_type="constant",               # use constant learning rate scheduler
    push_to_hub=True,                           # push model to hub
    report_to="tensorboard",                    # report metrics to tensorboard
    gradient_checkpointing_kwargs={
        "use_reentrant": False
    },  # use reentrant checkpointing
    dataset_text_field="",                      # need a dummy field for collator
    dataset_kwargs={"skip_prepare_dataset": True},  # important for collator
)
args.remove_unused_columns = False # important for collator

# Create a data collator to encode text and image pairs
def collate_fn(examples):
    texts = []
    images = []
    for example in examples:
        image_inputs = process_vision_info(example["messages"])
        text = processor.apply_chat_template(
            example["messages"], add_generation_prompt=False, tokenize=False
        )
        texts.append(text.strip())
        images.append(image_inputs)

    # Tokenize the texts and process the images
    batch = processor(text=texts, images=images, return_tensors="pt", padding=True)

    # The labels are the input_ids, and we mask the padding tokens and image tokens in the loss computation
    labels = batch["input_ids"].clone()

    # Mask image tokens
    image_token_id = [
        processor.tokenizer.convert_tokens_to_ids(
            processor.tokenizer.special_tokens_map["boi_token"]
        )
    ]
    # Mask tokens for not being used in the loss computation
    labels[labels == processor.tokenizer.pad_token_id] = -100
    labels[labels == image_token_id] = -100
    labels[labels == 262144] = -100

    batch["labels"] = labels
    return batch

Tani keni çdo bllok ndërtimi që ju nevojitet për të krijuar SFTTrainer tuaj për të filluar trajnimin e modelit tuaj.

from trl import SFTTrainer

trainer = SFTTrainer(
    model=model,
    args=args,
    train_dataset=dataset,
    peft_config=peft_config,
    processing_class=processor,
    data_collator=collate_fn,
)

Filloni stërvitjen duke thirrur metodën train() .

# Start training, the model will be automatically saved to the Hub and the output directory
trainer.train()

# Save the final model again to the Hugging Face Hub
trainer.save_model()

Përpara se të testoni modelin tuaj, sigurohuni që të lironi memorien.

# free the memory again
del model
del trainer
torch.cuda.empty_cache()

Kur përdorni QLoRA, ju trajnoni vetëm adaptorët dhe jo modelin e plotë. Kjo do të thotë kur ruani modelin gjatë stërvitjes, kurseni vetëm peshat e përshtatësit dhe jo modelin e plotë. Nëse dëshironi të ruani modelin e plotë, gjë që e bën më të lehtë përdorimin me grupe shërbyese si vLLM ose TGI, mund të bashkoni peshat e përshtatësit në peshat e modelit duke përdorur metodën merge_and_unload dhe më pas ta ruani modelin me metodën save_pretrained . Kjo ruan një model të paracaktuar, i cili mund të përdoret për përfundime.

from peft import PeftModel

# Load Model base model
model = AutoModelForImageTextToText.from_pretrained(model_id, low_cpu_mem_usage=True)

# Merge LoRA and base model and save
peft_model = PeftModel.from_pretrained(model, args.output_dir)
merged_model = peft_model.merge_and_unload()
merged_model.save_pretrained("merged_model", safe_serialization=True, max_shard_size="2GB")

processor = AutoProcessor.from_pretrained(args.output_dir)
processor.save_pretrained("merged_model")

Testoni konkluzionet e modelit dhe gjeneroni përshkrimet e produktit

Pas përfundimit të trajnimit, do të dëshironi të vlerësoni dhe testoni modelin tuaj. Ju mund të ngarkoni mostra të ndryshme nga grupi i të dhënave testuese dhe të vlerësoni modelin në ato mostra.

import torch

# Load Model with PEFT adapter
model = AutoModelForImageTextToText.from_pretrained(
  args.output_dir,
  device_map="auto",
  torch_dtype=torch.bfloat16,
  attn_implementation="eager",
)
processor = AutoProcessor.from_pretrained(args.output_dir)

Ju mund të provoni konkluzionet duke ofruar një emër produkti, kategori dhe imazh. sample përfshin një figurë veprimi të mrekullueshme.

import requests
from PIL import Image

# Test sample with Product Name, Category and Image
sample = {
  "product_name": "Hasbro Marvel Avengers-Serie Marvel Assemble Titan-Held, Iron Man, 30,5 cm Actionfigur",
  "category": "Toys & Games | Toy Figures & Playsets | Action Figures",
  "image": Image.open(requests.get("https://m.media-amazon.com/images/I/81+7Up7IWyL._AC_SY300_SX300_.jpg", stream=True).raw).convert("RGB")
}

def generate_description(sample, model, processor):
    # Convert sample into messages and then apply the chat template
    messages = [
        {"role": "system", "content": [{"type": "text", "text": system_message}]},
        {"role": "user", "content": [
            {"type": "image","image": sample["image"]},
            {"type": "text", "text": user_prompt.format(product=sample["product_name"], category=sample["category"])},
        ]},
    ]
    text = processor.apply_chat_template(
        messages, tokenize=False, add_generation_prompt=True
    )
    # Process the image and text
    image_inputs = process_vision_info(messages)
    # Tokenize the text and process the images
    inputs = processor(
        text=[text],
        images=image_inputs,
        padding=True,
        return_tensors="pt",
    )
    # Move the inputs to the device
    inputs = inputs.to(model.device)

    # Generate the output
    stop_token_ids = [processor.tokenizer.eos_token_id, processor.tokenizer.convert_tokens_to_ids("<end_of_turn>")]
    generated_ids = model.generate(**inputs, max_new_tokens=256, top_p=1.0, do_sample=True, temperature=0.8, eos_token_id=stop_token_ids, disable_compile=True)
    # Trim the generation and decode the output to text
    generated_ids_trimmed = [out_ids[len(in_ids) :] for in_ids, out_ids in zip(inputs.input_ids, generated_ids)]
    output_text = processor.batch_decode(
        generated_ids_trimmed, skip_special_tokens=True, clean_up_tokenization_spaces=False
    )
    return output_text[0]

# generate the description
description = generate_description(sample, model, processor)
print(description)

Përmbledhja dhe hapat e mëtejshëm

Ky tutorial trajtoi se si të rregulloni një model Gemma për detyrat e vizionit duke përdorur TRL dhe QLoRA, veçanërisht për gjenerimin e përshkrimeve të produkteve. Shikoni dokumentet e mëposhtme në vijim: