एक LLM बनाएँमध्यमपाठ 526 मिनट का पाठ

स्टेप 16 · LoRA, वह रास्ता जो ज़्यादातर लोग चुनते हैं

0.1% पैरामीटर्स को ट्रेन करें, ज़्यादातर फ़ायदे पाएं, वो भी सिर्फ़ एक कंज़्यूमर GPU पर। यह पूरे ट्रैक में सबसे ज़्यादा प्रैक्टिकल वैल्यू वाला मॉड्यूल है।

पाठ वीडियो में

60 सेकंड में

स्टेप 16 · LoRA, वह रास्ता जो ज़्यादातर लोग चुनते हैं

0.1% पैरामीटर्स को ट्रेन करें, ज़्यादातर फ़ायदे पाएं, वो भी सिर्फ़ एक कंज़्यूमर GPU पर। यह पूरे ट्रैक में सबसे ज़्यादा प्रैक्टिकल वैल्यू वाला मॉड्यूल है।

1/5
आसान शब्दों में
पूरी टेक्स्टबुक दोबारा लिखने के बजाय, आप मार्जिन में स्टिकी नोट्स चिपकाते हैं। मेहनत बहुत कम, और आप उन्हें बाद में हटा भी सकते हैं।
फुल फ़ाइन-ट्यूनिंग हर वेट को अपडेट करती है, जिसके लिए मेमोरी में मॉडल के साइज़ से लगभग आठ गुना जगह चाहिए होती है। LoRA ओरिजिनल वेट्स को फ़्रीज़ कर देता है और उनके साथ एक छोटा लो-रैंक करेक्शन सीखता है।
Frozen Wd x d, unchanged4096 x 4096 = 16.7M+Ad x rBr x dr = 16 -> 131ktrained0.8% of the weightssame task qualityoutput = Wx + BAx · the frozen path is untouched
यह कैसे काम करता है। फ़ाइन-ट्यून को जो बदलाव करने की ज़रूरत होती है, वह असल में लो-रैंक निकलता है — यानी वह एक छोटे सबस्पेस में रहता है। इसलिए आप एक बड़े और मोटे मैट्रिक्स के बजाय दो पतले मैट्रिसेस से इसे दिखा सकते हैं।
LoRA from scratchpython
class LoRALinear(nn.Module):
    def __init__(self, base: nn.Linear, r=16, alpha=32, dropout=0.05):
        super().__init__()
        self.base = base
        for p in self.base.parameters():
            p.requires_grad = False              # freeze the original

        self.A = nn.Parameter(torch.zeros(r, base.in_features))
        self.B = nn.Parameter(torch.zeros(base.out_features, r))
        nn.init.kaiming_uniform_(self.A, a=math.sqrt(5))
        # B starts at zero, so the adapter is a no-op at step 0
        self.scale = alpha / r
        self.drop = nn.Dropout(dropout)

    def forward(self, x):
        return self.base(x) + self.drop(x) @ self.A.T @ self.B.T * self.scale

    def merge(self):
        """Fold the adapter into the base weight for zero-overhead serving."""
        self.base.weight.data += (self.B @ self.A) * self.scale
        return self.base
यह करें
ध्यान दें कि B को ज़ीरो पर इनिशियलाइज़ किया जाता है। इसका मतलब है कि अडैप्ट किया गया मॉडल बिल्कुल ओरिजिनल जैसा ही शुरू होता है — कोई रैंडम गड़बड़ी नहीं, कोई वॉर्मअप शॉक नहीं। यह एक छोटी सी बारीकी है जो LoRA को बेहद स्थिर बनाती है।

QLoRA: फ़्रीज़ किए गए वेट्स भी छोटे हो जाते हैं

फ़्रीज़ किए गए बेस मॉडल को 4 बिट्स में क्वांटाइज़ करें, LoRA अडैप्टर्स को bfloat16 में रखें, और ट्रेन करें। एक 70B मॉडल एक सिंगल 48 GB कार्ड पर फ़ाइन-ट्यून होने लायक बन जाता है; एक 7B मॉडल आराम से 16 GB वाले कार्ड में फ़िट हो जाता है।
QLoRA in practicepython
from transformers import AutoModelForCausalLM, BitsAndBytesConfig
from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training

bnb = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_quant_type="nf4",              # normal-float 4, best for weights
    bnb_4bit_compute_dtype=torch.bfloat16,
    bnb_4bit_use_double_quant=True,         # quantise the quantisation constants
)

model = AutoModelForCausalLM.from_pretrained(
    "meta-llama/Llama-3.1-8B", quantization_config=bnb, device_map="auto")
model = prepare_model_for_kbit_training(model)

model = get_peft_model(model, LoraConfig(
    r=16, lora_alpha=32, lora_dropout=0.05, bias="none",
    task_type="CAUSAL_LM",
    # adapt attention AND the feed-forward layers -- ignoring the FFN
    # is the single most common reason a LoRA underperforms
    target_modules=["q_proj","k_proj","v_proj","o_proj",
                    "gate_proj","up_proj","down_proj"],
))
model.print_trainable_parameters()    # ~ 42M of 8B = 0.5%

रैंक चुनना

रैंकट्रेनेबल हिस्साकिसके लिए सही है
4–8~0.1%स्टाइल, टोन, आउटपुट फ़ॉर्मैट
16–32~0.5%ज़्यादातर टास्क — यहाँ से शुरू करें
64–128~2%व्यवहार में बड़े बदलाव, नए डोमेन
256+~5%फुल फ़ाइन-ट्यूनिंग के करीब; सोचें कि क्या आपको सच में इसकी ज़रूरत है
सावधान रहें
alpha को लगभग रैंक का दोगुना सेट करें और एक बार में सिर्फ़ एक को बदलें। दोनों को एक साथ ट्यून करना ही वह वजह है जिससे लोग मान बैठते हैं कि LoRA काम नहीं करता।

यह यहाँ का सबसे ज़्यादा काम आने वाला मॉड्यूल क्यों है

  • सस्ता। एक काम का फ़ाइन-ट्यून बस कुछ डॉलर के GPU समय में हो जाता है।
  • पोर्टेबल। एक अडैप्टर कुछ दर्जन मेगाबाइट का होता है। दर्जनों भेजो, रनटाइम पर बदलो, एक ही बेस मॉडल से कई कस्टमर्स को सेवा दो।
  • रिवर्सिबल। पसंद नहीं आया? अडैप्टर हटा दो। बेस मॉडल को कभी छुआ ही नहीं गया था।
  • मर्ज करने लायक। सर्विंग के लिए इसे वेट्स में मिला दो और इन्फ़रेंस पर कोई अतिरिक्त समय या लागत न दो।
  • कंपोज़ेबल। अडैप्टर्स को एक के ऊपर एक रखा या मिलाया जा सकता है, भले ही नतीजे मिले-जुले हों लेकिन उपयोगिता असली है।
ख़तरा
सुरक्षा से जुड़ी ज़रूरी बात जो ट्रैक B की है: एक LoRA अडैप्टर एग्ज़ीक्यूटेबल व्यवहार है, जिसे एक छोटी फ़ाइल के रूप में बांटा जाता है। किसी अजनबी का अडैप्टर डाउनलोड करना डेटा लोड करने से ज़्यादा उनका कोड चलाने जैसा है। यह बैकडोर इंस्टॉल कर सकता है, रिफ़्यूज़ल हटा सकता है, या कोई ट्रिगर फ़्रेज़ जोड़ सकता है। अडैप्टर्स को भी उसी शक की नज़र से देखें जैसे डिपेंडेंसीज़ को — मॉड्यूल 15।

और देखें और पढ़ें

लैब

एक LoRA फ़ाइन-ट्यून जो आपके टास्क पर फुल फ़ाइन-ट्यूनिंग को पछाड़ दे, वो भी सौवें हिस्से की लागत में।

~25 min

समस्या

एक ही मॉडल को दो बार फ़ाइन-ट्यून करें: LoRA r=16 और फुल फ़ाइन-ट्यूनिंग। टास्क क्वालिटी, जनरल-बेंचमार्क रिटेंशन, लगने वाला समय और पीक मेमोरी की तुलना करें। फिर टारगेट मॉड्यूल्स को टेस्ट (ablate) करें — सिर्फ़ अटेंशन बनाम अटेंशन और FFN दोनों।
शुरुआती कोडpython
target_modules=["q_proj","k_proj","v_proj","o_proj",
                "gate_proj","up_proj","down_proj"]   # drop the last three and compare
Google Colab खोलें ↗इस कोड के लिए आपके अपने सेटअप की ज़रूरत है (एक मॉडल, एक GPU या अतिरिक्त पैकेज)। इसे Google Colab में चलाएं: File → Upload notebook।

आपका काम तब पूरा होगा जब

कठिन सवाल

उत्तर देखने से पहले ख़ुद जवाब देने की कोशिश करें। अगर आप इनके जवाब दे सकते हैं, तो आप पाठ समझ गए हैं।

Q1LoRA r=16 आपके टास्क पर फुल फ़ाइन-ट्यूनिंग की बराबरी करता है। एक ऐसा टास्क बताएं जहाँ यह बराबरी न कर पाए, और समझाएं कि क्यों।दिखाएं
व्यवहार को अडैप्ट करने के बजाय सचमुच नया ज्ञान या नई भाषा सिखाना। LoRA अपडेट को सिर्फ़ रैंक-16 सबस्पेस तक सीमित रखता है, जो स्टाइल, फ़ॉर्मैट और टास्क अडैप्टेशन के लिए बहुत है — क्योंकि ये लो-रैंक बदलाव साबित होते हैं — लेकिन नए बड़े रिप्रज़ेंटेशन्स जोड़ने के लिए बहुत संकीर्ण है। पहचान: ट्रेनिंग लॉस उस स्तर से काफ़ी ऊपर रुक जाता है जहाँ फुल फ़ाइन-ट्यूनिंग पहुँचती है, और रैंक बढ़ाने से लगातार मदद मिलती रहती है। अगर रैंक बढ़ाने से फ़ायदा होना बंद हो जाए, तो आपकी सीमा कभी रैंक थी ही नहीं।

जारी रखने के लिए कृपया साइन इन करें।

अक्सर पूछे जाने वाले सवाल

क्या LoRA फुल फ़ाइन-ट्यूनिंग की बराबरी कर पाता है?

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

मुझे किन मॉड्यूल्स को अडैप्ट करना चाहिए?

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

क्या मैं कई अडैप्टर्स को मर्ज कर सकता हूँ?

हाँ, वेटेड एवरेजिंग के ज़रिए, और नतीजे अलग-अलग हो सकते हैं। विरोधी व्यवहारों के लिए ट्रेन किए गए अडैप्टर्स आपस में टकराते हैं। उन्हें अलग-अलग सर्व करना और रूट करना ज़्यादा भरोसेमंद है।

क्या 4 बिट्स में क्वांटाइज़ करने से नुकसान होता है?

NF4 डबल क्वांटाइज़ेशन के साथ थोड़ा-बहुत असर दिखता है, लेकिन एक ऐसे मॉडल को फ़ाइन-ट्यून कर पाने की क्षमता जिसे आप छू भी नहीं सकते थे, आमतौर पर इस नुकसान से कहीं बड़ी होती है। सर्विंग के लिए, फ़ाइनल मॉडल का 8-बिट या 4-बिट क्वांटाइज़ेशन एक आम चलन है।

पाठ का टेस्ट

5 सवाल। पास होने और इस पाठ को पूरा करने के लिए 3 सही होने चाहिए (60%)।

टेस्ट देने और अपनी प्रोग्रेस सेव करने के लिए साइन इन करें