मुख्य सामग्री पर जाएं

Unsloth का उपयोग करके PubMedQA पर DiffusionGemma को फाइन-ट्यून कैसे करें

RunPod H100 GPU पर Unsloth, LoRA, Hugging Face का उपयोग करके PubMedQA पर जैव-चिकित्सीय प्रश्नोत्तर के लिए DiffusionGemma 26B-A4B को फाइन-ट्यून करना सीखें।
अद्यतन 3 अग॰ 2026  · 9 मि॰ पढ़ना

AI के साथ खोजें

ChatGPT में खोलेंClaude में खोलेंPerplexity में खोलें

DiffusionGemma Google DeepMind का एक प्रायोगिक भाषा मॉडल है जो पारंपरिक बड़े भाषा मॉडलों से अलग तरीके से टेक्स्ट उत्पन्न करता है। बाएं से दाएं एक-एक टोकन की भविष्यवाणी करने के बजाय, यह शोरयुक्त टोकनों के एक स्थिर कैनवास से शुरू करता है और कई डीन्वॉइज़िंग चरणों के माध्यम से उन्हें धीरे-धीरे परिष्कृत करता है। इससे मॉडल कई टोकन स्थानों को समानांतर में अपडेट कर सकता है और जनरेशन के दौरान अपने उत्तर के हिस्सों में संशोधन कर सकता है।

इस गाइड में, हम एक NVIDIA H100 GPU का उपयोग करके PubMedQA डेटासेट पर फाइन-ट्यून diffusiongemma-26B-A4B-it करेंगे। मॉडल को एक जैव-चिकित्सीय प्रश्न और सहायक संदर्भ प्राप्त होगा, फिर वह yes, no, या maybe का अनुमान लगाएगा। हम डेटा तैयार करेंगे, एक LoRA एडेप्टर प्रशिक्षित करेंगे, फाइन-ट्यूनिंग से पहले और बाद में मॉडल का मूल्यांकन करेंगे, और अंतिम एडेप्टर को Hugging Face पर अपलोड करेंगे।

मैंने पूरा नोटबुक भी प्रकाशित किया है ताकि आप मूल कोड की समीक्षा कर सकें, साथ-साथ चल सकें, और स्वयं प्रयोग चला सकें।

नोट: यह प्रोजेक्ट केवल सीखने और प्रयोग के लिए है और वास्तविक चिकित्सा निर्णयों के लिए उपयोग नहीं किया जाना चाहिए।

1. RunPod Jupyter Notebook खोलें

एक नया RunPod पॉड NVIDIA H100 GPU के साथ बनाएँ और PyTorch/Jupyter टेम्पलेट चुनें। कम से कम 100 GB का पर्सिस्टेंट स्टोरेज कॉन्फ़िगर करें ताकि पॉड बंद होने पर आपके मॉडल फाइलें और प्रशिक्षण आउटपुट न खोएँ।

अपने Hugging Face एक्सेस टोकन को एक environment variable के रूप में जोड़ें:

HF_TOKEN=your_hugging_face_token

Editing the Runpod Pytorch template

इससे मॉडल और डेटासेट तेज़ी से डाउनलोड होते हैं और आपको नोटबुक से मैन्युअल लॉगिन किए बिना सेव किए गए LoRA एडेप्टर को Hugging Face पर अपलोड करने की सुविधा मिलती है।

कॉन्फ़िगर किया गया पॉड लगभग $3 प्रति घंटे का खर्च होना चाहिए, हालांकि अंतिम मूल्य GPU उपलब्धता और चयनित पॉड प्रकार के अनुसार बदल सकता है।

Runpod H100 GPU summary

पॉड चलने के बाद, RunPod इंटरफ़ेस से JupyterLab या Jupyter Notebook खोलें और diffusiongemma_pubmedqa.ipynb नाम का नया नोटबुक बनाएँ।

2. आवश्यक पैकेज इंस्टॉल करें

DiffusionGemma को लोड, फाइन-ट्यून और सेव करने के लिए आवश्यक लाइब्रेरी और Unsloth इंस्टॉल करने हेतु पहले नोटबुक सेल में निम्न कमांड चलाएँ।

%%capture
%pip install --upgrade pip wheel setuptools packaging ninja
%pip install unsloth
%pip install --no-deps --upgrade --force-reinstall git+https://github.com/unslothai/unsloth-zoo.git git+https://github.com/unslothai/unsloth.git
%pip install sentencepiece protobuf "datasets==4.3.0" "huggingface_hub>=0.34.0" hf_transfer
%pip install --no-deps bitsandbytes accelerate peft trl triton
%pip install --no-deps --upgrade "torchao>=0.16.0"
%pip install --no-deps transformers==5.11.0 "tokenizers>=0.22.0,<=0.23.0"

%%capture कमांड लंबे इंस्टॉलेशन आउटपुट को छिपा देता है। पैकेज वर्ज़न पिन किए गए हैं ताकि DiffusionGemma, Transformers, Unsloth, और ट्रेनिंग लाइब्रेरियों के बीच संगतता संबंधी समस्याएँ न हों।

इंस्टॉलेशन पूरा होने के बाद, आगे बढ़ने से पहले नोटबुक कर्नेल को रीस्टार्ट करें।

3. लाइब्रेरी इम्पोर्ट करें

डेटासेट तैयारी, मॉडल लोडिंग, ट्रेनिंग और मूल्यांकन के लिए आवश्यक लाइब्रेरी इम्पोर्ट करें।

import copy
import os
import random
import time

import torch
from datasets import load_dataset
from unsloth import FastModel

os.environ["HF_HUB_ENABLE_HF_TRANSFER"] = "1"
torch._dynamo.config.recompile_limit = 64

print("Torch:", torch.__version__)
print("CUDA available:", torch.cuda.is_available())
print(
    "GPU:",
    torch.cuda.get_device_name(0)
    if torch.cuda.is_available()
    else "None",
)

HF_HUB_ENABLE_HF_TRANSFER Hugging Face Hub से तेज़ डाउनलोड सक्षम करता है, जबकि Dynamo recompilation सीमा बढ़ाने से मॉडल के साथ काम करते समय रुकावटें कम होती हैं।

सेल सफलतापूर्वक चलने पर, Unsloth ट्रेनिंग एनवायरनमेंट को पैच करेगा, और आउटपुट यह पुष्टि करेगा कि CUDA उपलब्ध है और H100 GPU का पता चल गया है।

🦥 Unsloth: Will patch your computer to enable 2x faster free fine-tuning.
🦥 Unsloth Zoo will now patch everything to make training faster!
Torch: 2.10.0+cu128
CUDA available: True
GPU: NVIDIA H100 80GB HBM3

4. कॉन्फ़िगरेशन सेट करें

एक ही स्थान पर मॉडल, डेटासेट, ट्रेनिंग पैरामीटर, मूल्यांकन सेटिंग्स, और आउटपुट डायरेक्टरी परिभाषित करें।

MODEL_NAME = "unsloth/diffusiongemma-26B-A4B-it"
DATASET_NAME = "qiaojin/PubMedQA"

TRAIN_SUBSET = "pqa_artificial"
EVAL_SUBSET = "pqa_labeled"

N_TRAIN = 3000
N_EVAL = 200

MAX_CONTEXT_CHARS = 2500

STEPS = 60
GRAD_ACCUM = 4
LR = 1e-4
T_LO = 0.1

EVAL_TOTAL = 50
EVAL_DENOISING_STEPS = 16

OUTPUT_DIR = "diffusiongemma_pubmedqa_lora"

हम 3,000 कृत्रिम उदाहरणों का ट्रेनिंग के लिए और 200 मैन्युअली लेबल किए गए उदाहरणों का मूल्यांकन के लिए उपयोग करेंगे। प्रयोग को तेज़ रखने के लिए, मॉडल 60 स्टेप्स तक ट्रेन होगा और 16 डीन्वॉइज़िंग स्टेप्स के साथ 50 उदाहरणों का मूल्यांकन करेगा।

DiffusionGemma कैसे काम करता है

मॉडल लोड करने से पहले, यह समझना उपयोगी है कि DiffusionGemma वास्तव में उत्तर कैसे बनाता है। क्रमशः टोकन लिखने के बजाय, यह एक निश्चित लंबाई के कैनवास से शुरू करता है और कई डीन्वॉइज़िंग चरणों में कई स्थानों को एक साथ अपडेट करते हुए उसे परिष्कृत करता है, जब तक कि टेक्स्ट एक सुसंगत उत्तर में न बदल जाए। 

नीचे दिया गया कोड 256 की कैनवास लंबाई, यानी एक सिंगल ब्लॉक का आकार, रिपोर्ट करता है। हमारे छोटे yes/no/maybe उत्तरों के लिए एक कैनवास पर्याप्त है, जबकि लंबे आउटपुट ब्लॉक-ब्लॉक करके कैनवास को जोड़कर बनाए जाते हैं। नीचे दिया गया आरेख उच्च स्तर पर इस परिष्करण प्रक्रिया को दिखाता है:

Text Diffusion Explanation

5. DiffusionGemma लोड करें

bfloat16 प्रिसीजन में instruction-tuned DiffusionGemma मॉडल लोड करें। हम 4-बिट क्वांटाइज़ेशन का उपयोग नहीं करेंगे क्योंकि H100 GPU में उच्च प्रिसीजन पर मॉडल लोड करने के लिए पर्याप्त मेमोरी है।

model, tokenizer = FastModel.from_pretrained(
    model_name=MODEL_NAME,
    dtype=torch.bfloat16,
    load_in_4bit=False,
)

processor = tokenizer
tok = processor.tokenizer if hasattr(processor, "tokenizer") else processor

vocab = model.config.text_config.vocab_size
canvas_len = model.config.canvas_length

dev = next(
    (p.device for p in model.parameters() if p.device.type != "meta"),
    torch.device("cuda"),
)

print("Vocab size:", vocab)
print("Canvas length:", canvas_len)
print("Model device:", dev)

वोकैबुलरी साइज का उपयोग डिफ्यूज़न ट्रेनिंग के दौरान रैंडम शोर जोड़ते समय होता है। कैनवास लंबाई यह निर्धारित करती है कि एक जेनरेशन ब्लॉक में मॉडल अधिकतम कितने टोकन परिष्कृत कर सकता है।

आपको ऐसा आउटपुट दिखना चाहिए:

Vocab size: 262144
Canvas length: 256
Model device: cuda:0

6. LoRA एडेप्टर जोड़ें

एक LoRA एडेप्टर जोड़ें ताकि पूरे 26-बिलियन-पैरामीटर मॉडल को अपडेट करने के बजाय केवल थोड़े से अतिरिक्त पैरामीटर प्रशिक्षित हों।

model = FastModel.get_peft_model(
    model,
    r=64,
    lora_alpha=128,
    use_gradient_checkpointing=False,
)

इससे फाइन-ट्यूनिंग के लिए आवश्यक मेमोरी और कंप्यूट में काफी कमी आती है। ग्रेडिएंट चेकपॉइंटिंग को अक्षम किया गया है क्योंकि इस प्रयोग के लिए H100 में पर्याप्त GPU मेमोरी है।

7. PubMedQA लोड करें

ट्रेनिंग के लिए कृत्रिम PubMedQA सबसेट और मूल्यांकन के लिए मैन्युअली लेबल किया गया सबसेट लोड करें।

train_data = load_dataset(
    DATASET_NAME,
    TRAIN_SUBSET,
    split="train",
)

eval_data = load_dataset(
    DATASET_NAME,
    EVAL_SUBSET,
    split="train",
)

print("Train size:", len(train_data))
print("Eval size:", len(eval_data))
print(train_data[0])

ट्रेनिंग सबसेट में स्वतः उत्पन्न उदाहरण हैं, जबकि मूल्यांकन सबसेट में विशेषज्ञों द्वारा लेबल किए गए जैव-चिकित्सीय प्रश्न हैं। 

डेटा फ़ॉर्मेट करने से पहले पहला रो प्रिंट करने से हम प्रश्न, एब्स्ट्रैक्ट संदर्भ, और अंतिम निर्णय की जाँच कर सकते हैं।

आपको यह दिखना चाहिए:

Train size: 211269
Eval size: 1000

प्रत्येक उदाहरण में एक जैव-चिकित्सीय प्रश्न, एक या अधिक सहायक एब्स्ट्रैक्ट पैसेज, और yes, no, या maybe का अंतिम उत्तर होता है।

Loading the PubMedQA

8. डेटासेट को कन्वर्ट करें

प्रत्येक PubMedQA उदाहरण को चैट-स्टाइल फ़ॉर्मेट में बदलें जिसमें एक उपयोगकर्ता प्रॉम्प्ट और एक असिस्टेंट उत्तर शामिल हो।

def make_prompt(row):
    context = " ".join(row["context"]["contexts"])
    context = context[:MAX_CONTEXT_CHARS]
    question = row["question"]

    return f"""Answer the biomedical research question using only the context.

Context:
{context}

Question:
{question}

Answer with only one word: yes, no, or maybe."""


def make_answer(row):
    return row["final_decision"].strip().lower()


def convert_row(row):
    answer = make_answer(row)

    if answer not in ["yes", "no", "maybe"]:
        return None

    return {
        "messages": [
            {"role": "user", "content": make_prompt(row)},
            {"role": "assistant", "content": answer},
        ]
    }


train_rows = []

for row in train_data.select(range(N_TRAIN)):
    item = convert_row(row)

    if item is not None:
        train_rows.append(item)


eval_rows = []

for row in eval_data.select(range(N_EVAL)):
    item = convert_row(row)

    if item is not None:
        eval_rows.append(item)


print("Prepared train examples:", len(train_rows))
print("Prepared eval examples:", len(eval_rows))
print(train_rows[0]["messages"][0]["content"])
print("Answer:", train_rows[0]["messages"][1]["content"])

संदर्भ पैसेज को एक सिंगल स्ट्रिंग में संयोजित किया जाता है और इनपुट को प्रबंधनीय रखने के लिए 2,500 कैरेक्टर तक सीमित किया जाता है। प्रत्येक उत्तर को लोअरकेस में बदला जाता है, और yes, no, या maybe के बाहर वाले लेबल वाले उदाहरण हटा दिए जाते हैं।

पहला कन्वर्ट किया गया उदाहरण प्रिंट करने से ट्रेनिंग से पहले यह पुष्टि करने में मदद मिलती है कि संदर्भ, प्रश्न और उत्तर सही तरह से फ़ॉर्मेट हुए हैं।

Formatting the PubMedQA dataset in chat format

9. डिफ्यूज़न ट्रेनिंग उदाहरण बनाएँ

DiffusionGemma को लक्ष्य उत्तर को एक स्थिर लंबाई के कैनवास के भीतर रखना आवश्यक होता है। यह फ़ंक्शन प्रॉम्प्ट को टोकनाइज़ करता है, उत्तर को टोकन IDs में बदलता है, उसे मॉडल के कैनवास की लंबाई तक पैड करता है, और एक मास्क बनाता है जो दिखाता है कि किन टोकनों को लॉस में योगदान देना चाहिए।

eos = model.generation_config.eos_token_id or [1]
eos = eos[0] if isinstance(eos, (list, tuple)) else eos

pad = tok.pad_token_id if tok.pad_token_id is not None else eos


def build_examples(rows):
    examples = []

    for row in rows:
        user_message = row["messages"][0]
        assistant_message = row["messages"][1]

        prompt_ids = processor.apply_chat_template(
            [user_message],
            tokenize=True,
            add_generation_prompt=True,
            return_tensors="pt",
        )[0]

        answer_ids = tok.encode(
            assistant_message["content"],
            add_special_tokens=False,
        )

        content = answer_ids + [eos]
        n = len(content)

        if n > canvas_len:
            continue

        x0 = torch.tensor(
            content + [pad] * (canvas_len - n),
            dtype=torch.long,
        )

        loss_mask = torch.zeros(canvas_len, dtype=torch.bool)
        loss_mask[:n] = True

        examples.append((prompt_ids, x0, loss_mask))

    return examples


examples = build_examples(train_rows)

प्रत्येक उत्तर के बाद end-of-sequence टोकन जोड़ा जाता है, जबकि शेष कैनवास स्थानों को पैडिंग टोकनों से भरा जाता है। लॉस मास्क सुनिश्चित करता है कि ट्रेनिंग पैड किए गए स्थानों के बजाय केवल उत्तर और end-of-sequence टोकनों पर केंद्रित रहे।

10. इन्फ़रेंस और मूल्यांकन फ़ंक्शन बनाएँ

अब, उत्तर जनरेट करने, मॉडल के आउटपुट को साफ़ करने, और मूल्यांकन सटीकता की गणना करने के लिए फ़ंक्शन परिभाषित करें।

उत्तर जनरेट करें

answer_question() फ़ंक्शन प्रॉम्प्ट को फ़ॉर्मेट करता है, कई डीन्वॉइज़िंग चरणों के माध्यम से प्रतिक्रिया जनरेट करता है, और जेनरेटेड टोकनों को टेक्स्ट में डिकोड करता है।

def answer_question(prompt, steps=64):
    input_ids = processor.apply_chat_template(
        [{"role": "user", "content": prompt}],
        tokenize=True,
        add_generation_prompt=True,
        return_tensors="pt",
    ).to(dev)

    gen_config = copy.deepcopy(model.generation_config)
    gen_config.max_denoising_steps = steps
    gen_config.max_new_tokens = canvas_len

    model.eval()

    with torch.no_grad():
        output = model.generate(
            input_ids=input_ids,
            generation_config=gen_config,
        )

    generated = output.sequences[0, input_ids.shape[1]:]
    text = tok.decode(
        generated.tolist(),
        skip_special_tokens=True,
    )

    return text.strip().lower()

प्रेडिक्शन निकालें

हालाँकि प्रॉम्प्ट एक-शब्दीय उत्तर मांगता है, मॉडल कभी-कभी अतिरिक्त टेक्स्ट भी जनरेट कर सकता है। यह फ़ंक्शन पहले मान्य yes, no, या maybe प्रेडिक्शन को निकालता है।

def clean_prediction(text):
    text = text.lower().strip()

    if text.startswith("yes"):
        return "yes"

    if text.startswith("no"):
        return "no"

    if text.startswith("maybe"):
        return "maybe"

    words = text.replace(".", " ").replace(",", " ").split()

    for word in words:
        if word in ["yes", "no", "maybe"]:
            return word

    return "unknown"

सटीकता का मूल्यांकन करें

मूल्यांकन फ़ंक्शन प्रत्येक साफ़ किए गए प्रेडिक्शन की सही उत्तर से तुलना करता है, हर उदाहरण के लिए परिणाम प्रिंट करता है, और समग्र सटीकता को व्यक्तिगत प्रेडिक्शनों के साथ वापस करता है।

def evaluate_model(
    rows,
    total=50,
    steps=64,
    title="Evaluation",
):
    correct = 0
    results = []
    total = min(total, len(rows))

    print(title)
    print("-" * len(title))

    for i, row in enumerate(rows[:total], start=1):
        prompt = row["messages"][0]["content"]
        gold = row["messages"][1]["content"]

        raw_pred = answer_question(prompt, steps=steps)
        pred = clean_prediction(raw_pred)

        is_correct = pred == gold
        correct += int(is_correct)

        results.append({
            "index": i,
            "gold": gold,
            "prediction": pred,
            "raw_prediction": raw_pred,
            "correct": is_correct,
        })

        print(
            f"{i:02d}. Gold: {gold} | "
            f"Pred: {pred} | Correct: {is_correct}"
        )

    accuracy = correct / total if total else 0

    print()
    print("Accuracy:", accuracy)
    print()

    return {
        "accuracy": accuracy,
        "correct": correct,
        "total": total,
        "results": results,
    }

11. फाइन-ट्यूनिंग से पहले मॉडल का मूल्यांकन करें

बेसलाइन स्थापित करने के लिए ट्रेनिंग से पहले मूल्यांकन चलाएँ।

before_eval = evaluate_model(
    eval_rows,
    total=EVAL_TOTAL,
    steps=EVAL_DENOISING_STEPS,
    title="Before Fine-Tuning Evaluation",
)

यह प्रत्येक उत्तर के लिए 16 डीन्वॉइज़िंग स्टेप्स का उपयोग करके 50 उदाहरणों का मूल्यांकन करता है। इस प्रयोग में, बेस मॉडल ने 50 में से 30 प्रश्नों का सही उत्तर दिया।

Baseline result of the DiffusionGemma

इस बेसलाइन की आगे फाइन-ट्यूनिंग के बाद मॉडल की सटीकता से तुलना की जाएगी।

12. ट्रेनिंग सेट अप करें

मॉडल को ट्रेनिंग मोड में स्विच करें, ऑप्टिमाइज़र और लर्निंग-रेट शेड्यूलर बनाएँ, और डिफ्यूज़न ट्रेनिंग के दौरान स्वच्छ उत्तर टोकनों को कैसे भ्रष्ट किया जाएगा, यह परिभाषित करें।

model.config.use_cache = True
model.train()

opt = torch.optim.AdamW(
    [p for p in model.parameters() if p.requires_grad],
    lr=LR,
    betas=(0.9, 0.95),
    weight_decay=0.0,
)

sched = torch.optim.lr_scheduler.OneCycleLR(
    opt,
    max_lr=LR,
    total_steps=STEPS,
    pct_start=0.03,
    anneal_strategy="cos",
)

केवल requires_grad=True वाले पैरामीटर ऑप्टिमाइज़र को पास किए जाते हैं, जिसका अर्थ है कि ट्रेनिंग प्रक्रिया पूरे मॉडल के बजाय LoRA एडेप्टर को अपडेट करती है।

अब, एक corruption फ़ंक्शन बनाएँ जो उत्तर के कैनवास के एक रैंडम अनुपात को रैंडम टोकनों से बदल दे।

def corrupt(x0):
    noise_level = random.uniform(T_LO, 1.0)

    xt = x0.to(dev).clone()

    noise_mask = (
        torch.rand(canvas_len, device=dev) < noise_level
    )

    xt[noise_mask] = torch.randint(
        0,
        vocab,
        (canvas_len,),
        device=dev,
    )[noise_mask]

    return xt.unsqueeze(0)

शोर की मात्रा हर उदाहरण के लिए बदलती है। ट्रेनिंग के दौरान, मॉडल इन भ्रष्ट कैनवास टोकनों से मूल उत्तर का पुनर्निर्माण करना सीखता है।

13. मॉडल को ट्रेन करें

निम्न लूप ग्रेडिएंट एक्यूमुलेशन का उपयोग करके 60 स्टेप्स तक LoRA एडेप्टर को ट्रेन करता है।

order = list(range(len(examples)))
ptr = 0
start_time = time.time()

opt.zero_grad(set_to_none=True)

for step in range(1, STEPS + 1):
    step_loss = 0.0

    for _ in range(GRAD_ACCUM):
        if ptr >= len(order):
            random.shuffle(order)
            ptr = 0

        prompt_ids, x0, loss_mask = examples[order[ptr]]
        ptr += 1

        output = model(
            input_ids=prompt_ids.unsqueeze(0).to(dev),
            canvas_ids=corrupt(x0),
            self_conditioning_logits=None,
        )

        logits = output.logits[0].float()
        mask = loss_mask.to(dev)

        loss = torch.nn.functional.cross_entropy(
            logits[mask],
            x0.to(dev)[mask],
        )

        (loss / GRAD_ACCUM).backward()
        step_loss += loss.item() / GRAD_ACCUM

    torch.nn.utils.clip_grad_norm_(
        [
            p
            for p in model.parameters()
            if p.requires_grad
        ],
        1.0,
    )

    opt.step()
    sched.step()
    opt.zero_grad(set_to_none=True)

    if step % 20 == 0:
        elapsed = time.time() - start_time

        print(
            f"step {step}/{STEPS} | "
            f"loss {step_loss:.4f} | "
            f"{elapsed:.0f}s"
        )

प्रत्येक ट्रेनिंग उदाहरण के लिए, मॉडल को जैव-चिकित्सीय प्रॉम्प्ट और एक भ्रष्ट उत्तर कैनवास मिलता है। क्रॉस-एंट्रॉपी लॉस केवल लॉस मास्क द्वारा चुने गए वास्तविक उत्तर टोकनों के लिए गणना किया जाता है।

ग्रेडिएंट एक्यूमुलेशन, मॉडल अपडेट करने से पहले चार उदाहरणों को संयोजित करता है। ग्रेडिएंट क्लिपिंग भी ट्रेनिंग को स्थिर रखने के लिए लागू की जाती है।

इस प्रयोग में, ट्रेनिंग लगभग दो मिनट में पूरी हुई:

step 20/60 | loss 0.0019 | 43s
step 40/60 | loss 0.0003 | 85s
step 60/60 | loss 0.0001 | 126s

लगातार घटता लॉस यह दर्शाता है कि एडेप्टर भ्रष्ट कैनवास से अपेक्षित उत्तरों का पुनर्निर्माण करना सीख रहा है। ट्रेनिंग के दौरान, आप GPU मेमोरी उपयोग और उपयोगिता की निगरानी के लिए RunPod टर्मिनल में nvidia-smi भी चला सकते हैं।

Nvidia model statistic while model training

14. फाइन-ट्यून किए गए मॉडल का मूल्यांकन करें

फाइन-ट्यूनिंग के बाद वही मूल्यांकन फिर से चलाएँ ताकि मापा जा सके कि मॉडल का प्रदर्शन बेहतर हुआ है या नहीं।

after_eval = evaluate_model(
    eval_rows,
    total=EVAL_TOTAL,
    steps=EVAL_DENOISING_STEPS,
    title="After Fine-Tuning Evaluation",
)

फाइन-ट्यून मॉडल का मूल्यांकन उन्हीं 50 उदाहरणों और उन्हीं 16 डीन्वॉइज़िंग स्टेप्स के साथ किया जाता है जैसा कि बेसलाइन मूल्यांकन में था।

Fine-tune result of the DiffusionGemma

अब, फाइन-ट्यूनिंग से पहले और बाद की सटीकता की तुलना करें।

before_accuracy = before_eval["accuracy"]
after_accuracy = after_eval["accuracy"]
improvement = after_accuracy - before_accuracy

print("Before fine-tuning accuracy:", before_accuracy)
print("After fine-tuning accuracy:", after_accuracy)
print("Improvement:", improvement)
Before fine-tuning accuracy: 0.6
After fine-tuning accuracy: 0.8
Improvement: 0.2

इस प्रयोग में, मॉडल की सटीकता 0.60 से बढ़कर 0.80 हो गई।

यह 20 प्रतिशत-बिंदु का सुधार दर्शाता है—फाइन-ट्यूनिंग के बाद मॉडल ने 50 में से 40 प्रश्नों का सही उत्तर दिया, जबकि ट्रेनिंग से पहले 50 में से 30 सही थे।

15. फाइन-ट्यून एडेप्टर को सेव और अपलोड करें

ट्रेन किया गया LoRA एडेप्टर और प्रोसेसर फाइलों को पहले परिभाषित आउटपुट डायरेक्टरी में सेव करें।

model.save_pretrained(OUTPUT_DIR)
processor.save_pretrained(OUTPUT_DIR)

print(f"Saved LoRA adapter to: {OUTPUT_DIR}")

आपको यह दिखना चाहिए:

Saved LoRA adapter to: diffusiongemma_pubmedqa_lora

इससे 26-बिलियन-पैरामीटर वाले बेस मॉडल की एक और पूरी कॉपी के बजाय केवल हल्का LoRA एडेप्टर सेव होता है।

अब एडेप्टर और प्रोसेसर फाइलें Hugging Face Hub पर अपलोड करें:

REPO_ID = "kingabzpro/diffusiongemma_pubmedqa"

model.push_to_hub(REPO_ID)
processor.push_to_hub(REPO_ID)

क्योंकि RunPod पॉड कॉन्फ़िगरेशन के दौरान HF_TOKEN environment variable जोड़ा गया था, Hugging Face को स्वतः प्रमाणित होना चाहिए। आपको केवल तब notebook_login() चलाने की आवश्यकता है जब टोकन पहले से कॉन्फ़िगर न हो:

from huggingface_hub import notebook_login

notebook_login()

अपलोड पूरा होने के बाद, रिपॉजिटरी में LoRA एडेप्टर और वह प्रोसेसर कॉन्फ़िगरेशन होगा जिसकी आवश्यकता बाद में फाइन-ट्यून मॉडल लोड करने के लिए पड़ेगी।

Finetuned lora on Hugging face: diffusiongemma_pubmedqa

स्रोत: kingabzpro/diffusiongemma_pubmedqa · Hugging Face 

अंतिम विचार

Unsloth के साथ DiffusionGemma को फाइन-ट्यून करना आश्चर्यजनक रूप से आसान था। सबसे समय लेने वाला भाग सही डिपेंडेंसी इंस्टॉल करना और डिफ्यूज़न-विशिष्ट ट्रेनिंग प्रक्रिया को समझना था। एक बार एनवायरनमेंट सेट हो जाने पर, मॉडल लोड करना, LoRA एडेप्टर को ट्रेन करना, उसका मूल्यांकन करना, और परिणामों को Hugging Face पर अपलोड करना सभी बहुत सहज रहा।

मुझे DiffusionGemma खास तौर पर दिलचस्प लगा क्योंकि यह पारंपरिक भाषा मॉडल की तरह एक-एक करके टोकन जनरेट नहीं करता। इसके बजाय, यह एक स्थिर कैनवास के साथ काम करता है और डीन्वॉइज़िंग स्टेप्स के ज़रिए शोरयुक्त टोकनों को धीरे-धीरे परिष्कृत करता है। इस भिन्न जेनरेशन प्रक्रिया को समझना और इसे जैव-चिकित्सीय प्रश्नोत्तर कार्य पर फाइन-ट्यून करना मेरे लिए विशेष रूप से मूल्यवान रहा।

छोटे सेटअप के बावजूद, 50-उदाहरण सैंपल पर सटीकता 0.60 से 0.80 तक बढ़ी—हालाँकि इतने छोटे सैंपल पर त्रुटि की सीमा व्यापक होती है, और इस मूल्यांकन सेट पर "हमेशा yes" बेसलाइन पहले से लगभग 55% स्कोर करती है। 

यह भी ध्यान देने योग्य है कि कृत्रिम ट्रेनिंग सबसेट में लगभग कोई "maybe" लेबल नहीं है, इसलिए मॉडल को उस वर्ग को सीखने का बहुत कम मौका मिलता है, भले ही वह मूल्यांकन डेटा में दिखाई देता हो। इसे इस रूप में देखें कि यह फाइन-ट्यूनिंग प्रक्रिया कैसे काम करती है का एक त्वरित प्रयोग है, न कि इस बात का प्रमाण कि मॉडल वास्तविक चिकित्सा उपयोग के लिए तैयार है।

एक सिंगल फाइन-ट्यूनिंग रन से आगे बढ़ने के लिए तैयार हैं? हमारा Developing Large Language Models ट्रैक आपको PyTorch और transformers की बुनियाद से लेकर अपने स्वयं के LLMs बनाने और उन्हें डिप्लॉय करने तक ले जाता है।

विषय

शीर्ष LLM कोर्स

Track

बड़े भाषा मॉडल विकसित करना

16 घंटा
PyTorch और Hugging Face के साथ बड़े भाषा मॉडल (LLMs) विकसित करना सीखें, नवीनतम डीप लर्निंग और NLP तकनीकों का उपयोग करते हुए।
विस्तृत जानकारी देखेंRight Arrow
कोर्स शुरू करें
और देखेंRight Arrow