Fine-tuning: tayyor modelni moslashtirish
Sahna: 499 ta o'zbek xabari
Siz ijara agentligida ishlaysiz. Mijozlar Telegram orqali xabar yozadi, kuniga yuzlab. Ularni qo'lda tartiblash kimningdir to'liq ish kuni.
Vazifa: har xabarning maqsadini aniqlash. To'rt turi bor: narx so'rash, ko'rishga yozilish, shikoyat, bekor qilish.
Bu — matn klassifikatsiyasi. 35-bobda transformer qanday ishlashini ko'rdik. Endi savol boshqa: tayyor modelni o'z ma'lumotimizga qanday moslashtiramiz?
import os os.environ["HF_HUB_OFFLINE"] = "1" os.environ["TRANSFORMERS_OFFLINE"] = "1" os.environ["CUDA_VISIBLE_DEVICES"] = "-1" os.environ["TOKENIZERS_PARALLELISM"] = "false" import time import numpy as np import pandas as pd xabarlar = pd.read_csv(DATA / "mijoz_xabarlari.csv") print(f"Xabarlar: {len(xabarlar)}") print() print(xabarlar["maqsad"].value_counts().to_string()) print() print("Namunalar:") for _, q in xabarlar.head(6).iterrows(): belgi = "QIYIN" if q["qiyin"] else "oson" print(f" [{q['maqsad']:<8}] [{belgi:<5}] {q['xabar']}")
Xabarlar: 499 maqsad shikoyat 141 korish 137 bekor 113 narx 108 Namunalar: [narx ] [QIYIN] indinga ko'rishdan oldin to'lov shartlarini bilsam [korish ] [QIYIN] Narx muhim emas, indinga ko'rishga chiqaman [shikoyat] [oson ] Kalit berilmadi, besh kun kutdim [korish ] [oson ] Salom. Shu hafta soat 18:00 da ko'rishga kelsam bo'ladi? [bekor ] [QIYIN] Depozit qaytmasa ham bekor qilaman [bekor ] [oson ] Endi kerak emas, rahmat
Bu dataset sun'iy — va `qiyin` ustuni ataylab qo'yilgan
datasets/xabarlar_qur.py bu faylni qat'iy seed bilan yasaydi. Haqiqiy mijoz xabarlari emas — shaxsiy ma'lumot ishlatmaslik uchun.
qiyin ustuni muhim. qiyin=1 bo'lgan xabarlarda yuzaki kalit so'z boshqa sinfga ishora qiladi:
- "Narx juda baland, bu aldov" — ichida "narx" bor, lekin bu shikoyat
- "Konditsioner buzuq ekan, shuning uchun bekor qilaman" — ichida buzuq jihoz bor, lekin bu bekor
- "Bekor qilsam depozit qaytadimi?" — ichida "bekor" bor, lekin bu narx savoli
Nega shunday qildim: kalit so'zga qarab ishlaydigan model shu yerda yiqilishi kerak. Transformer esa kontekstni ko'radi. Taxmin shu edi — pastda o'lchaymiz.
Bu bob uchun BIR MARTALIK yuklab olish kerak
Bu bobdagi kod tayyor modellardan foydalanadi. Ular kompyuteringizda bo'lmasa, kod
OSError: We couldn't connect to huggingface.co xatosini beradi — chunki kod
qasddan oflayn rejimda ishlaydi (takrorlanadigan natija uchun).
Shuning uchun bobni boshlashdan oldin bir marta quyidagini bajaring (internet kerak):
# yuklab_ol.py — bir marta ishga tushiriladi, ~600 MB from transformers import AutoTokenizer, AutoModelForSequenceClassification for nom in ["distilbert-base-multilingual-cased", "distilroberta-base"]: AutoTokenizer.from_pretrained(nom) AutoModelForSequenceClassification.from_pretrained(nom, num_labels=4) print(nom, "tayyor")
Kerakli kutubxonalar:
pip install transformers peft torch
Yuklab olingandan keyin model kompyuteringizda keshda qoladi va internet boshqa kerak bo'lmaydi.
Internetingiz yoki joyingiz bo'lmasa: bu bobni o'qib chiqing, kod ishga tushirmasdan. Bobning asosiy xulosasi (baza avval o'lchanadi, TF-IDF bu vazifada yutdi) kod ishga tushirmasdan ham tushunarli, va u faqat sklearn talab qiladi.
Birinchi qadam: baza (har doim)
6-bobdagi qoida bu yerda ham o'zgarmaydi. Transformer yuklashdan oldin oddiy model nima ko'rsatishini bilishimiz kerak.
from sklearn.dummy import DummyClassifier from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.linear_model import LogisticRegression from sklearn.pipeline import make_pipeline from sklearn.model_selection import train_test_split sinflar = sorted(xabarlar["maqsad"].unique()) sinf_raqami = {s: i for i, s in enumerate(sinflar)} y = xabarlar["maqsad"].map(sinf_raqami).values X = xabarlar["xabar"].values tr, te = train_test_split(np.arange(len(xabarlar)), test_size=0.25, random_state=42, stratify=y) print(f"train {len(tr)}, test {len(te)}, {len(sinflar)} sinf: {sinflar}") print() baza = DummyClassifier(strategy="most_frequent").fit(X[tr], y[tr]) tfidf = make_pipeline(TfidfVectorizer(ngram_range=(1, 2), min_df=1), LogisticRegression(max_iter=2000)).fit(X[tr], y[tr]) t0 = time.perf_counter() tfidf_vaqt = time.perf_counter() - t0 print(f"Baza (eng ko'p sinf) : {baza.score(X[te], y[te]):.4f}") print(f"TF-IDF + LogReg : {tfidf.score(X[te], y[te]):.4f}")
train 374, test 125, 4 sinf: ['bekor', 'korish', 'narx', 'shikoyat'] Baza (eng ko'p sinf) : 0.2880 TF-IDF + LogReg : 0.9920
qiyin_maska = xabarlar["qiyin"].values[te].astype(bool) print("TF-IDF ni qismlarga bo'lib tekshiramiz:") print(f" OSON misollarda : {tfidf.score(X[te][~qiyin_maska], y[te][~qiyin_maska]):.4f} ({(~qiyin_maska).sum()} misol)") print(f" QIYIN misollarda: {tfidf.score(X[te][qiyin_maska], y[te][qiyin_maska]):.4f} ({qiyin_maska.sum()} misol)") print() print("Mening taxminim: TF-IDF qiyin misollarda yiqiladi.") print("O'lchov: yiqilmadi.")
TF-IDF ni qismlarga bo'lib tekshiramiz: OSON misollarda : 1.0000 (94 misol) QIYIN misollarda: 0.9677 (31 misol) Mening taxminim: TF-IDF qiyin misollarda yiqiladi. O'lchov: yiqilmadi.
Men bu bobni "transformer kerak" degan taxmin bilan boshlagandim
Yuqoridagi raqamlarga qarang. TF-IDF + logistic regression deyarli hamma xabarni to'g'ri tasnifladi — qiyin deb ataylab yasagan misollarda ham.
Nega: xabarlar_qur.py shablonlardan foydalanadi. Har shablon — o'ziga xos so'z birikmasi. Men "narx" so'zini shikoyat sinfiga qo'ydim, lekin jumlaning qolgan qismi ("bu aldov", "aldadingiz") baribir shikoyatga xos. Model shuni topdi.
Bu — sun'iy ma'lumotning chegarasi, va uni yashirmaslik kerak. Shablondan yasalgan har qanday matn dataseti bag-of-words model uchun oson bo'ladi.
Shuning uchun bu bobdagi fine-tuning — mashq, g'alaba emas. Siz API ni o'rganasiz, chunki ish joyida u kerak bo'ladi. Lekin shu vazifada transformer ishlatish — resurs isrofi, va buni o'lchab ko'rsatamiz.
Haqiqiy loyihada tartib shu: baza o'lchanadi, keyin agar baza yetarli bo'lmasa, transformer ko'riladi. Teskari tartib — eng ko'p uchraydigan va eng qimmat xato.
Fine-tuning nima (va nima emas)
show(pd.DataFrame([ {"Yondashuv": "Noldan o'qitish", "Ma'lumot": "millionlab", "Narxi": "minglab GPU-soat", "Qachon": "Deyarli hech qachon — sizning vazifangiz emas"}, {"Yondashuv": "Fine-tuning (to'liq)", "Ma'lumot": "minglab", "Narxi": "soatlar", "Qachon": "Ko'p ma'lumot bor, vazifa pretraining dan uzoq"}, {"Yondashuv": "LoRA / QLoRA", "Ma'lumot": "yuzlab-minglab", "Narxi": "daqiqalar", "Qachon": "Odatiy tanlov — arzon va deyarli shunday yaxshi"}, {"Yondashuv": "Faqat bosh qatlam", "Ma'lumot": "yuzlab", "Narxi": "daqiqalar", "Qachon": "Juda kam ma'lumot"}, {"Yondashuv": "Prompt / RAG", "Ma'lumot": "0", "Narxi": "yo'q", "Qachon": "Bilim kerak, uslub emas — o'qitish shart emas"}, ]))
| Yondashuv | Ma'lumot | Narxi | Qachon |
|---|---|---|---|
| Noldan o'qitish | millionlab | minglab GPU-soat | Deyarli hech qachon — sizning vazifangiz emas |
| Fine-tuning (to'liq) | minglab | soatlar | Ko'p ma'lumot bor, vazifa pretraining dan uzoq |
| LoRA / QLoRA | yuzlab-minglab | daqiqalar | Odatiy tanlov — arzon va deyarli shunday yaxshi |
| Faqat bosh qatlam | yuzlab | daqiqalar | Juda kam ma'lumot |
| Prompt / RAG | 0 | yo'q | Bilim kerak, uslub emas — o'qitish shart emas |
Tokenizatsiya: model o'zbek tilini ko'radimi?
Fine-tuning dan oldin tekshirish kerak: tanlagan model o'zbek matnini qanday bo'laklarga ajratadi?
from transformers import AutoTokenizer namunalar = ["Bugun to'lasam narx o'zgaradimi?", "Konditsioner buzilgan, tuzatib bering", "Bronni bekor qilmoqchiman"] tok_jadval = [] for nom in ["distilroberta-base", "distilbert-base-multilingual-cased"]: tok = AutoTokenizer.from_pretrained(nom) tokenlar = [len(tok.tokenize(s)) for s in namunalar] belgilar = [len(s) for s in namunalar] tok_jadval.append({"model": nom, "lug'at hajmi": f"{tok.vocab_size:,}", "tokenlar": str(tokenlar), "token/belgi": round(sum(tokenlar) / sum(belgilar), 3)}) show(pd.DataFrame(tok_jadval)) for nom in ["distilroberta-base", "distilbert-base-multilingual-cased"]: tok = AutoTokenizer.from_pretrained(nom) print(f"{nom}:") print(f" {tok.tokenize(namunalar[0])}")
distilroberta-base: ['Bug', 'un', 'Ġto', "'", 'las', 'am', 'Ġnar', 'x', 'Ġo', "'", 'z', 'gar', 'ad', 'imi', '?'] distilbert-base-multilingual-cased: ['Bug', '##un', 'to', "'", 'las', '##am', 'nar', '##x', 'o', "'", 'z', '##gara', '##dim', '##i', '?']
| model | lug'at hajmi | tokenlar | token/belgi |
|---|---|---|---|
| distilroberta-base | 50,265 | [15, 16, 11] | 0.447 |
| distilbert-base-multilingual-cased | 119,547 | [15, 12, 9] | 0.383 |
Ikki model ham o'zbek so'zlarini maydalab tashlaydi
"Bugun" bitta so'z. Ikki model ham uni ikki bo'lakka ajratdi. "o'zgaradimi" esa bir necha bo'lakka.
Bu nima degani: model o'zbek morfologiyasini bilmaydi. U harflar ketma-ketligini ko'radi, so'z o'zagini emas.
token/belgi ustuni shuni o'lchaydi — raqam kichik bo'lsa, model matnni kamroq bo'lakka bo'ladi, ya'ni tilni yaxshiroq "biladi". Ko'p tilli model bu ko'rsatkichda yaxshiroq, lekin ikkisi ham mukammal emas.
Amaliy natijalar:
- Ko'p tilli modelni tanlang (
multilingualso'zi nomida bo'lsin). Ingliz tiliga o'qitilgan model o'zbek matnida zaifroq. - Maydalanish tufayli bir xil matn ko'proq token oladi — kontekst chegarasi tezroq to'ladi va LLM da narx oshadi.
- Agar loyihangiz butunlay o'zbek tilida bo'lsa, o'zbek korpusida pretraining qilingan model (yoki o'zingiz davom ettirgan pretraining) sezilarli farq beradi.
To'liq fine-tuning va LoRA
Endi ikki usulni bir xil sharoitda o'lchaymiz.
shu faylni yaratingmoslashtirish/oqit.py
"""Matn klassifikatsiyasi uchun fine-tuning: to'liq va LoRA.""" import time import numpy as np import torch import torch.nn as nn from torch.utils.data import DataLoader, TensorDataset from transformers import AutoModelForSequenceClassification, AutoTokenizer MODEL = "distilbert-base-multilingual-cased" MAKS_UZUNLIK = 48 def tayyorla(matnlar, model_nomi=MODEL, maks=MAKS_UZUNLIK): tok = AutoTokenizer.from_pretrained(model_nomi) return tok(list(matnlar), truncation=True, max_length=maks, padding="max_length", return_tensors="pt") def oqit(enc, y, train_idx, test_idx, n_sinf, lora=False, epoxalar=3, lr=None, seed=0, model_nomi=MODEL): """Modelni o'qitadi va (aniqlik, o'qitiladigan, jami, vaqt, model) qaytaradi. lora=True bo'lsa, asosiy vaznlar MUZLATILADI va faqat kichik adapter matritsalari o'qitiladi. """ torch.manual_seed(seed) model = AutoModelForSequenceClassification.from_pretrained(model_nomi, num_labels=n_sinf) if lora: from peft import LoraConfig, get_peft_model model = get_peft_model(model, LoraConfig( task_type="SEQ_CLS", r=8, lora_alpha=16, lora_dropout=0.05, target_modules=["q_lin", "v_lin"])) # faqat attention Q va V oqitiladigan = sum(p.numel() for p in model.parameters() if p.requires_grad) jami = sum(p.numel() for p in model.parameters()) def bolak(idx): return TensorDataset(enc["input_ids"][idx], enc["attention_mask"][idx], torch.tensor(y[idx])) opt = torch.optim.AdamW([p for p in model.parameters() if p.requires_grad], lr=lr or (5e-4 if lora else 3e-5)) yuklovchi = DataLoader(bolak(train_idx), batch_size=16, shuffle=True, generator=torch.Generator().manual_seed(seed)) t0 = time.perf_counter() model.train() for _ in range(epoxalar): for ids, maska, nishon in yuklovchi: opt.zero_grad() model(input_ids=ids, attention_mask=maska, labels=nishon).loss.backward() opt.step() vaqt = time.perf_counter() - t0 model.eval() togri = 0 with torch.no_grad(): for ids, maska, nishon in DataLoader(bolak(test_idx), batch_size=32): bashorat = model(input_ids=ids, attention_mask=maska).logits.argmax(-1) togri += int((bashorat == nishon).sum()) return togri / len(test_idx), oqitiladigan, jami, vaqt, model
LoRA g'oyasi: katta matritsani ikki kichigi bilan tuzatish
To'liq fine-tuning da har vazn W o'zgaradi. LoRA da W muzlatiladi, va uning yoniga kichik tuzatma qo'shiladi:
W_yangi = W + B @ A
Bunda A va B juda "yupqa" matritsalar (r=8 — ichki o'lcham). Faqat ular o'qitiladi.
Nega ishlaydi: fine-tuning paytida vaznlarga kerakli o'zgarish odatda past rangli (low-rank) bo'ladi — ya'ni uni kichik matritsalar ko'paytmasi bilan ifodalash mumkin. LoRA nomi shundan: Low-Rank Adaptation.
Amaliy natijasi — pastdagi jadvalda.
import sys sys.path.insert(0, str(ISH)) from moslashtirish.oqit import tayyorla, oqit enc = tayyorla(X) print(f"Tokenizatsiya tayyor: {tuple(enc['input_ids'].shape)}") print() natijalar = [] modellar = {} for nom, lora in [("to'liq fine-tuning", False), ("LoRA (r=8)", True)]: aniqlik, oqitiladigan, jami, vaqt, model = oqit(enc, y, tr, te, len(sinflar), lora=lora) modellar[nom] = model natijalar.append({"usul": nom, "aniqlik": round(aniqlik, 4), "o'qitiladigan": oqitiladigan, "jami parametr": jami, "ulushi": f"{oqitiladigan / jami:.2%}", "vaqt (s)": round(vaqt, 1)}) show(pd.DataFrame(natijalar))
Tokenizatsiya tayyor: (499, 48)
| usul | aniqlik | o'qitiladigan | jami parametr | ulushi | vaqt (s) |
|---|---|---|---|---|---|
| to'liq fine-tuning | 0.96 | 135 327 748 | 135 327 748 | 100.00% | 45 |
| LoRA (r=8) | 0.904 | 741 124 | 136 068 872 | 0.54% | 21.3 |
import shutil from pathlib import Path print(f"{'usul':<22} {'diskda':>12}") print("-" * 36) for nom, model in modellar.items(): papka = ISH / ("saqlangan_" + ("lora" if "LoRA" in nom else "toliq")) shutil.rmtree(papka, ignore_errors=True) model.save_pretrained(papka) hajm = sum(p.stat().st_size for p in Path(papka).rglob("*") if p.is_file()) print(f"{nom:<22} {hajm / 1e6:>9.2f} MB") print() print("LoRA da faqat adapter saqlanadi — asosiy model o'zgarmagan, qayta saqlash shart emas.")
usul diskda ------------------------------------ to'liq fine-tuning 541.32 MB LoRA (r=8) 2.97 MB LoRA da faqat adapter saqlanadi — asosiy model o'zgarmagan, qayta saqlash shart emas.
Uchta usulni yonma-yon qo'yamiz
KALIT = "o'qitiladigan" taqqoslash = pd.DataFrame([ {"usul": "baza (eng ko'p sinf)", "aniqlik": round(baza.score(X[te], y[te]), 4), "o'qitilgan parametr": "0", "izoh": "hech narsa o'rganmaydi"}, {"usul": "TF-IDF + LogReg", "aniqlik": round(tfidf.score(X[te], y[te]), 4), "o'qitilgan parametr": "minglab", "izoh": "bir soniyada o'qitiladi"}, {"usul": natijalar[0]["usul"], "aniqlik": natijalar[0]["aniqlik"], "o'qitilgan parametr": f"{natijalar[0][KALIT]:,}", "izoh": "hamma vazn o'zgaradi"}, {"usul": natijalar[1]["usul"], "aniqlik": natijalar[1]["aniqlik"], "o'qitilgan parametr": f"{natijalar[1][KALIT]:,}", "izoh": "adapter — bir necha MB"}, ]) show(taqqoslash)
| usul | aniqlik | o'qitilgan parametr | izoh |
|---|---|---|---|
| baza (eng ko'p sinf) | 0.288 | 0 | hech narsa o'rganmaydi |
| TF-IDF + LogReg | 0.992 | minglab | bir soniyada o'qitiladi |
| to'liq fine-tuning | 0.96 | 135,327,748 | hamma vazn o'zgaradi |
| LoRA (r=8) | 0.904 | 741,124 | adapter — bir necha MB |
Xulosa ikkita, va ikkisi ham o'lchangan.
Birinchi: shu vazifada TF-IDF ikkala transformerdan ham yuqori natija berdi. Minglab marta kam resurs bilan.
Ikkinchi: LoRA to'liq fine-tuning dan bir oz pastroq aniqlik berdi, lekin parametrlarning juda kichik ulushini o'qitdi, tezroq tugatdi va diskda bir necha MB joy oldi.
LoRA ning afzalligi aniqlikda emas
Jadvalga qarang: LoRA aniqlikda to'liq fine-tuning dan yutmadi. Adabiyotda ko'pincha "LoRA deyarli shunday yaxshi" deb yoziladi va bu to'g'ri — lekin "deyarli" so'zi muhim.
LoRA ning haqiqiy afzalliklari boshqa joyda:
- Xotira. Faqat kichik adapter uchun gradient va optimizer holati saqlanadi. Shu tufayli katta modelni kichik GPU da moslashtirish mumkin bo'ladi — QLoRA (4-bit kvantizatsiya + LoRA) shu g'oyaning davomi.
- Saqlash. Yuqoridagi o'lchovga qarang: adapter to'liq modelga nisbatan juda kichik. 50 ta mijoz uchun 50 ta maxsus model kerak bo'lsa, siz 50 ta adapter saqlaysiz, 50 ta to'liq model emas.
- Almashtirish. Bitta asosiy model xotirada turadi, adapterlar ish vaqtida ulanadi va uziladi.
- Tezlik. O'lchangan vaqt ustuni — kamroq parametr uchun kamroq hisob.
Agar sizda bitta vazifa va cheksiz resurs bo'lsa, to'liq fine-tuning bir oz yaxshiroq bo'lishi mumkin. Amalda esa resurs cheksiz emas, va vazifalar bitta emas.
Fine-tuning tuzoqlari
show(pd.DataFrame([ {"Tuzoq": "lr juda katta", "Belgisi": "loss NaN yoki aniqlik tasodifiy darajada", "Yechim": "to'liq FT uchun 2e-5..5e-5; LoRA uchun 1e-4..1e-3"}, {"Tuzoq": "Katastrofik unutish", "Belgisi": "model yangi vazifada yaxshi, boshqa hammasida yomon", "Yechim": "kamroq epoxa, kichik lr, yoki LoRA ishlatish"}, {"Tuzoq": "Kam ma'lumotda ko'p epoxa", "Belgisi": "train aniqlik 1.0, test pastda qoladi", "Yechim": "early stopping, validation kuzatiladi"}, {"Tuzoq": "Test da sozlash", "Belgisi": "qog'ozda yaxshi, amalda yomon", "Yechim": "validation da sozlanadi — 5 va 23-bob"}, {"Tuzoq": "Nomutanosib sinflar", "Belgisi": "kichik sinf umuman topilmaydi", "Yechim": "class weight yoki F1 metrikasi — 7 va 8-bob"}, {"Tuzoq": "Tasodifiy seed", "Belgisi": "har ishga tushirishda boshqa natija", "Yechim": "3 seed, eng yomonini ham yozish — 34-bob"}, ]))
| Tuzoq | Belgisi | Yechim |
|---|---|---|
| lr juda katta | loss NaN yoki aniqlik tasodifiy darajada | to'liq FT uchun 2e-5..5e-5; LoRA uchun 1e-4..1e-3 |
| Katastrofik unutish | model yangi vazifada yaxshi, boshqa hammasida yomon | kamroq epoxa, kichik lr, yoki LoRA ishlatish |
| Kam ma'lumotda ko'p epoxa | train aniqlik 1.0, test pastda qoladi | early stopping, validation kuzatiladi |
| Test da sozlash | qog'ozda yaxshi, amalda yomon | validation da sozlanadi — 5 va 23-bob |
| Nomutanosib sinflar | kichik sinf umuman topilmaydi | class weight yoki F1 metrikasi — 7 va 8-bob |
| Tasodifiy seed | har ishga tushirishda boshqa natija | 3 seed, eng yomonini ham yozish — 34-bob |
Bu bobda bitta seed ishlatildi — va buni aytib qo'yish kerak
34-bobda o'lchab ko'rsatgandik: neyron tarmoq natijasi seedga sezilarli bog'liq.
Bu bobdagi fine-tuning raqamlari bitta seed bilan olingan, chunki har qo'shimcha seed kitob qurilishiga daqiqalar qo'shadi. Shuning uchun ulardan "LoRA aynan shu farq bilan pastroq" degan aniq xulosa chiqarib bo'lmaydi — faqat "taqqoslanadigan darajada" deyish mumkin.
Siz o'z loyihangizda kamida 3 seed ishlatasiz. Kitobdagi cheklov — qurilish vaqti, ilmiy asos emas, va shuni yashirish noto'g'ri bo'lardi.
Qachon fine-tuning QILMASLIK kerak
show(pd.DataFrame([ {"Holat": "Kalit so'zlar sinfni aniqlaydi", "To'g'ri yechim": "TF-IDF + logistic regression", "Sabab": "shu bobda o'lchandi — arzonroq va yuqoriroq"}, {"Holat": "Bilim kerak, uslub emas", "To'g'ri yechim": "RAG (qidirish + LLM)", "Sabab": "yangi fakt qo'shish uchun o'qitish shart emas"}, {"Holat": "Ma'lumot 100 dan kam", "To'g'ri yechim": "prompt yoki few-shot", "Sabab": "fine-tuning shovqinga moslashadi"}, {"Holat": "Talab tez-tez o'zgaradi", "To'g'ri yechim": "prompt", "Sabab": "har o'zgarishda qayta o'qitish qimmat"}, {"Holat": "Chiqish formati kerak", "To'g'ri yechim": "fine-tuning YOKI struktura majburlash", "Sabab": "uslub va format — fine-tuning kuchli tomoni"}, {"Holat": "Maxsus domen tili", "To'g'ri yechim": "fine-tuning", "Sabab": "tibbiy, huquqiy matn — pretraining dan uzoq"}, ]))
| Holat | To'g'ri yechim | Sabab |
|---|---|---|
| Kalit so'zlar sinfni aniqlaydi | TF-IDF + logistic regression | shu bobda o'lchandi — arzonroq va yuqoriroq |
| Bilim kerak, uslub emas | RAG (qidirish + LLM) | yangi fakt qo'shish uchun o'qitish shart emas |
| Ma'lumot 100 dan kam | prompt yoki few-shot | fine-tuning shovqinga moslashadi |
| Talab tez-tez o'zgaradi | prompt | har o'zgarishda qayta o'qitish qimmat |
| Chiqish formati kerak | fine-tuning YOKI struktura majburlash | uslub va format — fine-tuning kuchli tomoni |
| Maxsus domen tili | fine-tuning | tibbiy, huquqiy matn — pretraining dan uzoq |
Protokolga ulanish
show(pd.DataFrame([ {"Qadam": "36. Ma'lumot yig'ildi", "Holati": "bajarildi"}, {"Qadam": "37. Dataset qurildi", "Holati": "bajarildi — guruh bo'yicha split"}, {"Qadam": "38. Baza o'lchandi", "Holati": "TF-IDF yetarli ekani ANIQLANDI"}, {"Qadam": "38. Fine-tuning o'rganildi", "Holati": "to'liq va LoRA — mexanizm ma'lum"}, {"Qadam": "39. Modelni saqlash", "Holati": "keyingi bob"}, {"Qadam": "40. Xizmatga chiqarish", "Holati": "Django API"}, ]))
| Qadam | Holati |
|---|---|
| 36. Ma'lumot yig'ildi | bajarildi |
| 37. Dataset qurildi | bajarildi — guruh bo'yicha split |
| 38. Baza o'lchandi | TF-IDF yetarli ekani ANIQLANDI |
| 38. Fine-tuning o'rganildi | to'liq va LoRA — mexanizm ma'lum |
| 39. Modelni saqlash | keyingi bob |
| 40. Xizmatga chiqarish | Django API |
Bugun nima o'rgandik
show(pd.DataFrame([ {"Tushuncha": "Baza avval", "Bitta jumla": "O'lchandi: TF-IDF transformerdan yuqori chiqdi"}, {"Tushuncha": "Fine-tuning", "Bitta jumla": "Tayyor vaznlardan boshlab o'z ma'lumotida davom etish"}, {"Tushuncha": "LoRA", "Bitta jumla": "Asosiy vazn muzlatiladi, kichik adapter o'qitiladi"}, {"Tushuncha": "LoRA afzalligi", "Bitta jumla": "Xotira, saqlash, almashtirish — aniqlik emas"}, {"Tushuncha": "Tokenizatsiya", "Bitta jumla": "O'lchandi: ikki model ham o'zbek so'zini maydalaydi"}, {"Tushuncha": "Ko'p tilli model", "Bitta jumla": "O'zbek matni uchun ingliz modelidan afzal"}, {"Tushuncha": "Katastrofik unutish", "Bitta jumla": "Ko'p epoxa eski bilimni buzadi"}, {"Tushuncha": "Qachon qilmaslik", "Bitta jumla": "Kalit so'z yetarli bo'lsa, RAG yoki prompt bo'lsa"}, ]))
| Tushuncha | Bitta jumla |
|---|---|
| Baza avval | O'lchandi: TF-IDF transformerdan yuqori chiqdi |
| Fine-tuning | Tayyor vaznlardan boshlab o'z ma'lumotida davom etish |
| LoRA | Asosiy vazn muzlatiladi, kichik adapter o'qitiladi |
| LoRA afzalligi | Xotira, saqlash, almashtirish — aniqlik emas |
| Tokenizatsiya | O'lchandi: ikki model ham o'zbek so'zini maydalaydi |
| Ko'p tilli model | O'zbek matni uchun ingliz modelidan afzal |
| Katastrofik unutish | Ko'p epoxa eski bilimni buzadi |
| Qachon qilmaslik | Kalit so'z yetarli bo'lsa, RAG yoki prompt bo'lsa |
Keyingi bobda modelni saqlaymiz va qaytarib yuklaymiz — va bu yerda eng ko'p uchraydigan xatolarni o'lchaymiz.
Bu bobni bepul o'qidingiz.
Kitob o'rgatadi, lekin sizning kodingiz nega ishlamaganini ayta olmaydi. Kursda uy vazifangiz tekshiriladi.