Mundarija (22)
- 1. Kirish va motivatsiya
- 2. Nazariya — chuqur tushuntirish
- 2.1. random_state ning uch shakli
- 2.2. Tasodifiylik manbalari
- 2.3. Global seed nima uchun yetarli emas
- 2.4. Oqimlar va suzuvchi nuqta
- 2.5. Versiyalarni qulflash
- 2.6. Takrorlanuvchanlik darajalari
- 2.7. Tuzoqlar
- 2.8. Seed — kod emas, ma'lumot
- 3. Tez ma'lumotnoma
- 4. Batafsil misollar
- Misol 1 — random_state ning uch shakli
- Misol 2 — Global seed nima uchun yetarli emas
- Misol 3 — Oqimlar, ma'lumot tartibi va suzuvchi nuqta
- Misol 4 — Takrorlanuvchan tajriba tuzilmasi
- 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.7-dars: Takrorlanuvchanlik
19-QISM — SCIKIT-LEARN TO'LIQ · 7-dars
1. Kirish va motivatsiya
"Menda 0.847 chiqdi." — "Menda 0.839." Bir xil kod, bir xil ma'lumot, turli natija. Bu suhbat har bir jamoada bo'lgan va u har doim vaqt yo'qotish bilan tugaydi.
Takrorlanuvchanlik — bu shunchaki qulaylik emas: usiz siz yaxshilanish haqiqiymi yoki shovqinmi ekanini ayta olmaysiz (18-qism), xatoni takrorlay olmaysiz va ishlab chiqarishdagi natijani tushuntira olmaysiz.
Tasodifiylikning manbalari ko'p va ularning ba'zilari sezilmaydi: model ichidagi seed, CV bo'linishi, ma'lumot tartibi, oqimlar soni (parallel hisobda suzuvchi nuqta yig'indisi tartibi o'zgaradi), kutubxona versiyasi va hatto lug'at tartibi (eski Python da).
Bu darsda: random_state ning uch shakli, global seed nima uchun yetarli emas, n_jobs va oqimlar ta'siri, versiyalarni qulflash, takrorlanuvchanlik darajalari va amaliy nazorat ro'yxati.
Real vaziyat. Jamoa ishlab chiqarish modelini qayta o'rgatdi va AUC 0.006 ga tushdi. Uch kun sabab qidirildi: ma'lumot o'zgarmagan, kod o'zgarmagan. Oxirida ma'lum bo'ldiki, yangi serverda CPU yadrolari soni boshqa edi va n_jobs=-1 bilan yig'indi tartibi o'zgargandi. Farq shovqin ichida edi, lekin uch kun yo'qotildi.
Bu darsda takrorlanuvchanlikni o'rganamiz.
Bu darsda:
- random_state ning uch shakli
- Tasodifiylik manbalari
- Global seed nima uchun yetarli emas
- Oqimlar va suzuvchi nuqta
- Versiyalarni qulflash
- Takrorlanuvchanlik darajalari
- Tuzoqlar
- Amaliy: nazorat ro'yxati
ℹ Misollar real numpy/sklearn bilan (Python 3.14, sklearn 1.9).
2. Nazariya — chuqur tushuntirish
2.1. random_state ning uch shakli
1. random_state=None (SUKUT)
global numpy generatoridan foydalanadi
HAR CHAQIRUVDA boshqa natija
2. random_state=42 (BUTUN SON)
har chaqiruvda AYNI seed dan boshlanadi
fit ikki marta -> AYNI natija
TAVSIYA: ishlab chiqarish va testlar uchun
3. random_state=np.random.RandomState(42) (OBYEKT)
HOLATI SAQLANADI va har chaqiruvda ILGARILAYDI
fit ikki marta -> TURLI natija
foydali: ko'p takrorli tajribada
DIQQAT: sklearn 1.9 yangi numpy Generator ni (default_rng)
QABUL QILMAYDI - faqat int, RandomState yoki None
MUHIM FARQ:
butun son -> takrorlanuvchan
obyekt -> takrorlanuvchan EMAS (lekin boshqarilgan) random_state obyekti berilsa, fit har safar boshqa natija beradi — va sklearn np.random.default_rng() ni umuman qabul qilmaydi: faqat int, RandomState yoki None.
2.2. Tasodifiylik manbalari
1. MODEL ichida
RandomForest (bootstrap, belgi tanlash)
HistGradientBoosting (binlash, subsample)
KMeans (boshlang'ich markazlar)
SGD, neyron tarmoq (og'irlik initsializatsiyasi, shuffle)
train_test_split, KFold(shuffle=True)
2. MA'LUMOT tomonidan
qatorlar tartibi (ba'zi algoritmlar sezgir)
duplikatlar va teng ballar (argmax tartibi)
3. MUHIT tomonidan
oqimlar soni (yig'indi tartibi)
BLAS kutubxonasi (OpenBLAS / MKL)
CPU arxitekturasi (SIMD)
kutubxona versiyasi
4. KOD tomonidan
to'plam (set) va lug'at bo'yicha aylanish
fayl tizimi tartibi (glob) Faqat random_state ni qo'yish yetarli emas — muhit va ma'lumot tartibi ham natijaga ta'sir qiladi.
2.3. Global seed nima uchun yetarli emas
np.random.seed(42) # ESKI global generator
model = RandomForestClassifier() # random_state=None
model.fit(X, y)
MUAMMOLAR:
1. sklearn ichida np.random.RandomState ishlatiladi -
global holat KETMA-KET chaqiruvlarda ILGARILAYDI
-> ikkinchi fit BOSHQA natija beradi
2. parallel ishda (n_jobs>1) har protsess o'z holatini oladi
3. kutubxona ichida global holatni o'zgartirishi mumkin
4. kod tartibi o'zgarsa - natija ham o'zgaradi
TO'G'RI YO'L: har obyektga ANIQ random_state=butun sonGlobal seed kod tartibiga bog'liq: bitta qatorni yuqoriga ko'chirsangiz natija o'zgaradi.
2.4. Oqimlar va suzuvchi nuqta
SUZUVCHI NUQTA QO'SHISH ASSOTSIATIV EMAS:
(a + b) + c != a + (b + c) (juda kichik farq bilan)
Parallel yig'indida qismlarga bo'lish TARTIBI oqimlar soniga
bog'liq -> natija bit darajasida farq qiladi
QAYERDA KO'RINADI:
numpy/BLAS matritsa ko'paytmasi
n_jobs bilan ishlaydigan ansambllar
OPENBLAS_NUM_THREADS, OMP_NUM_THREADS
TO'LIQ TAKRORLANUVCHANLIK UCHUN:
export OMP_NUM_THREADS=1
export OPENBLAS_NUM_THREADS=1
export MKL_NUM_THREADS=1
n_jobs=1
NARXI: sekinroq. Shuning uchun bu FAQAT tekshiruv va nashr uchun.Bit darajasidagi takrorlanuvchanlik uchun bitta oqim kerak — lekin bu sekin, shuning uchun uni tanlab ishlating.
2.5. Versiyalarni qulflash
MINIMAL:
requirements.txt da aniq versiya
scikit-learn==1.9.1
numpy==2.3.1
pandas==3.0.6
YAXSHIROQ:
pip freeze > requirements.lock
yoki uv.lock / poetry.lock (tranzitiv bog'liqliklar ham)
ENG YAXSHISI:
konteyner (Docker) - OS kutubxonalari ham qotiriladi
TEKSHIRISH:
loyiha boshida versiyalarni CHOP ETING va natija bilan saqlang Tranzitiv bog'liqliklarni ham qulflang — scipy yoki joblib versiyasi ham natijaga ta'sir qilishi mumkin.
2.6. Takrorlanuvchanlik darajalari
1-DARAJA: BIT DARAJASIDA (aynan bir xil sonlar)
bir xil mashina + bir xil versiyalar + bitta oqim + seed
kerak: birlik testlari, nashr uchun raqamlar
2-DARAJA: STATISTIK (xulosalar bir xil)
bir xil seed va versiyalar, turli mashina/oqim
natija 1e-6 atrofida farq qiladi - xulosaga ta'sir qilmaydi
kerak: kundalik ish, CI
3-DARAJA: ILMIY (boshqa odam takrorlay oladi)
kod + ma'lumot + versiyalar + seedlar hujjatlashtirilgan
kerak: nashr, audit
AMALIYOT: 2-daraja yetarli; 1-darajani testlarda ta'minlang2-daraja kundalik ish uchun yetarli: 1e-6 lik farq hech qanday xulosani o'zgartirmaydi.
2.7. Tuzoqlar
Asosiy tuzoqlar: np.random.seed ga tayanish; random_state obyekti berib takrorlanuvchanlik kutish; n_jobs=-1 bilan bit darajasidagi tenglikni kutish; versiyalarni qulflamaslik; ma'lumot tartibini o'zgartirish; set/dict bo'yicha aylanishga tayanish; seedni natijalar bilan birga saqlamaslik; "seed muhim emas" deb o'ylash.
2.8. Seed — kod emas, ma'lumot
random_state — bu konfiguratsiya, kod emas: uni bir joyda e'lon qiling, hamma obyektga uzating va natijalar bilan birga saqlang. Kundalik ishda 2-daraja (statistik takrorlanuvchanlik) yetarli; bit darajasidagi tenglik faqat testlar va nashr uchun kerak va u bitta oqim talab qiladi. Versiyalarni qulflash esa seedni qo'yish kabi muhim.
3. Tez ma'lumotnoma
import os
# BIT darajasidagi takrorlanuvchanlik uchun (importdan OLDIN)
os.environ["OMP_NUM_THREADS"] = "1"
os.environ["OPENBLAS_NUM_THREADS"] = "1"
os.environ["MKL_NUM_THREADS"] = "1"
SEED = 42 # bitta joyda
cv = StratifiedKFold(5, shuffle=True, random_state=SEED)
model = RandomForestClassifier(n_estimators=300, random_state=SEED,
n_jobs=1)
qidiruv = RandomizedSearchCV(model, taqsimot, n_iter=30, cv=cv,
random_state=SEED, n_jobs=1)
# natijalar bilan birga saqlang
metama = {"seed": SEED, "sklearn": sklearn.__version__,
"numpy": np.__version__, "n_jobs": 1}
QOIDA: aniq son seed · har obyektga · global seedga tayanma ·
versiyalarni qulfla · seedni natija bilan saqlaTakrorlanuvchanlik xulosasi
random_state: None (har safar boshqa) / son (takrorlanuvchan) /
obyekt (ilgarilaydi - takrorlanmaydi)
Manbalar: model, ma'lumot, muhit, kod
Global seed kod tartibiga bog'liq
Bit darajasi uchun: bitta oqim + qulflangan versiyalar
Amaliyotda 2-daraja (statistik) yetarli4. Batafsil misollar
Misollar real numpy/sklearn bilan (Python 3.14).
Misol 1 — random_state ning uch shakli
"""None, son va RandomState obyekti farqi (real numpy/sklearn)."""
import numpy as np
from sklearn.cluster import KMeans
from sklearn.datasets import make_classification
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
def main() -> None:
X, y = make_classification(n_samples=600, n_features=10,
n_informative=5, flip_y=0.2, random_state=0)
print("=== 1. sklearn qaysi turlarni qabul qiladi ===")
turlar = {
"int (42)": 42,
"RandomState": np.random.RandomState(42),
"Generator (default_rng)": np.random.default_rng(42),
"None": None,
}
print(f" {'tur':<26} {'natija'}")
for nom, rs in turlar.items():
try:
RandomForestClassifier(n_estimators=5, random_state=rs,
n_jobs=1).fit(X, y)
print(f" {nom:<26} qabul qilindi")
except Exception as xato:
print(f" {nom:<26} {type(xato).__name__}")
print(" DIQQAT: yangi numpy Generator QABUL QILINMAYDI")
print("\n=== 2. random_state=None ===")
ballar = []
for _ in range(12):
m = RandomForestClassifier(n_estimators=30, random_state=None,
n_jobs=1).fit(X, y)
ballar.append(round(float(m.predict_proba(X[:1])[0, 1]), 6))
# qiymatlarning O'ZINI chop etmaymiz - ular har yurishda boshqa
print(" 12 marta fit qilindi")
print(f" hammasi bir xilmi: {len(set(ballar)) == 1}")
print("\n=== 3. random_state=butun son ===")
ballar = []
for _ in range(3):
m = RandomForestClassifier(n_estimators=30, random_state=42,
n_jobs=1).fit(X, y)
ballar.append(round(float(m.predict_proba(X[:1])[0, 1]), 6))
print(f" uch marta fit: {ballar}")
print(f" bir xilmi: {len(set(ballar)) == 1}")
print("\n=== 4. random_state=RandomState obyekti ===")
rs = np.random.RandomState(42)
ballar = []
for _ in range(3):
m = RandomForestClassifier(n_estimators=30, random_state=rs,
n_jobs=1).fit(X, y)
ballar.append(round(float(m.predict_proba(X[:1])[0, 1]), 6))
print(f" uch marta fit: {ballar}")
print(f" bir xilmi: {len(set(ballar)) == 1}")
print(" obyekt HOLATI ilgarilaydi - har fit boshqa")
print("\n=== 5. Obyektni har safar qayta yaratish ===")
ballar = []
for _ in range(3):
rs2 = np.random.RandomState(42) # HAR SAFAR yangi
m = RandomForestClassifier(n_estimators=30, random_state=rs2,
n_jobs=1).fit(X, y)
ballar.append(round(float(m.predict_proba(X[:1])[0, 1]), 6))
print(f" uch marta fit: {ballar}")
print(f" bir xilmi: {len(set(ballar)) == 1}")
print("\n=== 6. Boshqa obyektlarda ham bir xil qoida ===")
print(f" {'obyekt':<22} {'son bilan':>11} {'obyekt bilan':>14}")
for nom, yasovchi in [
("train_test_split",
lambda rs_: train_test_split(X, y, test_size=0.3,
random_state=rs_)[0][0, 0]),
("KMeans",
lambda rs_: KMeans(n_clusters=3, n_init=3, random_state=rs_)
.fit(X).cluster_centers_[0, 0])]:
son_natijalari = {round(float(yasovchi(7)), 8) for _ in range(3)}
ob = np.random.RandomState(7)
obyekt_natijalari = {round(float(yasovchi(ob)), 8)
for _ in range(3)}
print(f" {nom:<22} {str(len(son_natijalari) == 1):>11} "
f"{str(len(obyekt_natijalari) == 1):>14}")
print(" ⭐ Takrorlanuvchanlik uchun BUTUN SON bering")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. sklearn qaysi turlarni qabul qiladi ===
tur natija
int (42) qabul qilindi
RandomState qabul qilindi
Generator (default_rng) InvalidParameterError
None qabul qilindi
DIQQAT: yangi numpy Generator QABUL QILINMAYDI
=== 2. random_state=None ===
12 marta fit qilindi
hammasi bir xilmi: False
=== 3. random_state=butun son ===
uch marta fit: [0.066667, 0.066667, 0.066667]
bir xilmi: True
=== 4. random_state=RandomState obyekti ===
uch marta fit: [0.066667, 0.133333, 0.1]
bir xilmi: False
obyekt HOLATI ilgarilaydi - har fit boshqa
=== 5. Obyektni har safar qayta yaratish ===
uch marta fit: [0.066667, 0.066667, 0.066667]
bir xilmi: True
=== 6. Boshqa obyektlarda ham bir xil qoida ===
obyekt son bilan obyekt bilan
train_test_split True False
KMeans True False
⭐ Takrorlanuvchanlik uchun BUTUN SON beringNima ko'rsatdi: 2.1-bo'lim.
Misol 2 — Global seed nima uchun yetarli emas
"""np.random.seed va kod tartibi (real numpy/sklearn)."""
import numpy as np
from sklearn.datasets import make_classification
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import StratifiedKFold, cross_val_score
def main() -> None:
X, y = make_classification(n_samples=500, n_features=10,
n_informative=5, flip_y=0.2, random_state=0)
print("=== 1. Global seed va ketma-ket chaqiruvlar ===")
np.random.seed(42)
ballar = []
for i in range(3):
m = RandomForestClassifier(n_estimators=25, n_jobs=1).fit(X, y)
ballar.append(round(float(m.predict_proba(X[:1])[0, 1]), 6))
print(f" bitta seed, uch fit: {ballar}")
print(f" bir xilmi: {len(set(ballar)) == 1}")
print(" global holat HAR chaqiruvda ilgarilaydi")
print("\n=== 2. Har chaqiruvdan oldin qayta seed ===")
ballar = []
for i in range(3):
np.random.seed(42) # har safar qaytadan
m = RandomForestClassifier(n_estimators=25, n_jobs=1).fit(X, y)
ballar.append(round(float(m.predict_proba(X[:1])[0, 1]), 6))
print(f" uch fit: {ballar}")
print(f" bir xilmi: {len(set(ballar)) == 1}")
print(" ishlaydi, lekin mo'rt - har joyda yozish kerak")
print("\n=== 3. Kod tartibi o'zgarganda ===")
def tartib_a():
np.random.seed(42)
_ = np.random.rand(10) # qo'shimcha chaqiruv
m = RandomForestClassifier(n_estimators=25, n_jobs=1).fit(X, y)
return round(float(m.predict_proba(X[:1])[0, 1]), 6)
def tartib_b():
np.random.seed(42)
m = RandomForestClassifier(n_estimators=25, n_jobs=1).fit(X, y)
_ = np.random.rand(10) # keyin chaqirilgan
return round(float(m.predict_proba(X[:1])[0, 1]), 6)
print(f" tartib A (avval rand): {tartib_a()}")
print(f" tartib B (keyin rand): {tartib_b()}")
print(f" bir xilmi: {tartib_a() == tartib_b()}")
print(" bitta qatorni ko'chirish natijani o'zgartiradi")
print("\n=== 4. Aniq random_state bilan ===")
def aniq_a():
_ = np.random.rand(10)
m = RandomForestClassifier(n_estimators=25, random_state=42,
n_jobs=1).fit(X, y)
return round(float(m.predict_proba(X[:1])[0, 1]), 6)
def aniq_b():
m = RandomForestClassifier(n_estimators=25, random_state=42,
n_jobs=1).fit(X, y)
_ = np.random.rand(10)
return round(float(m.predict_proba(X[:1])[0, 1]), 6)
print(f" tartib A: {aniq_a()}")
print(f" tartib B: {aniq_b()}")
print(f" bir xilmi: {aniq_a() == aniq_b()}")
print("\n=== 5. CV da ham shunday ===")
cv_yoq = StratifiedKFold(4, shuffle=True) # random_state yo'q
cv_bor = StratifiedKFold(4, shuffle=True, random_state=0)
m = RandomForestClassifier(n_estimators=25, random_state=0, n_jobs=1)
yoq = {round(float(cross_val_score(m, X, y, cv=cv_yoq,
scoring="roc_auc").mean()), 6)
for _ in range(3)}
bor = {round(float(cross_val_score(m, X, y, cv=cv_bor,
scoring="roc_auc").mean()), 6)
for _ in range(3)}
print(f" cv random_state siz: {len(yoq)} ta turli natija")
print(f" cv random_state bilan: {len(bor)} ta turli natija")
print(" ⭐ Global seedga tayanmang - har obyektga aniq son bering")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Global seed va ketma-ket chaqiruvlar ===
bitta seed, uch fit: [0.12, 0.04, 0.0]
bir xilmi: False
global holat HAR chaqiruvda ilgarilaydi
=== 2. Har chaqiruvdan oldin qayta seed ===
uch fit: [0.12, 0.12, 0.12]
bir xilmi: True
ishlaydi, lekin mo'rt - har joyda yozish kerak
=== 3. Kod tartibi o'zgarganda ===
tartib A (avval rand): 0.04
tartib B (keyin rand): 0.12
bir xilmi: False
bitta qatorni ko'chirish natijani o'zgartiradi
=== 4. Aniq random_state bilan ===
tartib A: 0.12
tartib B: 0.12
bir xilmi: True
=== 5. CV da ham shunday ===
cv random_state siz: 3 ta turli natija
cv random_state bilan: 1 ta turli natija
⭐ Global seedga tayanmang - har obyektga aniq son beringNima ko'rsatdi: 2.3-bo'lim.
Misol 3 — Oqimlar, ma'lumot tartibi va suzuvchi nuqta
"""Muhit va ma'lumotdan kelgan farqlar (real numpy/sklearn)."""
import numpy as np
from sklearn.datasets import make_classification
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
def main() -> None:
print("=== 1. Suzuvchi nuqta qo'shish assotsiativ emas ===")
rng = np.random.default_rng(0)
a = rng.normal(0, 1, 100_000).astype(np.float64)
ketma_ket = float(np.sum(a))
ikki_qism = float(np.sum(a[:50_000]) + np.sum(a[50_000:]))
tort_qism = float(sum(np.sum(a[i::4]) for i in range(4)))
print(f" ketma-ket: {ketma_ket:.17f}")
print(f" ikki qism: {ikki_qism:.17f}")
print(f" to'rt qism: {tort_qism:.17f}")
print(f" ketma-ket va ikki qism bir xilmi: "
f"{ketma_ket == ikki_qism}")
print(f" farq: {abs(ketma_ket - ikki_qism):.3e}")
print("\n=== 2. Farq qanchalik katta ===")
print(f" nisbiy farq: "
f"{abs(ketma_ket - ikki_qism) / abs(ketma_ket):.3e}")
print(" bu 1e-12 darajasida - xulosaga ta'sir qilmaydi")
print(" lekin BIT darajasidagi tenglikni buzadi")
print("\n=== 3. Ma'lumot tartibi ta'siri ===")
X, y = make_classification(n_samples=1000, n_features=12,
n_informative=6, flip_y=0.2, random_state=0)
model = make_pipeline(StandardScaler(),
LogisticRegression(max_iter=3000))
asl = model.fit(X, y).predict_proba(X[:3])[:, 1]
aralash = np.random.default_rng(0).permutation(len(y))
teskari = model.fit(X[aralash], y[aralash]).predict_proba(X[:3])[:, 1]
print(f" asl tartib: {np.round(asl, 12).tolist()}")
print(f" aralash tartib: {np.round(teskari, 12).tolist()}")
print(f" aynan bir xil: {np.array_equal(asl, teskari)}")
print(f" maksimal farq: {np.abs(asl - teskari).max():.3e}")
print("\n=== 4. Teng ballar va argmax ===")
ballar = np.array([0.3, 0.7, 0.7, 0.2])
print(f" ballar: {ballar.tolist()}")
print(f" argmax: {int(np.argmax(ballar))} (BIRINCHI maksimum)")
print(f" teskari tartibda argmax: "
f"{len(ballar) - 1 - int(np.argmax(ballar[::-1]))}")
print(" teng ballarda tartib natijani belgilaydi")
print("\n=== 5. Amaliy xulosa ===")
print(f" {'daraja':<28} {'talab':<34}")
print(f" {'1: bit darajasida':<28} "
f"{'bitta oqim + versiya + seed':<34}")
print(f" {'2: statistik (1e-6)':<28} "
f"{'seed + versiya':<34}")
print(f" {'3: ilmiy':<28} "
f"{'kod + ma_lumot + hujjat':<34}")
print(" ⭐ Kundalik ishda 2-daraja yetarli")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Suzuvchi nuqta qo'shish assotsiativ emas ===
ketma-ket: -90.82507731206121093
ikki qism: -90.82507731206121093
to'rt qism: -90.82507731206115409
ketma-ket va ikki qism bir xilmi: True
farq: 0.000e+00
=== 2. Farq qanchalik katta ===
nisbiy farq: 0.000e+00
bu 1e-12 darajasida - xulosaga ta'sir qilmaydi
lekin BIT darajasidagi tenglikni buzadi
=== 3. Ma'lumot tartibi ta'siri ===
asl tartib: [0.864456217718, 0.198158166214, 0.609747750019]
aralash tartib: [0.864456217718, 0.198158166214, 0.609747750019]
aynan bir xil: False
maksimal farq: 2.220e-16
=== 4. Teng ballar va argmax ===
ballar: [0.3, 0.7, 0.7, 0.2]
argmax: 1 (BIRINCHI maksimum)
teskari tartibda argmax: 2
teng ballarda tartib natijani belgilaydi
=== 5. Amaliy xulosa ===
daraja talab
1: bit darajasida bitta oqim + versiya + seed
2: statistik (1e-6) seed + versiya
3: ilmiy kod + ma_lumot + hujjat
⭐ Kundalik ishda 2-daraja yetarliNima ko'rsatdi: 2.2, 2.4, 2.6-bo'limlar.
Misol 4 — Takrorlanuvchan tajriba tuzilmasi
"""Seed, versiya va metama'lumot bir joyda (real numpy/sklearn)."""
import sys
import numpy as np
import sklearn
from sklearn.datasets import make_classification
from sklearn.ensemble import HistGradientBoostingClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import (RandomizedSearchCV,
StratifiedKFold, cross_val_score,
train_test_split)
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from scipy.stats import loguniform, randint
SEED = 42
def tajriba(seed: int) -> dict:
"""Butun tajriba BITTA seed bilan boshqariladi."""
X, y = make_classification(n_samples=1500, n_features=15,
n_informative=7, flip_y=0.18,
class_sep=0.9, random_state=seed)
Xtr, Xte, ytr, yte = train_test_split(X, y, test_size=0.25,
stratify=y, random_state=seed)
cv = StratifiedKFold(4, shuffle=True, random_state=seed)
taqsimot = {"learning_rate": loguniform(0.02, 0.4),
"max_leaf_nodes": randint(4, 40)}
qidiruv = RandomizedSearchCV(
HistGradientBoostingClassifier(max_iter=150, early_stopping=False,
random_state=seed),
taqsimot, n_iter=8, cv=cv, scoring="roc_auc",
random_state=seed, n_jobs=1).fit(Xtr, ytr)
from sklearn.metrics import roc_auc_score
test = roc_auc_score(yte, qidiruv.predict_proba(Xte)[:, 1])
return {"cv": round(float(qidiruv.best_score_), 6),
"test": round(float(test), 6),
"lr": round(float(qidiruv.best_params_["learning_rate"]), 6),
"barglar": int(qidiruv.best_params_["max_leaf_nodes"])}
def main() -> None:
print("=== 1. Muhit ===")
metama = {"seed": SEED,
"python": sys.version.split()[0],
"numpy": np.__version__,
"sklearn": sklearn.__version__}
for kalit, qiymat in metama.items():
print(f" {kalit:<10} {qiymat}")
print("\n=== 2. Bir xil seed bilan uch marta ===")
natijalar = [tajriba(SEED) for _ in range(3)]
print(f" {'urinish':>9} {'CV':>10} {'test':>10} {'lr':>10} "
f"{'barglar':>9}")
for i, n in enumerate(natijalar, 1):
print(f" {i:>9} {n['cv']:>10.6f} {n['test']:>10.6f} "
f"{n['lr']:>10.6f} {n['barglar']:>9}")
bir_xil = all(n == natijalar[0] for n in natijalar)
print(f" hammasi bir xil: {bir_xil}")
print("\n=== 3. Turli seed bilan ===")
print(f" {'seed':>6} {'CV':>10} {'test':>10} {'lr':>10} "
f"{'barglar':>9}")
turli = []
for seed in [0, 1, 42]:
n = tajriba(seed)
turli.append(n)
print(f" {seed:>6} {n['cv']:>10.6f} {n['test']:>10.6f} "
f"{n['lr']:>10.6f} {n['barglar']:>9}")
cv_lar = [n["cv"] for n in turli]
print(f" CV tarqoqligi: {max(cv_lar) - min(cv_lar):.4f}")
print(" (bu ma'lumot va bo'linish farqidan - 18.3-dars)")
print("\n=== 4. Natija bilan birga saqlanadigan yozuv ===")
yozuv = {**metama, "natija": natijalar[0], "n_jobs": 1,
"oqimlar": "OMP_NUM_THREADS=1"}
print(f" {'kalit':<12} {'qiymat'}")
for kalit, qiymat in yozuv.items():
print(f" {kalit:<12} {qiymat}")
print("\n=== 5. Nazorat ro'yxati ===")
tekshiruvlar = [
("bitta SEED o'zgaruvchisi", True),
("har obyektga random_state", True),
("global np.random.seed ishlatilmagan", True),
("n_jobs qat'iy (1)", True),
("versiyalar yozilgan", "sklearn" in metama),
("natija bilan birga saqlanadi", "natija" in yozuv),
]
print(f" {'tekshiruv':<36} {'holat':>7}")
for nom, holat in tekshiruvlar:
print(f" {nom:<36} {'OK' if holat else 'XATO':>7}")
print(" ⭐ Seed - konfiguratsiya: bir joyda, natija bilan saqlanadi")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Muhit ===
seed 42
python 3.14.5
numpy 2.5.3
sklearn 1.9.1
=== 2. Bir xil seed bilan uch marta ===
urinish CV test lr barglar
1 0.852930 0.881971 0.173929 33
2 0.852930 0.881971 0.173929 33
3 0.852930 0.881971 0.173929 33
hammasi bir xil: True
=== 3. Turli seed bilan ===
seed CV test lr barglar
0 0.870897 0.861792 0.138471 27
1 0.845521 0.862708 0.096268 32
42 0.852930 0.881971 0.173929 33
CV tarqoqligi: 0.0254
(bu ma'lumot va bo'linish farqidan - 18.3-dars)
=== 4. Natija bilan birga saqlanadigan yozuv ===
kalit qiymat
seed 42
python 3.14.5
numpy 2.5.3
sklearn 1.9.1
natija {'cv': 0.85293, 'test': 0.881971, 'lr': 0.173929, 'barglar': 33}
n_jobs 1
oqimlar OMP_NUM_THREADS=1
=== 5. Nazorat ro'yxati ===
tekshiruv holat
bitta SEED o'zgaruvchisi OK
har obyektga random_state OK
global np.random.seed ishlatilmagan OK
n_jobs qat'iy (1) OK
versiyalar yozilgan OK
natija bilan birga saqlanadi OK
⭐ Seed - konfiguratsiya: bir joyda, natija bilan saqlanadiNima ko'rsatdi: 2.5, 2.6-bo'limlar.
5. To'g'ri va noto'g'ri tushunishlar
| Noto'g'ri fikr | To'g'risi |
|---|---|
"np.random.seed(42) yetarli" |
Kod tartibiga bog'liq |
"random_state=rng takrorlanuvchan" |
Obyekt holati ilgarilaydi |
| "Seed qo'ysam bit darajasida bir xil" | Oqimlar ham ta'sir qiladi |
| "Versiya muhim emas" | Natijani o'zgartiradi |
| "Ma'lumot tartibi ahamiyatsiz" | Teng ballar va yig'indi tartibi |
"n_jobs=-1 xavfsiz" |
Bit darajasidagi tenglikni buzadi |
| "Seedni saqlash shart emas" | Natija bilan birga saqlanadi |
| "Bit darajasi har doim kerak" | 2-daraja odatda yetarli |
6. Keng tarqalgan xatolar va yechimlari
1. Global seedga tayanish
np.random.seed(42); model = RandomForestClassifier() # ⚠️
model = RandomForestClassifier(random_state=SEED) # ✅2. Obyekt berish
rs = np.random.RandomState(42)
RandomForestClassifier(random_state=rs) # har fit boshqa # ⚠️
RandomForestClassifier(random_state=42) # ✅3. CV da random_state yo'q
StratifiedKFold(5, shuffle=True) # ⚠️
StratifiedKFold(5, shuffle=True, random_state=SEED) # ✅4. Har joyda turli seed
train_test_split(..., random_state=1); KFold(..., random_state=7) # ⚠️
SEED = 42 # bitta joyda, hamma joyga uzatiladi # ✅5. Versiyalarni qulflamaslik
# requirements.txt: scikit-learn # ⚠️
# requirements.txt: scikit-learn==1.9.1 # ✅6. Seedni saqlamaslik
print(f"AUC: {ball}") # ⚠️
print(f"AUC: {ball} (seed={SEED}, sklearn={sklearn.__version__})") # ✅7. Testlarda n_jobs=-1
def test_model(): m = RF(n_jobs=-1, random_state=0) # ⚠️
def test_model(): m = RF(n_jobs=1, random_state=0) # ✅7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 18.3-dars (o'tilgan): CV dispersiyasi
- 18.11-dars (o'tilgan): Validatsiyaga overfitting
- 19.6-dars (o'tilgan): Model saqlash
- 19.8-dars: Diagnostika
- 29-qism: MLOps
8. Eng yaxshi amaliyotlar
Bitta
SEEDo'zgaruvchisi.Har obyektga aniq son.
Global seedga tayanmang.
CV ga ham
random_state.Versiyalarni qulflang.
Seedni natija bilan saqlang.
Testlarda bitta oqim.
Qaysi daraja kerakligini biling.
9. Amaliy topshiriq
Vazifa 1: Bashorat qiling
1. # random_state ning uch shakli?
2. # obyekt berilsa nima bo'ladi?
3. # global seed nima uchun mo'rt?
4. # tasodifiylikning to'rt manbai?
5. # oqimlar nima uchun ta'sir qiladi?
6. # bit darajasi uchun nima kerak?
7. # 2-daraja nima?
8. # amaliyotda qaysi daraja?
9. # versiyalarni qanday qulflash?
10. # seed qayerda saqlanadi?
11. # teng ballar nima uchun muhim?
12. # testlarda n_jobs qancha?Javoblar
None, butun son,RandomStateobyekti- Holati ilgarilaydi — har fit boshqa
- Kod tartibiga bog'liq
- Model, ma'lumot, muhit, kod
- Suzuvchi nuqta yig'indisi tartibi
- Bitta oqim + versiya + seed
- Statistik (1e-6 farq)
- 2-daraja
==bilan, lock fayl, konteyner- Natija bilan birga
argmaxtartibga bog'liq- 1
Vazifa 2: Xatolarni tuzating
1. np.random.seed(42); model = RandomForestClassifier()
2. rs = np.random.RandomState(42)
RandomForestClassifier(random_state=rs)
3. StratifiedKFold(5, shuffle=True)
4. train_test_split(..., random_state=1); KFold(..., random_state=7)
5. print(f"AUC: {ball}")Javoblar
1. model = RandomForestClassifier(random_state=SEED)
2. RandomForestClassifier(random_state=42)
3. StratifiedKFold(5, shuffle=True, random_state=SEED)
4. SEED = 42 # bitta joyda
5. print(f"AUC: {ball} (seed={SEED}, sklearn={sklearn.__version__})")Vazifa 3: Uch shakl
Modellang:
None- Butun son
- Obyekt
- Qayta yaratish
Vazifa 4: Global seed
Modellang:
- Ketma-ket
- Qayta seed
- Kod tartibi
- Aniq
random_state
Vazifa 5: Muhit
Modellang:
- Assotsiativlik
- Farq kattaligi
- Ma'lumot tartibi
- Teng ballar
Vazifa 6: Tuzilma
Modellang:
- Muhit
- Bir xil seed
- Turli seed
- Yozuv
Vazifa 7: O'ylash
Hamkasbingiz: "Men random_state=42 ni hamma joyga qo'ydim, lekin hamkasbimda boshqa natija chiqyapti." Ikkalangizda ham bir xil kod va bir xil ma'lumot. Qanday tekshirasiz?
Javob
Qisqa javob: ketma-ket to'rtta qatlamni tekshiring: versiyalar → oqimlar → ma'lumot → kod. Eng ehtimoliy sabab — kutubxona versiyalari.
1. Tekshirish tartibi
# 1-qadam: versiyalar
import sys, numpy, scipy, sklearn, pandas, joblib
for m in (sys, numpy, scipy, sklearn, pandas, joblib):
print(m.__name__, getattr(m, "__version__", sys.version.split()[0]))Ikkalangizning chiqishini solishtiring. Farq bo'lsa — sabab topildi.
2-qadam: oqimlar
import os
from threadpoolctl import threadpool_info
print({k: os.environ.get(k) for k in
("OMP_NUM_THREADS", "OPENBLAS_NUM_THREADS", "MKL_NUM_THREADS")})
print([(i["user_api"], i["num_threads"]) for i in threadpool_info()])Yadrolar soni yoki BLAS kutubxonasi (OpenBLAS/MKL) farq qilishi mumkin.
3-qadam: ma'lumot
import hashlib
print(hashlib.sha256(pd.util.hash_pandas_object(df, index=True).values
.tobytes()).hexdigest()[:16])
print(df.shape, list(df.columns), df.dtypes.to_dict())"Bir xil ma'lumot" ko'pincha bir xil emas: ustun tartibi, dtype yoki qatorlar tartibi farq qiladi.
4-qadam: kod
git status --short
git rev-parse HEAD2. Farq kattaligini o'lchang
farq = abs(mening_ballim - uning_balli)| Farq | Ehtimoliy sabab |
|---|---|
< 1e-10 |
Oqimlar / BLAS — e'tiborsiz qoldirsa bo'ladi |
1e-6 … 1e-3 |
Versiya farqi yoki ma'lumot tartibi |
> 0.001 |
Seed qo'yilmagan joy bor yoki ma'lumot boshqa |
3. Seed qo'yilmagan joyni topish
for nom, ob in quvur.get_params(deep=True).items():
if nom.endswith("random_state"):
print(nom, "=", ob)None qolgan joyni qidiring — ko'pincha CalibratedClassifierCV, KMeans yoki SelectFromModel ichidagi model unutiladi.
4. Umumiy muhit yaratish
uv lock # yoki: pip freeze > requirements.lockKeyin ikkalangiz ham aynan shu qulfdan o'rnating. Eng ishonchlisi — bitta Docker tasviri.
5. Xulosa
- Versiyalarni birinchi solishtiring
- Oqimlar sozlamasini tekshiring
- Ma'lumot xeshini solishtiring
- Farq kattaligi sababni ko'rsatadi
- Umumiy muhit (lock yoki konteyner)
Nimani mustahkamlaydi: 2.2, 2.5-bo'limlar.
Xulosa
Bu darsda takrorlanuvchanlikni o'rgandik.
Eng muhim uch fikr:
random_statega butun son bering, obyekt emas. Butun son harfitda ayni seed dan boshlanadi;RandomStateobyekti esa holatini ilgarilatadi va harfitboshqa natija beradi (sklearn 1.9 yanginp.random.default_rng()ni umuman qabul qilmaydi).np.random.seed()ga tayanish yanada mo'rt: u kod tartibiga bog'liq, ya'ni bitta qatorni ko'chirsangiz natija o'zgaradi.Tasodifiylikning to'rt manbai bor: model, ma'lumot, muhit, kod. Seed faqat birinchisini boshqaradi. Oqimlar soni suzuvchi nuqta yig'indisi tartibini o'zgartiradi va bit darajasidagi tenglikni buzadi; kutubxona versiyasi esa natijani sezilarli o'zgartirishi mumkin. Shuning uchun versiyalarni qulflash seed qo'yish kabi muhim.
Qaysi daraja kerakligini biling. Bit darajasidagi tenglik bitta oqim va qotirilgan muhitni talab qiladi — u testlar va nashr uchun. Kundalik ishda statistik (1e-6 atrofida) takrorlanuvchanlik yetarli. Va har qanday holatda seedni, versiyalarni va
n_jobsni natija bilan birga saqlang.
Keyingi darsda diagnostika vositalarini ko'ramiz: check_estimator, sklearn.set_config, HTML ko'rinish, xato xabarlarini o'qish va quvurdagi nosozlikni topish.
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!