Mundarija (22)
- 1. Kirish va motivatsiya
- 2. Nazariya — chuqur tushuntirish
- 2.1. dtype va xotira
- 2.2. Siyraklikni saqlash
- 2.3. n_jobs va ichma-ich parallellik
- 2.4. Model va hajm
- 2.5. partial_fit
- 2.6. Qayerni optimallashtirish
- 2.7. Tuzoqlar
- 2.8. Uch arzon yutuq
- 3. Tez ma'lumotnoma
- 4. Batafsil misollar
- Misol 1 — dtype va xotira
- Misol 2 — Siyraklikni saqlash
- Misol 3 — Model tanlash va hajm
- Misol 4 — partial_fit bilan bo'laklab o'rgatish
- 5. To'g'ri va noto'g'ri tushunishlar
- 6. Keng tarqalgan xatolar va yechimlari
- 7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 8. Eng yaxshi amaliyotlar
- 9. Amaliy topshiriq
- Xulosa
19.9-dars: Tezlik va xotira
19-QISM — SCIKIT-LEARN TO'LIQ · 9-dars
1. Kirish va motivatsiya
Ma'lumot o'sgani sari "ishlaydi" degan javob yetarli bo'lmay qoladi: o'rgatish tunda tugamaydi, xotira tugaydi, bashorat so'roviga javob kech keladi.
Yaxshi xabar shuki, sklearn da tezlik va xotira muammolarining katta qismi algoritmni almashtirmasdan hal qilinadi: to'g'ri dtype (float64 o'rniga float32 — ikki barobar kam xotira), siyrak matritsalar, n_jobs ni to'g'ri qo'yish, qaysi model qaysi hajmga mos ekanini bilish va partial_fit bilan bo'laklab o'rgatish.
Yomon xabar shuki, noto'g'ri qadamlar ham osongina qilinadi: n_jobs=-1 ni har joyga qo'yish sekinlashtirishi mumkin, siyrakni zichga aylantirish xotirani portlatadi, KNeighbors esa butun o'quv to'plamini saqlaydi.
Bu darsda: dtype, siyraklik, n_jobs va ichma-ich parallellik, model tanlash, partial_fit, xotirani o'lchash va qayerni optimallashtirish kerakligini aniqlash.
Real vaziyat. Matn klassifikatsiyasi quvuri 12 GB xotira so'rardi va serverda ishlamasdi. Sabab bitta qatorda edi: TfidfVectorizer chiqishi siyrak edi, lekin keyingi StandardScaler(with_mean=True) uni zichga aylantirishga majbur qilardi. with_mean=False qo'yilgach xotira 400 MB ga tushdi.
Bu darsda tezlik va xotirani o'rganamiz.
Bu darsda:
- dtype va xotira
- Siyraklikni saqlash
- n_jobs va ichma-ich parallellik
- Model va hajm
- partial_fit
- Qayerni optimallashtirish
- Tuzoqlar
- Amaliy: quvurni tezlashtirish
ℹ Misollar real numpy/scipy/sklearn bilan (Python 3.14, sklearn 1.9).
2. Nazariya — chuqur tushuntirish
2.1. dtype va xotira
float64 (sukut) 8 bayt/element
float32 4 bayt/element -> IKKI BAROBAR kam
float16 2 bayt -> aniqlik juda past, ehtiyot
1 000 000 x 100 matritsa:
float64 -> 800 MB
float32 -> 400 MB
sklearn ning KO'PCHILIGI float32 ni qabul qiladi va
ichkarida float64 ga AYLANTIRMAYDI (tekshiring!)
INT uchun ham: int64 -> int32 / int8 (kategoriya kodlari)
pandas da:
df = df.astype({"a": "float32", "k": "category"})
"category" dtype takroriy satrlarni bir marta saqlaydi float32 ga o'tish xotirani ikki barobar kamaytiradi va ko'pchilik model uchun aniqlikka ta'sir qilmaydi.
2.2. Siyraklikni saqlash
SIYRAK MATRITSA: faqat nolmas elementlar saqlanadi
CSR - qatorlar bo'yicha (sklearn ko'pchiligi shuni kutadi)
CSC - ustunlar bo'yicha
QACHON FOYDALI: nolmas ulush < 10%
matn (TF-IDF), one-hot (ko'p daraja), grafik
SIYRAKNI BUZADIGANLAR:
StandardScaler(with_mean=True) -> markazlashtirish nolni buzadi
PCA (oddiy) -> TruncatedSVD ishlating
PolynomialFeatures -> portlash
toarray() / todense() -> ochiq aylantirish
set_output("pandas") -> siyrak qo'llab-quvvatlanmaydi
SIYRAKNI QABUL QILADIGAN MODELLAR:
LogisticRegression, LinearSVC, SGDClassifier
MultinomialNB, ComplementNB
RandomForest (qabul qiladi, lekin sekin)
QABUL QILMAYDIGANLAR:
HistGradientBoosting, KNeighbors (ba'zi metrika bilan) StandardScaler(with_mean=False) siyraklikni saqlaydi — matn quvurlarida bu eng ko'p uchraydigan tuzatish.
2.3. n_jobs va ichma-ich parallellik
n_jobs=None (sukut) bitta protsess
n_jobs=-1 barcha yadrolar
n_jobs=k k ta protsess
QACHON FOYDA BERADI:
RandomForest, ExtraTrees (daraxtlar mustaqil)
cross_val_score, GridSearchCV (foldlar mustaqil)
KNeighbors (so'rovlar mustaqil)
QACHON FOYDA BERMAYDI yoki ZARAR QILADI:
kichik ma'lumot (protsess yaratish narxi kattaroq)
HistGradientBoosting (ichkarida OpenMP ishlatadi)
ichma-ich: GridSearchCV(n_jobs=-1) + RF(n_jobs=-1)
-> protsesslar YADRO UCHUN KURASHADI, sekinlashadi
QOIDA: FAQAT BIR pog'onada parallellik
tashqi (GridSearchCV) n_jobs=-1, ichki n_jobs=1 Ichma-ich parallellik sekinlashtiradi: tashqi halqada n_jobs=-1 bo'lsa, ichki modelda n_jobs=1 qo'ying.
2.4. Model va hajm
n < 10 000:
hamma narsa ishlaydi, SVC(rbf) ham
n = 10 000 - 100 000:
SVC(rbf) sekin (O(n^2)) -> LinearSVC yoki SGD
RandomForest ishlaydi
HistGradientBoosting - eng yaxshi tanlov
n = 100 000 - 1 000 000:
HistGradientBoosting (binlash tufayli tez)
SGDClassifier / SGDRegressor
KNeighbors SEKIN (har so'rov uchun qidiruv)
n > 1 000 000:
SGD + partial_fit
HistGradientBoosting (xotira yetsa)
namuna olish (subsampling) - ko'pincha yetarli
XOTIRA TALABI:
KNeighbors - BUTUN o'quv to'plami
SVC - support vektorlar
RandomForest - daraxtlar (n_estimators x chuqurlik)
chiziqli model - faqat koeffitsiyentlar (eng kichik) HistGradientBoosting katta ma'lumot uchun sukut tanlov: u qiymatlarni binlaydi va n bo'yicha deyarli chiziqli ishlaydi.
2.5. partial_fit
model = SGDClassifier(loss="log_loss", random_state=0)
sinflar = np.unique(y)
for bolak_X, bolak_y in bolaklar:
model.partial_fit(bolak_X, bolak_y, classes=sinflar)
QO'LLAB-QUVVATLAYDIGANLAR:
SGDClassifier, SGDRegressor
MultinomialNB, BernoulliNB
MiniBatchKMeans
StandardScaler, IncrementalPCA (transformerlar ham)
MUHIM:
birinchi chaqiruvda classes= berish SHART (klassifikatsiyada)
ma'lumot ARALASHTIRILGAN bo'lishi kerak
bir necha EPOXA kerak bo'lishi mumkin
Pipeline partial_fit ni QO'LLAB-QUVVATLAMAYDI Pipeline da partial_fit yo'q — bo'laklab o'rgatishda tayyorlashni qo'lda boshqarish kerak.
2.6. Qayerni optimallashtirish
QOIDA: OLDIN O'LCHANG, KEYIN OPTIMALLASHTIRING
O'LCHASH:
import time; t0 = time.perf_counter(); ...; time.perf_counter() - t0
cProfile / py-spy (funksiya darajasida)
quvur qadamlari: cross_validate -> fit_time
XOTIRA:
X.nbytes (zich), (data.nbytes + indices.nbytes + indptr.nbytes) (siyrak)
tracemalloc, memory_profiler
ODATIY TAQSIMOT:
ma'lumot o'qish/tayyorlash 40%
belgi hisoblash 30%
model fit 25%
qolgani 5%
Ya'ni model emas, TAYYORLASH ko'pincha eng qimmat Model fit ko'pincha eng qimmat qadam emas — avval o'lchang, keyin optimallashtiring.
2.7. Tuzoqlar
Asosiy tuzoqlar: ichma-ich n_jobs=-1; siyrakni zichga aylantirish; StandardScaler(with_mean=True) ni siyrak bilan; float64 ni keraksiz saqlash; kichik ma'lumotda n_jobs=-1; KNeighbors ni katta ma'lumotda; o'lchamasdan optimallashtirish; PolynomialFeatures ni ko'p belgi bilan.
2.8. Uch arzon yutuq
Tezlik va xotira muammolarining katta qismi uchta arzon qadam bilan hal bo'ladi: float32 ga o'tish (xotira yarmiga), siyraklikni saqlash (with_mean=False, TruncatedSVD) va parallellikni bir pog'onada qoldirish. To'rtinchisi — to'g'ri modelni tanlash: n > 100 000 da HistGradientBoosting yoki SGD. Va har doim oldin o'lchang.
3. Tez ma'lumotnoma
import numpy as np
from scipy import sparse
from sklearn.decomposition import TruncatedSVD
from sklearn.preprocessing import StandardScaler
X32 = X.astype(np.float32) # xotira yarmiga
StandardScaler(with_mean=False) # siyraklikni saqlaydi
TruncatedSVD(n_components=100) # siyrak uchun PCA
OneHotEncoder(sparse_output=True) # siyrak chiqish
GridSearchCV(..., n_jobs=-1) # TASHQI parallellik
RandomForestClassifier(..., n_jobs=1) # ICHKI ketma-ket
def hajm_mb(m):
if sparse.issparse(m):
return (m.data.nbytes + m.indices.nbytes
+ m.indptr.nbytes) / 1024**2
return m.nbytes / 1024**2
QOIDA: oldin o'lcha · float32 · siyrakni saqla ·
parallellik bir pog'onadaTezlik va xotira xulosasi
float32: xotira yarmiga
Siyraklik: with_mean=False, TruncatedSVD
n_jobs: faqat BIR pog'onada
n > 100k: HistGradientBoosting yoki SGD
partial_fit: bo'laklab (Pipeline qo'llab-quvvatlamaydi)
Oldin o'lchang4. Batafsil misollar
Misollar real numpy/scipy/sklearn bilan (Python 3.14).
Misol 1 — dtype va xotira
"""float64, float32 va kategoriya (real numpy/pandas/sklearn)."""
import numpy as np
import pandas as pd
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import roc_auc_score
from sklearn.model_selection import train_test_split
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
def main() -> None:
rng = np.random.default_rng(0)
n, p = 60_000, 40
X64 = rng.normal(0, 1, (n, p))
y = (X64[:, 0] + 0.5 * X64[:, 1] + rng.normal(0, 1, n) > 0).astype(int)
print("=== 1. Massiv hajmi ===")
print(f" {'dtype':<12} {'hajm (MB)':>11} {'nisbat':>8}")
asos = X64.nbytes / 1024**2
for nom, dt in [("float64", np.float64), ("float32", np.float32),
("float16", np.float16)]:
Xd = X64.astype(dt)
mb = Xd.nbytes / 1024**2
print(f" {nom:<12} {mb:>11.2f} {asos / mb:>7.1f}x")
print("\n=== 2. Aniqlikka ta'siri ===")
Xtr64, Xte64, ytr, yte = train_test_split(X64, y, test_size=0.3,
random_state=0)
print(f" {'dtype':<12} {'test AUC':>10} {'farq':>10}")
asos_auc = None
for nom, dt in [("float64", np.float64), ("float32", np.float32)]:
m = make_pipeline(StandardScaler(),
LogisticRegression(max_iter=2000))
m.fit(Xtr64.astype(dt), ytr)
auc = roc_auc_score(yte, m.predict_proba(Xte64.astype(dt))[:, 1])
asos_auc = asos_auc if asos_auc is not None else auc
print(f" {nom:<12} {auc:>10.6f} {auc - asos_auc:>+10.6f}")
print("\n=== 3. sklearn dtype ni saqlaydimi ===")
for nom, dt in [("float64", np.float64), ("float32", np.float32)]:
sc = StandardScaler().fit(X64[:1000].astype(dt))
chiqish = sc.transform(X64[:1000].astype(dt))
print(f" kirish {nom:<9} -> chiqish {chiqish.dtype}, "
f"mean_ {sc.mean_.dtype}")
print("\n=== 4. pandas: category dtype ===")
df = pd.DataFrame({
"kod": rng.choice([f"m{i}" for i in range(50)], n),
"son": rng.normal(0, 1, n),
})
xom_mb = df.memory_usage(deep=True).sum() / 1024**2
df2 = df.astype({"kod": "category", "son": "float32"})
yangi_mb = df2.memory_usage(deep=True).sum() / 1024**2
print(f" {'variant':<24} {'hajm (MB)':>11}")
print(f" {'xom (str + float64)':<24} {xom_mb:>11.2f}")
print(f" {'category + float32':<24} {yangi_mb:>11.2f}")
print(f" tejash: {xom_mb / yangi_mb:.1f}x")
print(" ⭐ float32 - eng arzon optimallashtirish")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Massiv hajmi ===
dtype hajm (MB) nisbat
float64 18.31 1.0x
float32 9.16 2.0x
float16 4.58 4.0x
=== 2. Aniqlikka ta'siri ===
dtype test AUC farq
float64 0.848591 +0.000000
float32 0.848591 +0.000000
=== 3. sklearn dtype ni saqlaydimi ===
kirish float64 -> chiqish float64, mean_ float64
kirish float32 -> chiqish float32, mean_ float64
=== 4. pandas: category dtype ===
variant hajm (MB)
xom (str + float64) 3.42
category + float32 0.29
tejash: 11.9x
⭐ float32 - eng arzon optimallashtirishNima ko'rsatdi: 2.1-bo'lim.
Misol 2 — Siyraklikni saqlash
"""Siyraklikni nima buzadi (real numpy/scipy/sklearn)."""
import numpy as np
from scipy import sparse
from sklearn.decomposition import PCA, TruncatedSVD
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import MaxAbsScaler, StandardScaler
def matnlar_yasa(n: int = 6000, seed: int = 0):
rng = np.random.default_rng(seed)
lugat = [f"soz{i}" for i in range(4000)]
matnlar, y = [], []
for _ in range(n):
sinf = int(rng.integers(0, 2))
asos = rng.choice(lugat[:200] if sinf else lugat[200:400], 8)
shovqin = rng.choice(lugat, 12)
matnlar.append(" ".join(np.concatenate([asos, shovqin])))
y.append(sinf)
return matnlar, np.asarray(y)
def hajm_mb(m) -> float:
if sparse.issparse(m):
return (m.data.nbytes + m.indices.nbytes
+ m.indptr.nbytes) / 1024**2
return m.nbytes / 1024**2
def main() -> None:
matnlar, y = matnlar_yasa()
vek = TfidfVectorizer(max_features=4000)
X = vek.fit_transform(matnlar)
print("=== 1. Siyrak matritsa ===")
print(f" shakl: {X.shape}, turi: {type(X).__name__}")
print(f" nolmas elementlar: {X.nnz:,}")
toldirilgan = X.nnz / (X.shape[0] * X.shape[1])
print(f" to'ldirilganlik: {toldirilgan:.3%}")
print(f" siyrak hajm: {hajm_mb(X):.2f} MB")
print(f" zich bo'lsa: "
f"{X.shape[0] * X.shape[1] * 8 / 1024**2:.2f} MB")
print("\n=== 2. Nima siyraklikni buzadi ===")
sinashlar = {
"StandardScaler(with_mean=True)": StandardScaler(),
"StandardScaler(with_mean=False)": StandardScaler(with_mean=False),
"MaxAbsScaler": MaxAbsScaler(),
"TruncatedSVD(50)": TruncatedSVD(n_components=50, random_state=0),
}
print(f" {'transformer':<34} {'natija':<22}")
for nom, tr in sinashlar.items():
try:
chiqish = tr.fit_transform(X)
turi = "siyrak" if sparse.issparse(chiqish) else "ZICH"
print(f" {nom:<34} {turi + f', {hajm_mb(chiqish):.1f} MB':<22}")
except Exception as xato:
print(f" {nom:<34} {type(xato).__name__:<22}")
print("\n=== 3. PCA siyrak bilan ===")
try:
PCA(n_components=50).fit(X)
print(" PCA siyrakni qabul qildi (kutilmagan)")
except TypeError as xato:
print(f" PCA: {type(xato).__name__}")
print(f" {str(xato).splitlines()[0][:60]}")
svd = TruncatedSVD(n_components=50, random_state=0).fit(X)
print(f" TruncatedSVD ishladi: "
f"tushuntirilgan dispersiya "
f"{svd.explained_variance_ratio_.sum():.4f}")
print("\n=== 4. To'g'ri va noto'g'ri quvur ===")
from sklearn.model_selection import StratifiedKFold, cross_val_score
cv = StratifiedKFold(3, shuffle=True, random_state=0)
variantlar = {
"with_mean=False (siyrak)": Pipeline([
("sc", StandardScaler(with_mean=False)),
("m", LogisticRegression(max_iter=1000))]),
"MaxAbsScaler (siyrak)": Pipeline([
("sc", MaxAbsScaler()),
("m", LogisticRegression(max_iter=1000))]),
}
print(f" {'variant':<28} {'CV AUC':>9} {'oraliq hajm (MB)':>18}")
for nom, q in variantlar.items():
b = cross_val_score(q, X, y, cv=cv, scoring="roc_auc")
oraliq = q.fit(X, y)[:-1].transform(X)
print(f" {nom:<28} {b.mean():>9.4f} {hajm_mb(oraliq):>18.2f}")
zich_mb = X.shape[0] * X.shape[1] * 8 / 1024**2
print(f" {'zich bo_lsa':<28} {'-':>9} {zich_mb:>18.2f}")
print(" ⭐ with_mean=False siyraklikni saqlaydi")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Siyrak matritsa ===
shakl: (6000, 4000), turi: csr_matrix
nolmas elementlar: 118,934
to'ldirilganlik: 0.496%
siyrak hajm: 1.38 MB
zich bo'lsa: 183.11 MB
=== 2. Nima siyraklikni buzadi ===
transformer natija
StandardScaler(with_mean=True) ValueError
StandardScaler(with_mean=False) siyrak, 1.4 MB
MaxAbsScaler siyrak, 1.4 MB
TruncatedSVD(50) ZICH, 2.3 MB
=== 3. PCA siyrak bilan ===
PCA siyrakni qabul qildi (kutilmagan)
TruncatedSVD ishladi: tushuntirilgan dispersiya 0.0611
=== 4. To'g'ri va noto'g'ri quvur ===
variant CV AUC oraliq hajm (MB)
with_mean=False (siyrak) 1.0000 1.38
MaxAbsScaler (siyrak) 1.0000 1.38
zich bo_lsa - 183.11
⭐ with_mean=False siyraklikni saqlaydiNima ko'rsatdi: 2.2-bo'lim.
Misol 3 — Model tanlash va hajm
"""Qaysi model qaysi hajmga mos (real numpy/sklearn)."""
import io
import pickle
import numpy as np
from sklearn.datasets import make_classification
from sklearn.ensemble import HistGradientBoostingClassifier, RandomForestClassifier
from sklearn.linear_model import LogisticRegression, SGDClassifier
from sklearn.metrics import roc_auc_score
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
def hajm_kb(model) -> float:
buf = io.BytesIO()
pickle.dump(model, buf, protocol=pickle.HIGHEST_PROTOCOL)
return buf.tell() / 1024
def main() -> None:
X, y = make_classification(n_samples=12_000, n_features=25,
n_informative=10, n_redundant=5,
flip_y=0.15, class_sep=0.85, random_state=0)
Xtr, Xte, ytr, yte = train_test_split(X, y, test_size=0.3,
random_state=0)
print("=== 1. Model hajmi va sifati (n=8400) ===")
modellar = {
"LogisticRegression": make_pipeline(
StandardScaler(), LogisticRegression(max_iter=2000)),
"SGDClassifier": make_pipeline(
StandardScaler(),
SGDClassifier(loss="log_loss", max_iter=1500, tol=1e-4,
random_state=0)),
"HistGradientBoosting": HistGradientBoostingClassifier(
max_iter=150, early_stopping=False, random_state=0),
"RandomForest(150)": RandomForestClassifier(
n_estimators=150, min_samples_leaf=5, random_state=0, n_jobs=1),
"KNN(k=25)": make_pipeline(StandardScaler(),
KNeighborsClassifier(n_neighbors=25)),
}
print(f" {'model':<24} {'test AUC':>10} {'hajm (KB)':>11} "
f"{'hajm/n':>10}")
for nom, m in modellar.items():
m.fit(Xtr, ytr)
p = (m.predict_proba(Xte)[:, 1] if hasattr(m, "predict_proba")
else m.decision_function(Xte))
kb = hajm_kb(m)
print(f" {nom:<24} {roc_auc_score(yte, p):>10.4f} {kb:>11.1f} "
f"{kb / len(ytr) * 1000:>10.3f}")
print("\n=== 2. Hajm o'quv to'plamiga bog'liqmi ===")
print(f" {'n':>8} {'KNN (KB)':>11} {'LogReg (KB)':>13} "
f"{'HistGB (KB)':>13}")
for n in [1000, 3500, 8400]:
knn = make_pipeline(StandardScaler(),
KNeighborsClassifier(n_neighbors=25))
knn.fit(Xtr[:n], ytr[:n])
lr = make_pipeline(StandardScaler(),
LogisticRegression(max_iter=2000))
lr.fit(Xtr[:n], ytr[:n])
gb = HistGradientBoostingClassifier(max_iter=150,
early_stopping=False,
random_state=0)
gb.fit(Xtr[:n], ytr[:n])
print(f" {n:>8} {hajm_kb(knn):>11.1f} {hajm_kb(lr):>13.1f} "
f"{hajm_kb(gb):>13.1f}")
print(" KNN hajmi n ga PROPORSIONAL - butun to'plamni saqlaydi")
print("\n=== 3. RandomForest hajmi nimaga bog'liq ===")
print(f" {'n_estimators':>13} {'min_samples_leaf':>18} "
f"{'hajm (KB)':>11} {'test AUC':>10}")
for n_est, min_leaf in [(50, 1), (150, 1), (150, 20), (300, 20)]:
rf = RandomForestClassifier(n_estimators=n_est,
min_samples_leaf=min_leaf,
random_state=0, n_jobs=1).fit(Xtr, ytr)
auc = roc_auc_score(yte, rf.predict_proba(Xte)[:, 1])
print(f" {n_est:>13} {min_leaf:>18} {hajm_kb(rf):>11.1f} "
f"{auc:>10.4f}")
print(" min_samples_leaf ni oshirish hajmni keskin kamaytiradi")
print("\n=== 4. Tavsiya jadvali ===")
tavsiya = [
("n < 10 000", "hamma narsa, SVC(rbf) ham"),
("10k - 100k", "HistGradientBoosting, LinearSVC, RF"),
("100k - 1M", "HistGradientBoosting, SGD"),
("n > 1M", "SGD + partial_fit, namuna olish"),
]
print(f" {'hajm':<14} {'tavsiya'}")
for hajm, matn in tavsiya:
print(f" {hajm:<14} {matn}")
print(" ⭐ KNN va SVC hajmi o'quv to'plamiga bog'liq")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Model hajmi va sifati (n=8400) ===
model test AUC hajm (KB) hajm/n
LogisticRegression 0.7168 1.8 0.217
SGDClassifier 0.6949 2.0 0.243
HistGradientBoosting 0.8968 570.1 67.869
RandomForest(150) 0.8981 12561.8 1495.447
KNN(k=25) 0.8864 1707.9 203.318
=== 2. Hajm o'quv to'plamiga bog'liqmi ===
n KNN (KB) LogReg (KB) HistGB (KB)
1000 204.7 1.8 570.1
3500 712.5 1.8 570.1
8400 1707.9 1.8 570.1
KNN hajmi n ga PROPORSIONAL - butun to'plamni saqlaydi
=== 3. RandomForest hajmi nimaga bog'liq ===
n_estimators min_samples_leaf hajm (KB) test AUC
50 1 7468.6 0.8963
150 1 22395.2 0.9005
150 20 4595.3 0.8897
300 20 9184.8 0.8906
min_samples_leaf ni oshirish hajmni keskin kamaytiradi
=== 4. Tavsiya jadvali ===
hajm tavsiya
n < 10 000 hamma narsa, SVC(rbf) ham
10k - 100k HistGradientBoosting, LinearSVC, RF
100k - 1M HistGradientBoosting, SGD
n > 1M SGD + partial_fit, namuna olish
⭐ KNN va SVC hajmi o'quv to'plamiga bog'liqNima ko'rsatdi: 2.4-bo'lim.
Misol 4 — partial_fit bilan bo'laklab o'rgatish
"""Xotiraga sig'maydigan ma'lumot uchun (real numpy/sklearn)."""
import numpy as np
from sklearn.datasets import make_classification
from sklearn.linear_model import LogisticRegression, SGDClassifier
from sklearn.metrics import roc_auc_score
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
def bolaklar(X, y, hajm: int):
for boshi in range(0, len(y), hajm):
yield X[boshi:boshi + hajm], y[boshi:boshi + hajm]
def main() -> None:
X, y = make_classification(n_samples=40_000, n_features=20,
n_informative=10, flip_y=0.15,
class_sep=0.8, random_state=0)
Xtr, Xte, ytr, yte = train_test_split(X, y, test_size=0.25,
random_state=0)
sinflar = np.unique(y)
print("=== 1. Bo'laklab masshtablash ===")
sc = StandardScaler()
for bX, _ in bolaklar(Xtr, ytr, 5000):
sc.partial_fit(bX)
sc_toliq = StandardScaler().fit(Xtr)
print(f" bo'laklab o'rtacha (birinchi 3): "
f"{np.round(sc.mean_[:3], 6).tolist()}")
print(f" to'liq o'rtacha (birinchi 3): "
f"{np.round(sc_toliq.mean_[:3], 6).tolist()}")
print(f" maksimal farq: "
f"{np.abs(sc.mean_ - sc_toliq.mean_).max():.2e}")
print("\n=== 2. Bo'laklab o'rgatish ===")
Xtr_s = sc.transform(Xtr)
Xte_s = sc.transform(Xte)
model = SGDClassifier(loss="log_loss", random_state=0)
print(f" {'epoxa':>7} {'test AUC':>10}")
rng = np.random.default_rng(0)
for epoxa in range(1, 6):
tartib = rng.permutation(len(ytr)) # ARALASHTIRISH muhim
for bX, by in bolaklar(Xtr_s[tartib], ytr[tartib], 2000):
model.partial_fit(bX, by, classes=sinflar)
auc = roc_auc_score(yte, model.predict_proba(Xte_s)[:, 1])
print(f" {epoxa:>7} {auc:>10.4f}")
print("\n=== 3. To'liq o'rgatish bilan solishtirish ===")
toliq = LogisticRegression(max_iter=2000).fit(Xtr_s, ytr)
toliq_auc = roc_auc_score(yte, toliq.predict_proba(Xte_s)[:, 1])
bolak_auc = roc_auc_score(yte, model.predict_proba(Xte_s)[:, 1])
print(f" {'usul':<28} {'test AUC':>10}")
print(f" {'LogisticRegression (to_liq)':<28} {toliq_auc:>10.4f}")
print(f" {'SGD + partial_fit (5 epoxa)':<28} {bolak_auc:>10.4f}")
print(f" farq: {bolak_auc - toliq_auc:+.4f}")
print("\n=== 4. Aralashtirishning ahamiyati ===")
# maqsad bo'yicha TARTIBLANGAN ma'lumot
tartib = np.argsort(ytr, kind="stable")
tartibli = SGDClassifier(loss="log_loss", random_state=0)
for _ in range(5):
for bX, by in bolaklar(Xtr_s[tartib], ytr[tartib], 2000):
if len(np.unique(by)) < 2:
tartibli.partial_fit(bX, by, classes=sinflar)
else:
tartibli.partial_fit(bX, by, classes=sinflar)
tartibli_auc = roc_auc_score(
yte, tartibli.predict_proba(Xte_s)[:, 1])
print(f" {'ma_lumot tartibi':<28} {'test AUC':>10}")
print(f" {'aralashtirilgan':<28} {bolak_auc:>10.4f}")
print(f" {'maqsad bo_yicha tartibli':<28} {tartibli_auc:>10.4f}")
print(f" farq: {tartibli_auc - bolak_auc:+.4f}")
print("\n=== 5. Qaysi obyektlar partial_fit ni qo'llab-quvvatlaydi ===")
from sklearn.cluster import MiniBatchKMeans
from sklearn.decomposition import IncrementalPCA
from sklearn.naive_bayes import MultinomialNB
from sklearn.pipeline import Pipeline
obyektlar = {
"SGDClassifier": SGDClassifier(),
"MultinomialNB": MultinomialNB(),
"StandardScaler": StandardScaler(),
"IncrementalPCA": IncrementalPCA(n_components=3),
"MiniBatchKMeans": MiniBatchKMeans(n_clusters=3, n_init=3),
"LogisticRegression": LogisticRegression(),
"Pipeline": Pipeline([("sc", StandardScaler())]),
}
print(f" {'obyekt':<22} {'partial_fit':>12}")
for nom, ob in obyektlar.items():
print(f" {nom:<22} "
f"{str(hasattr(ob, 'partial_fit')):>12}")
print(" ⭐ Pipeline partial_fit ni qo'llab-quvvatlamaydi")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Bo'laklab masshtablash ===
bo'laklab o'rtacha (birinchi 3): [0.002846, 0.389144, -0.40801]
to'liq o'rtacha (birinchi 3): [0.002846, 0.389144, -0.40801]
maksimal farq: 5.44e-15
=== 2. Bo'laklab o'rgatish ===
epoxa test AUC
1 0.6359
2 0.6586
3 0.6339
4 0.6857
5 0.6812
=== 3. To'liq o'rgatish bilan solishtirish ===
usul test AUC
LogisticRegression (to_liq) 0.7309
SGD + partial_fit (5 epoxa) 0.6812
farq: -0.0498
=== 4. Aralashtirishning ahamiyati ===
ma_lumot tartibi test AUC
aralashtirilgan 0.6812
maqsad bo_yicha tartibli 0.7271
farq: +0.0459
=== 5. Qaysi obyektlar partial_fit ni qo'llab-quvvatlaydi ===
obyekt partial_fit
SGDClassifier True
MultinomialNB True
StandardScaler True
IncrementalPCA True
MiniBatchKMeans True
LogisticRegression False
Pipeline False
⭐ Pipeline partial_fit ni qo'llab-quvvatlamaydiNima ko'rsatdi: 2.5-bo'lim.
5. To'g'ri va noto'g'ri tushunishlar
| Noto'g'ri fikr | To'g'risi |
|---|---|
"n_jobs=-1 har doim tezroq" |
Ichma-ich parallellik sekinlashtiradi |
"float64 kerak" |
float32 ko'pincha yetarli |
| "Siyrakni zichga aylantirsa qulay" | Xotira portlashi mumkin |
"StandardScaler siyrak bilan ishlaydi" |
with_mean=False kerak |
"PCA siyrakni qabul qiladi" |
TruncatedSVD kerak |
"Model fit eng qimmat" |
Tayyorlash ko'pincha qimmatroq |
"Pipeline da partial_fit bor" |
Yo'q |
| "KNN hajmi kichik" | Butun o'quv to'plami |
6. Keng tarqalgan xatolar va yechimlari
1. Ichma-ich parallellik
GridSearchCV(RandomForestClassifier(n_jobs=-1), ..., n_jobs=-1) # ⚠️
GridSearchCV(RandomForestClassifier(n_jobs=1), ..., n_jobs=-1) # ✅2. Siyraklikni buzish
Pipeline([("tfidf", TfidfVectorizer()), ("sc", StandardScaler())]) # ⚠️
Pipeline([("tfidf", TfidfVectorizer()),
("sc", StandardScaler(with_mean=False))]) # ✅3. Siyrak bilan PCA
Pipeline([("tfidf", TfidfVectorizer()), ("p", PCA(n_components=50))]) # ⚠️
Pipeline([("tfidf", TfidfVectorizer()),
("p", TruncatedSVD(n_components=50))]) # ✅4. Keraksiz float64
X = df.to_numpy() # float64 # ⚠️
X = df.to_numpy(dtype=np.float32) # ✅5. Katta ma'lumotda KNN
KNeighborsClassifier().fit(X_1M, y) # ⚠️
HistGradientBoostingClassifier().fit(X_1M, y) # ✅6. O'lchamasdan optimallashtirish
# modelni almashtiramiz, chunki sekin # ⚠️
n = cross_validate(...); print(n["fit_time"], n["score_time"]) # ✅7. partial_fit da classes yo'q
model.partial_fit(bX, by) # birinchi chaqiruvda xato # ⚠️
model.partial_fit(bX, by, classes=np.unique(y)) # ✅7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 19.3-dars (o'tilgan): Siyrak chiqish
- 19.6-dars (o'tilgan): Model hajmi
- 19.7-dars (o'tilgan):
n_jobsva takrorlanuvchanlik - 19.10-dars: To'liq loyiha
- 29-qism: MLOps va ishlab chiqarish
8. Eng yaxshi amaliyotlar
Oldin o'lchang.
float32ga o'ting.Siyraklikni saqlang.
Parallellik bir pog'onada.
Hajmga mos model.
categorydtype ishlating.Katta ma'lumotda
partial_fityoki namuna.Model hajmini kuzating.
9. Amaliy topshiriq
Vazifa 1: Bashorat qiling
1. # float32 nima beradi?
2. # siyraklik qachon foydali?
3. # nima siyraklikni buzadi?
4. # StandardScaler siyrak bilan qanday?
5. # PCA o'rniga nima?
6. # ichma-ich n_jobs muammosi?
7. # n > 100k da qaysi model?
8. # KNN hajmi nimaga bog'liq?
9. # partial_fit da nima shart?
10. # Pipeline partial_fit ni qo'llaydimi?
11. # odatda eng qimmat qadam?
12. # RF hajmini nima kamaytiradi?Javoblar
- Xotirani ikki barobar kamaytiradi
- Nolmas ulush < 10%
with_mean=True,PCA,toarray()with_mean=FalseTruncatedSVD- Protsesslar yadro uchun kurashadi
HistGradientBoostingyokiSGD- O'quv to'plami hajmiga
- Birinchi chaqiruvda
classes= - Yo'q
- Tayyorlash
min_samples_leafni oshirish
Vazifa 2: Xatolarni tuzating
1. GridSearchCV(RandomForestClassifier(n_jobs=-1), ..., n_jobs=-1)
2. Pipeline([("tfidf", TfidfVectorizer()), ("sc", StandardScaler())])
3. Pipeline([("tfidf", TfidfVectorizer()), ("p", PCA(n_components=50))])
4. KNeighborsClassifier().fit(X_1M, y)
5. model.partial_fit(bX, by)Javoblar
1. GridSearchCV(RandomForestClassifier(n_jobs=1), ..., n_jobs=-1)
2. ("sc", StandardScaler(with_mean=False))
3. ("p", TruncatedSVD(n_components=50))
4. HistGradientBoostingClassifier().fit(X_1M, y)
5. model.partial_fit(bX, by, classes=np.unique(y))Vazifa 3: dtype
Modellang:
- Hajm
- Aniqlik
- sklearn saqlaydimi
category
Vazifa 4: Siyraklik
Modellang:
- Siyrak matritsa
- Nima buzadi
PCA- Quvur
Vazifa 5: Model tanlash
Modellang:
- Hajm va sifat
nga bog'liqlik- RF hajmi
- Tavsiya
Vazifa 6: partial_fit
Modellang:
- Masshtablash
- O'rgatish
- Solishtirish
- Aralashtirish
Vazifa 7: O'ylash
Quvuringiz 40 daqiqa ishlaydi. Modelni RandomForest dan HistGradientBoosting ga o'tkazdingiz — vaqt 38 daqiqa bo'ldi. Nima qilishingiz kerak edi?
Javob
Qisqa javob: avval o'lchash kerak edi. 40 daqiqadan model fit atigi 2 daqiqa ekan — qolgan 38 daqiqa boshqa joyda.
1. Qayerni o'lchash
import time
t0 = time.perf_counter()
df = pd.read_parquet("data.parquet")
t_oqish = time.perf_counter() - t0
t0 = time.perf_counter()
X = belgilar_yasa(df)
t_belgilar = time.perf_counter() - t0
natija = cross_validate(quvur, X, y, cv=cv, return_train_score=False)
print(f"o'qish: {t_oqish:.1f}s, belgilar: {t_belgilar:.1f}s")
print(f"fit: {natija['fit_time'].sum():.1f}s, "
f"score: {natija['score_time'].sum():.1f}s")2. Odatiy taqsimot
| Bosqich | Ulush |
|---|---|
| Ma'lumot o'qish/tayyorlash | ~40% |
| Belgi hisoblash | ~30% |
Model fit |
~25% |
| Qolgani | ~5% |
Model fit kamdan-kam eng qimmat qadam bo'ladi.
3. Har bosqich uchun arzon yutuqlar
O'qish:
pd.read_parquet(...) # CSV o'rniga (5-10x tez)
pd.read_csv(..., usecols=[...], dtype={...}) # faqat keraklisiBelgilar:
# apply o'rniga vektorlashtirilgan amallar
df["nisbat"] = df["a"] / df["b"].clip(lower=1) # emas: df.apply(...)
# takroriy hisoblashni keshlang (Pipeline memory - 19.2)CV:
cross_validate(..., n_jobs=-1) # foldlar parallel
cv=StratifiedKFold(3) # 5 o'rniga 3 (18.3-dars)Ma'lumot hajmi:
X = X.astype(np.float32) # xotira va tezlik
# yoki ishlab chiqish paytida namuna oling
Xn, yn = X[:50_000], y[:50_000]4. Umumiy qoida
Optimallashtirishdan oldin profil oling. Profil olmasdan qilingan optimallashtirish o'rtacha taxmin bo'yicha bajariladi va ko'pincha noto'g'ri joyga tushadi.
5. Ishlab chiqish sikli
- Kichik namunada ishlang (10-50 ming qator)
- Mantiq to'g'ri bo'lgach to'liq ma'lumotga o'ting
- Sekin bo'lsa — o'lchang
- Eng katta ulushni optimallashtiring
- Qayta o'lchang
6. Xulosa
- Avval o'lchang
- Model
fitodatda eng qimmat emas - O'qish va belgilar ko'pincha katta ulush
- Ishlab chiqishda namuna bilan ishlang
Nimani mustahkamlaydi: 2.6-bo'lim.
Xulosa
Bu darsda tezlik va xotirani o'rgandik.
Eng muhim uch fikr:
Uch arzon yutuq:
float32, siyraklik, bir pog'onali parallellik.float64danfloat32ga o'tish xotirani ikki barobar kamaytiradi va ko'pchilik model uchun aniqlikka ta'sir qilmaydi. Siyrak matritsani saqlash (StandardScaler(with_mean=False),TruncatedSVD) matn va ko'p darajali kategoriya quvurlarida o'nlab barobar tejaydi.n_jobsfaqat bir pog'onada.GridSearchCV(n_jobs=-1)vaRandomForest(n_jobs=-1)birga ishlatilsa, protsesslar yadro uchun kurashadi va natija ketma-ket ishdan ham sekinroq bo'lishi mumkin. Tashqi halqada parallellik, ichkidan_jobs=1.Oldin o'lchang. Model
fitodatda eng qimmat qadam emas — ma'lumot o'qish va belgi hisoblash ko'pincha ko'proq vaqt oladi.cross_validateningfit_timevascore_timemaydonlari hamda oddiyperf_countero'lchovlari optimallashtirishni to'g'ri joyga yo'naltiradi.
Keyingi darsda to'liq loyiha: xom CSV dan boshlab, tayyorlash quvuri, sozlash, baholash va ishlab chiqarishga tayyor paketgacha bo'lgan yo'lni bir joyda quramiz.
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!