Tai kainuoja milijonus dolerių ir skaičiavimo laiko mėnesius, kad mokytumėte didelį kalbos modelį nuo pat pradžių. Šis tutorialas padės jums Jūs išmoksite keturis pagrindinius smulkinimo metodus, koduosite visą mokymo vamzdį Python ir išmoksite metodus, kurie atskiria gamybos paruoštus modelius nuo brangių eksperimentų. from theory to practice Kas yra LLM Fine-Tuning? "Fine-tuning" treniruoja esamą kalbos modelį ant jūsų duomenų, kad pagerintų Iš anksto apmokyti modeliai yra galingi generalistai, bet atskleidžia juos Galite paversti juos specialistais jūsų naudojimo atveju. performance on specific tasks focused examples Vietoj to, kad sukurtumėte modelį nuo nulio (kuris reikalauja didžiulių skaičiavimų ir duomenų), jau galinčiam modeliui suteikiate nesėkmės kursą tuo, kas jums svarbu, nesvarbu, ar tai yra medicininė diagnozė, klientų palaikymo automatizavimas, nuotaikos analizė, ar bet kokia kita konkreti užduotis. Kaip veikia LLM Fine-Tuning darbas? "Fine-tuning" tęsiasi mokymo procesą iš anksto apmokytais kalbos modeliais, naudojant jūsų konkretų duomenų rinkinį.Modelis apdoroja jūsų pateiktus pavyzdžius, palygina savo rezultatus su laukiamais rezultatais ir Pritaikyti ir sumažinti nuostolius. updates internal weights Šis metodas gali skirtis priklausomai nuo jūsų , ir Kai kuriems projektams reikalingas visiškas patikslinimas, kuriame atnaujinami visi modelio parametrai, o kiti geriau veikia parametrų efektyvumo metodais, pvz., Tai keičia tik nedidelę dalį. goals available data computational resources Lauras LLM Fine-Tuning metodai Fine-Tuning priežiūra SFT moko modelį išmokti teisingų klausimų ir atsakymų porų modelius ir koreguoja modelio svorius, kad tiksliai atitiktų tuos atsakymus. Naudokite tai, kai norite nuoseklių rezultatų, pavyzdžiui, kad modelis visada reaguotų JSON formatu, laikydamasis savo klientų aptarnavimo scenarijaus arba rašydamas el. Laiškus pagal jūsų įmonės toną. (Prompt, Ideal Response) Nepatvirtintas Fine-Tuning Maitina modelio tonas žaliavinio teksto (nėra klausimų ar ženklintų duomenų, reikalingų), kad jis išmoktų tam tikro domeno žodyną ir modelius. Nors tai techniškai yra ikimokyklinis procesas, žinomas kaip tęstinis ikimokyklinis mokymas (CPT), tai paprastai daroma po pradinio ikimokyklinio mokymo etapo. Naudokite tai pirmiausia, kai jūsų modeliui reikia suprasti specializuotą turinį, kuriame jis iš pradžių nebuvo apmokytas, pvz., medicinos terminologiją, teisines sutartis ar naują kalbą. Tiesioginis pirmenybės optimizavimas DPO moko modelį teikti pirmenybę geresniems atsakymams, parodydamas gerų ir blogų atsakymų į tą patį klausimą pavyzdžius ir pritaikydamas jį geresniems. Naudokite DPO po pagrindinio mokymo, kad ištaisytumėte erzinančią elgesį, pavyzdžiui, neleistumėte modeliui sukurti dalykų, būti pernelyg žodžiu arba pateikti nesaugius atsakymus. (Prompt, Good Response, Bad Response) Stiprinimas Fine-Tuning RLHF, jūs pirmiausia mokyti apdovanojimų modelį ant skambučių su kelių atsakymų, reitinguojamų žmonių, mokydami jį prognozuoti, kurie atsakymai žmonės nori. Tada, jūs naudojate stiprinimo mokymosi optimizuoti ir subalansuoti modelį, kuris generuoja atsakymus, kurį apdovanojimų modelis vertina. Tai padeda modelį mokytis laikui bėgant gaminti aukštesnius rezultatus. Šis procesas reikalauja duomenų rinkinius šiame formate: Tai geriausia užduotims, kuriose kokybės vertinimas yra lengvesnis nei tobulų pavyzdžių kūrimas, pvz., Medicinos diagnozės, teisiniai tyrimai ir kiti sudėtingi domeno specifiniai samprotavimai. (Prompt, [Response A, Response B, ...], [Rankings]) Žingsnis po žingsnio Fine-Tuning LLMs pamoka Mes vaikščioti jums per kiekvieną žingsnį subtilinti nedidelį iš anksto apmokytą modelį išspręsti žodžiu pagrįstas matematikos problemas, kažką ji kovoja su iš dėžutės. mes naudosime Qwen 2.5 bazinį modelį su 0.5B parametrus, kurie jau turi natūralių kalbos apdorojimo galimybes. požiūris : mokyti modelio specializuotą terminologiją, gerinti modelio našumą konkrečiose užduotims arba pritaikyti jį prie jūsų domeno. works for virtually any use case of fine-tuning LLMs Išankstinės sąlygos Įdiekite keletą „Python“ paketų, kuriuos naudosime per šį pamoką. naujoje projekto aplinkoje sukurkite ir aktyvuokite „Python“ virtualią aplinką, o tada įdiekite šias bibliotekas naudodami arba jūsų mėgstamiausias paketo tvarkytojas: pip pip install requests datasets transformers 'transformers[torch]' Gauti ir įkelti duomenų rinkinį Tinkimo procesas prasideda nuo duomenų rinkinio pasirinkimo, kuris, ko gero, yra pats svarbiausias sprendimas. . reflect the task you want your model to perform Paprastoms užduotims, pvz., nuotaikos analizei, reikia pagrindinių įvesties ir išvesties porų. Sudėtingoms užduotims, pvz., instrukcijų sekimui ar klausimų atsakymui, reikia turtingesnių duomenų rinkinių su kontekstu, pavyzdžiais ir įvairiais formatais. Lengviausia pradžia yra duomenų rinkinių biblioteka, kurioje yra tūkstančiai atviro kodo duomenų rinkinių skirtingiems domenams ir užduotims. arba viešai prieinami duomenys. Hugging Face Purchase specialized datasets build your own by Scraping Scraping Pavyzdžiui, jei norite sukurti nuotaikų analizės modelį "Amazon" produktų apžvalgoms, galite rinkti duomenis iš realių apžvalgų, naudojant žiniatinklio nuskaitymo įrankį. : Web Scraper API naudojimas import json import requests # Web Scraper API parameters. payload = { "source": "amazon_product", # Query is the ASIN of a product. "query": "B0DZDBWM5B", "parse": True, } # Send a request to the API and get the response. response = requests.post( "https://realtime.oxylabs.io/v1/queries", # Visit https://dashboard.oxylabs.io to claim FREE API tokens. auth=("USERNAME", "PASSWORD"), json=payload, ) print(response.text) # Extract the reviews from the response. reviews = response.json()["results"][0]["content"]["reviews"] print(f"Found {len(reviews)} reviews") # Save the reviews to a JSON file. with open("reviews.json", "w") as f: json.dump(reviews, f, indent=2) For this tutorial, let’s keep it simple without building a custom data collection pipeline. Since we're teaching the base model to solve word-based math problems, we can use the openai/gsm8k dataset. It’s a collection of grade-school math problems with step-by-step solutions. Load it in your Python file: from datasets import load_dataset dataset = load_dataset("openai/gsm8k", "main") print(dataset["train"][0]) Tokenizuoti duomenis apdorojimui Modeliai tiesiogiai nesupranta teksto; jie dirba su Tokenizacija konvertuoja jūsų tekstą į žetonus (numerinius atstovavimus), kuriuos modelis gali apdoroti.Kiekvienas modelis turi savo tokenizatorių, apmokytą šalia jo, todėl naudokite tą, kuris atitinka jūsų bazinį modelį: numbers from transformers import AutoTokenizer tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen2.5-0.5B") tokenizer.pad_token = tokenizer.eos_token Kaip mes tokenizuojame savo duomenų formas, ką modelis išmoksta. Matematinių problemų atveju norime subtilinti modelį, kad sužinotume, kaip Štai triukas: tokenizuokite klausimus ir atsakymus atskirai, tada naudokite maskavimo techniką. Atsakymas Užduoti klausimą token modelis tik mokosi iš atsakymų, todėl mokymas yra labiau orientuotas ir efektyvus. -100 def tokenize_function(examples): input_ids_list = [] labels_list = [] for question, answer in zip(examples["question"], examples["answer"]): # Tokenize question and answer separately question_tokens = tokenizer(question, add_special_tokens=False)["input_ids"] answer_tokens = tokenizer(answer, add_special_tokens=False)["input_ids"] + [tokenizer.eos_token_id] # Combine question + answer for input input_ids = question_tokens + answer_tokens # Mask question tokens with -100 so loss is only computed on the answer labels = [-100] * len(question_tokens) + answer_tokens input_ids_list.append(input_ids) labels_list.append(labels) return { "input_ids": input_ids_list, "labels": labels_list, } Taikykite šią tokenizacijos funkciją tiek mokymo, tiek testavimo duomenų rinkiniams. Mes filtruojame pavyzdžius, ilgesnius nei 512 žetonų, kad atminties naudojimas būtų tvarkomas ir užtikrintume, kad modelis apdorotų visą informaciją be trunkavimo. train_dataset = dataset["train"].map( tokenize_function, batched=True, remove_columns=dataset["train"].column_names, ).filter(lambda x: len(x["input_ids"]) <= 512) .shuffle(seed=42) eval_dataset = dataset["test"].map( tokenize_function, batched=True, remove_columns=dataset["test"].column_names, ).filter(lambda x: len(x["input_ids"]) <= 512) print(f"Samples: {len(dataset['train'])} → {len(train_dataset)} (after filtering)") print(f"Samples: {len(dataset['test'])} → {len(eval_dataset)} (after filtering)") Optional: Norite greitai išbandyti visą vamzdyną, prieš pradėdami vykdyti visą mokymą? Galite mokyti modelį pagal duomenų rinkinį.Taigi, vietoj to, kad naudotumėte visą 8.5K duomenų rinkinį, galite jį sumažinti iki 3K, todėl procesas yra daug greitesnis: train_dataset = train_dataset.select(range(2000)) eval_dataset = eval_dataset.select(range(1000)) Mažesni duomenų rinkiniai padidina perpildymo riziką, kai modelis įsimena mokymo duomenis, o ne bendrus mokymosi modelius. Keep in mind: Pradėkime nuo bazinio modelio Tada įkelkite iš anksto apmokytą bazinį modelį, kad jį subalansuotumėte, tobulindami savo matematikos problemų sprendimo įgūdžius: from transformers import AutoModelForCausalLM model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen2.5-0.5B") model.config.pad_token_id = tokenizer.pad_token_id Fine-Tune naudojant trenerio metodą Štai kur vyksta magija. „TrainingArguments“ kontroliuoja, kaip jūsų modelis mokosi (pagalvokite apie tai kaip apie receptą, kuris lemia jūsų galutinio rezultato kokybę). Šie nustatymai ir hiperparametrai gali padaryti arba nutraukti jūsų subtilų nustatymą, todėl eksperimentuokite su skirtingomis vertėmis, kad surastumėte, kas veikia jūsų naudojimo atveju. Key parameters explained: · Daugiau epochų reiškia daugiau mokymosi galimybių, tačiau per daug sukelia perpildymą. Epochs: · Poveikis atminties naudojimui ir mokymo greičiui. Pritaikykite juos pagal savo aparatūrą. Batch size: · Kontroliuoja, kaip greitai modelis prisitaiko.Per didelis ir jis gali praleisti optimalų sprendimą, per mažas ir mokymas trunka amžinai. Learning rate: · Gali padėti išvengti perpildymo, atgrasant modelį nuo pernelyg didelio nusileidimo bet kuriam vienam modeliui.Jei svorio kritimas yra per didelis, tai gali sukelti nepakankamą įrengimą, neleidžiant modeliui mokytis reikiamų modelių. Weight decay: Žemiau pateikta optimali konfigūracija yra specializuota CPU mokymui (pašalinti use_cpu=True, jei turite GPU): from transformers import TrainingArguments, Trainer, DataCollatorForSeq2Seq training_args = TrainingArguments( output_dir="./qwen-math", # Custom output directory for the fine-tuned model use_cpu=True, # Set to False or remove to use GPU if available # Training duration num_train_epochs=2, # 3 may improve reasoning at the expense of overfitting # Batch size and memory management per_device_train_batch_size=5, # Adjust depending on your PC capacity per_device_eval_batch_size=5, # Adjust depending on your PC capacity gradient_accumulation_steps=4, # Decreases memory usage, adjust if needed # Learning rate and regularization learning_rate=2e-5, # Affects learning speed and overfitting weight_decay=0.01, # Prevents overfitting by penalizing large weights max_grad_norm=1.0, # Prevents exploding gradients warmup_ratio=0.1, # Gradually increases learning rate to stabilize training lr_scheduler_type="cosine", # Smoother decay than linear # Evaluation and checkpointing eval_strategy="steps", eval_steps=100, save_strategy="steps", save_steps=100, save_total_limit=3, # Keep only the best 3 checkpoints load_best_model_at_end=True, # Load the best checkpoint at the end of training metric_for_best_model="eval_loss", greater_is_better=False, # Logging logging_steps=25, logging_first_step=True, ) # Data collator handles padding and batching data_collator = DataCollatorForSeq2Seq(tokenizer=tokenizer, model=model) # Initialize trainer trainer = Trainer( model=model, args=training_args, train_dataset=train_dataset, eval_dataset=eval_dataset, data_collator=data_collator, ) # Fine-tune the base model print("Fine-tuning started...") trainer.train() Once training completes, save your fine-tuned model: trainer.save_model("./qwen-math/final") tokenizer.save_pretrained("./qwen-math/final") 5. įvertinti modelį Po to, kai sumontuosite, išmatuokite, kaip gerai jūsų modelis veikia, naudodamiesi dviem bendrais rodikliais: · Matuoja, kaip toli nuo modelio prognozių yra tikslinės išvestys, kur mažesnės vertės rodo geresnį našumą. Loss: · Rodo tą pačią informaciją intuityvesniu mastu, kur mažesnės vertės reiškia, kad modelis labiau pasitiki savo prognoze. Perplexity (the exponential of loss): Gamybos aplinkos atveju apsvarstykite galimybę pridėti tokias metrikas kaip arba išmatuoti, kaip glaudžiai generuoti atsakymai atitinka nuorodos atsakymus. BLEU ROUGE import math eval_results = trainer.evaluate() print(f"Final Evaluation Loss: {eval_results['eval_loss']:.4f}") print(f"Perplexity: {math.exp(eval_results['eval_loss']):.2f}") Taip pat galite įtraukti kitus rodiklius, pvz., F1, kuris matuoja, kaip gerai jūsų modelis sugeba sugauti tai, kas svarbu, išlaikydamas tikslumą. yra geras pradinis taškas, kad sužinotumėte transformatorių bibliotekos naudojimo esmę. Žvilgsnis į veidą skaityti Fine-tuning kodo pavyzdys Po šių penkių žingsnių turėtumėte sujungti šį kodą į vieną "Python" failą: import math from datasets import load_dataset from transformers import ( AutoTokenizer, AutoModelForCausalLM, TrainingArguments, Trainer, DataCollatorForSeq2Seq, ) dataset = load_dataset("openai/gsm8k", "main") tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen2.5-0.5B") tokenizer.pad_token = tokenizer.eos_token # Tokenization function adjusted for the specific dataset format def tokenize_function(examples): input_ids_list = [] labels_list = [] for question, answer in zip(examples["question"], examples["answer"]): question_tokens = tokenizer(question, add_special_tokens=False)["input_ids"] answer_tokens = tokenizer(answer, add_special_tokens=False)["input_ids"] + [tokenizer.eos_token_id] input_ids = question_tokens + answer_tokens labels = [-100] * len(question_tokens) + answer_tokens input_ids_list.append(input_ids) labels_list.append(labels) return { "input_ids": input_ids_list, "labels": labels_list, } # Tokenize the data train_dataset = dataset["train"].map( tokenize_function, batched=True, remove_columns=dataset["train"].column_names, ).filter(lambda x: len(x["input_ids"]) <= 512) .shuffle(seed=42) eval_dataset = dataset["test"].map( tokenize_function, batched=True, remove_columns=dataset["test"].column_names, ).filter(lambda x: len(x["input_ids"]) <= 512) print(f"Samples: {len(dataset['train'])} → {len(train_dataset)} (after filtering)") print(f"Samples: {len(dataset['test'])} → {len(eval_dataset)} (after filtering)") # Optional: Use a smaller subset for faster testing # train_dataset = train_dataset.select(range(2000)) # eval_dataset = eval_dataset.select(range(1000)) model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen2.5-0.5B") model.config.pad_token_id = tokenizer.pad_token_id # Configuration settings and hyperparameters for fine-tuning training_args = TrainingArguments( output_dir="./qwen-math", use_cpu=True, # Training duration num_train_epochs=2, # Batch size and memory management per_device_train_batch_size=5, per_device_eval_batch_size=5, gradient_accumulation_steps=4, # Learning rate and regularization learning_rate=2e-5, weight_decay=0.01, max_grad_norm=1.0, warmup_ratio=0.1, lr_scheduler_type="cosine", # Evaluation and checkpointing eval_strategy="steps", eval_steps=100, save_strategy="steps", save_steps=100, save_total_limit=3, load_best_model_at_end=True, metric_for_best_model="eval_loss", greater_is_better=False, # Logging logging_steps=25, logging_first_step=True, ) data_collator = DataCollatorForSeq2Seq(tokenizer=tokenizer, model=model) trainer = Trainer( model=model, args=training_args, train_dataset=train_dataset, eval_dataset=eval_dataset, data_collator=data_collator, ) # Fine-tune the base model print("Fine-tuning started...") trainer.train() # Save the final model trainer.save_model("./qwen-math/final") tokenizer.save_pretrained("./qwen-math/final") # Evaluate after fine-tuning eval_results = trainer.evaluate() print(f"Final Evaluation Loss: {eval_results['eval_loss']:.4f}") print(f"Perplexity: {math.exp(eval_results['eval_loss']):.2f}") Prieš paleidžiant, paimkite akimirką, kad pritaikytumėte trenerių konfigūraciją ir hiperparametrus, atsižvelgiant į tai, ką jūsų mašina iš tikrųjų gali valdyti. Norėdami suteikti jums realaus pasaulio nuorodą, čia yra tai, kas mums sklandžiai dirbo „MacBook Air“ su M4 lustu ir 16 GB RAM. · : 7 Batch size for training · 7 Batch size for eval: · 5 Gradient accumulation: Kaip jūsų modelis traukiniai, laikykite akis į Jei jis padidėja, o treniruotės nuostoliai mažėja, modelis yra pernelyg tinkamas. Tokiu atveju, koreguokite epochas, sumažinkite mokymosi greitį, pakeiskite svorio kritimą ir kitus hiperparametrus. Žemiau pateiktame pavyzdyje matome sveikus rezultatus, o eval nuostoliai mažėja nuo dviejų Ir galutinis nesutarimas apie . evaluation loss 0.496 0.469 1.60 Išbandykite Fine-Tuned modelį Dabar tiesos akimirkai – ar mūsų subtilinimas iš tikrųjų buvo sėkmingas? Jūs galite rankiniu būdu išbandyti subtilų modelį, paprašydami jį naudodami šį Python kodą: from transformers import pipeline generator = pipeline( "text-generation", # Use `Qwen/Qwen2.5-0.5B` for testing the base model model="./qwen-math/final" ) output = generator( "James has 5 apples. He buys 3 times as many. Then gives half away. How many does he have?", return_full_text=False ) print(output[0]["generated_text"]) Šiame palyginime galite pamatyti, kaip prieš ir po modeliai reaguoja į tą patį klausimą (teisingas atsakymas yra 10): Su įgalinta mėginių ėmimo, abu modeliai kartais gauti teisingai ar neteisingai dėl atsitiktinumo. funkcija atskleidžia jų tikrą pasitikėjimą: modelis visada pasirenka savo didžiausią tikimybę atsakymą. Pasitikėjimas išėjimu (Kaip ) ir tuo tarpu Pasitikėjimas išėjimu (Kaip Būtent tai ir yra „fine-tuning“ darbe. do_sample=False in the generator() base model -2 neteisingai fine-tuned model 10 Teisingai Fine-Tuning geriausios praktikos pavyzdžiai Modelių atranka · Domeno specifiniai modeliai ir atitinkami kontekstiniai langai išgelbės jus nuo kovos su modelio turimomis žiniomis. Choose the right base model: · Tik kodavimo modeliai (pavyzdžiui, BERT) puikiai tinka klasifikavimo užduotims, tik dekodavimo modeliai (pavyzdžiui, GPT) teksto generavimui ir kodavimo dekodavimo modeliai (pavyzdžiui, T5) transformacijos užduotims, pvz., vertimui ar apibendrinimui. Understand the model architecture: · Jei jūsų bazinis modelis buvo apmokytas naudojant konkrečius skambučių šablonus, naudokite tą patį formatą. Match your model's input format: Duomenų paruošimas · Švarūs ir tikslūs pavyzdžiai kiekvieną kartą įveikia didžiulius ir triukšmingus duomenų rinkinius. Prioritize data quality over quantity: · Niekada neleiskite savo modelio matyti vertinimo duomenų mokymo metu.Tai leidžia jums sugauti perpildymą, kol jis sugadina jūsų modelį. Split training and evaluation samples: · Automatinės metrikos, tokios kaip painiojimas, nesako, ar modelis iš tikrųjų seka instrukcijas, ar tik statistiškai prognozuoja žodžius. Establish a "golden set" for evaluation: Mokymo strategija · Jūs atliekate nedidelius koregavimus, ne mokydami jį nuo nulio, todėl agresyvūs tarifai gali ištrinti tai, ką jis išmoko prieš treniruotę. Start with a lower learning rate: · Treniruokite tik 1% parametrų, kad gautumėte 90% + našumą, naudojant mažiau atminties ir laiko. Use parameter-efficient fine-tuning (LoRA/PEFT): · Išskyrus visus taškus ( ir tt) atneša modelius, kurie pagrįsta žymiai geriau, o ne tik imituoti stilių. Target all linear layers in LoRA: q_proj, k_proj, v_proj, o_proj, · Atsitiktinis triukšmas įterpimuose veikia kaip reguliarizacija, kuri gali užkirsti kelią įsiminimui ir padidinti pokalbio kokybę 35 procentiniais punktais. Use NEFTune ( ): Triukšmingas įterpimas Fine-tuning Triukšmingas įterpimas Fine-tuning · SFT moko, kaip kalbėti; DPO moko, kas yra gera, mokydamasis iš pageidaujamų porų. After SFT, Run DPO: Kokie yra LLM Fine-Tuning apribojimai? · Fine-tuning perrašinėja esamus neuroninius modelius, kurie gali ištrinti vertingas bendrąsias žinias, kurias modelis išmoko ikimokyklinio mokymo metu.Daugelio užduočių mokymasis, kuriame jūs mokysite savo specializuotą užduotį kartu su bendrais pavyzdžiais, gali padėti išsaugoti platesnes galimybes. Catastrophic forgetting: · Modelis gali įsiminti jūsų mokymo pavyzdžius, o ne mokymosi modelius, todėl jis nepavyksta šiek tiek skirtinguose įvedimuose. Overfitting on small datasets: · Milijardų parametrų patikslinimas reikalauja brangių GPU, didelės atminties ir valandų iki dienų ar savaičių mokymo laiko. High computational cost: · Iš anksto apmokyti modeliai jau turi savo mokymo duomenų prietarų, o subtilus nustatymas gali sustiprinti šiuos prietarus, jei jūsų duomenų rinkinys nėra kruopščiai kuruojamas. Bias amplification: · Dėl naujų ir išorinių žinių gali prireikti iš naujo apmokyti visą modelį arba įgyvendinti „Retrieval-Augmented Generation“ (RAG), o pakartotinis smulkinimas dažnai pablogina našumą. Manual knowledge update: Išvada Suderinkite jį su greitąja inžinerija, kad gautumėte geriausius rezultatus, kai subtilusis pritaikymas tvarko užduočių specializaciją, o greitasis inžinerija vadovauja modelio elgesiui išvados metu. Toliau paimkite modelį iš „Hugging Face“, kuris tinka jūsų naudojimo atvejui domeno specifinio smulkinimo tikslais, nuskaitykite arba sukurkite kokybišką duomenų rinkinį savo užduočiai, ir paleiskite savo pirmąją smulkinimo sesiją mažame pogrupyje. Kai pamatysite perspektyvius rezultatus, išplėskite ir eksperimentuokite su LoRA, DPO ar NEFTune, kad išspaustumėte geresnį našumą.