Asosiy qismga o'tish

Tajribalarni kuzatish: MLflow

22-bob 16 kod bloki 4071 so'z

Bu bobdagi kod shu fayllar bilan ishlaydio'z kompyuteringizda ishga tushiring

Payshanba kuni topilgan 0.87

Seshanba kuni model ustida ishladingiz. Parametrlarni o'zgartirdingiz, xususiyat qo'shdingiz, qayta o'qitdingiz. Yana. Yana.

Kunning bir payti ekranda 0.87 chiqdi. Eng yaxshi natija. "Zo'r!" dedingiz va ishni davom ettirdingiz — yana bir necha variant sinab ko'rish uchun.

Kechqurun 0.84 da to'xtadingiz.

Payshanba kuni boshliq so'radi: — Eng yaxshi natijangiz qancha edi?

— 0.87, dedingiz.

— Zo'r. O'shani chiqaraylik.

Va shu payda qorningizda sovuq bir narsa paydo bo'ladi. Chunki siz qaysi sozlama 0.87 berganini eslay olmaysiz.

Daraxtlar soni 200 mi, 400 mi edi? Barg chuqurligi qancha? Xususiyat qo'shgandim — qaysi biri? Jupyter katakchasini qayta ishga tushirgansiz, eski natija ustidan yozilgan.

Ikki kun ish. Natija yo'q. Qaytadan boshlaysiz.

Bu kimningdir aybi emas

Bu hikoyani deyarli har bir ML muhandisi boshidan kechirgan. Va diqqat qiling: bu yerda hech kim beparvolik qilmadi.

Siz yozib borishingiz kerak edi — lekin tajriba paytida odam yozib bormaydi. Fikr ketma-ket keladi: "buni sinab ko'ray... endi buni... voy, qiziq..." Har safar to'xtab, jadvalga o'tib, parametrlarni ko'chirish — fikr oqimini uzadi.

Shuning uchun yechim "ehtiyotkor bo'ling" emas. Yechim — yozib borishni odamdan olib qo'yish.

Kutubxonachini eslang (23-bobda batafsil ko'ramiz): u har kitobni qo'lda daftarga yozmaydi, skaner bor. Bu yerda ham shunday kerak — kod ishga tushganda o'zi yozib qo'ysin.

MLflow aynan shuni qiladi.

Nega qo'lda usullar ishlamaydi

Avval mavjud usullarni ko'rib chiqamiz — ularning har biri sizga tanish bo'lishi mumkin:

python7 qator
import pandas as pd
show(pd.DataFrame([
    {"usul": "Jupyter katakchalari", "muammo": "Oldingi natija ustidan yozib ketiladi"},
    {"usul": "Excel jadvali", "muammo": "Qo'lda to'ldiriladi — unutiladi, xato yoziladi"},
    {"usul": "Fayl nomlari (model_v3_final2)", "muammo": "Qaysi parametr bilan — noma'lum"},
    {"usul": "Jurnal fayllari", "muammo": "Taqqoslash uchun qidirish kerak"},
]))
usulmuammo
Jupyter katakchalariOldingi natija ustidan yozib ketiladi
Excel jadvaliQo'lda to'ldiriladi — unutiladi, xato yoziladi
Fayl nomlari (model_v3_final2)Qaysi parametr bilan — noma'lum
Jurnal fayllariTaqqoslash uchun qidirish kerak

Kerak bo'lgan narsa: har tajriba avtomatik yozilsin — parametrlar, metrikalar, artefaktlar va 2-bobdagi pasport ma'lumotlari.

MLflow nima qiladi

python15 qator
diagramma(
    {
        "O'qitish skripti": (0, 1.4, 2.6, 1.1, "qayta"),
        "mlflow.log_param\nlog_metric, log_artifact": (3.4, 1.4, 3.0, 1.1, "manba"),
        "Kuzatuv ombori\n(fayl yoki server)": (7.2, 1.4, 2.8, 1.1, "saqlash"),
        "Taqqoslash UI\nva API": (7.2, 3.6, 2.8, 1.1, "kuzatuv"),
    },
    [
        ("O'qitish skripti", "mlflow.log_param\nlog_metric, log_artifact"),
        ("mlflow.log_param\nlog_metric, log_artifact", "Kuzatuv ombori\n(fayl yoki server)"),
        ("Kuzatuv ombori\n(fayl yoki server)", "Taqqoslash UI\nva API"),
    ],
    nom="mlflow_oqimi.png", kenglik=12,
    izoh="Skript uch xil narsani yozadi: parametr (kirish), metrika (natija), artefakt (model va fayllar).",
)

Skript uch xil narsani yozadi: parametr (kirish), metrika (natija), artefakt (model va fayllar).

Skript uch xil narsani yozadi: parametr (kirish), metrika (natija), artefakt (model va fayllar).

MLflow da hammasi uchta tushunchaga bo'linadi. Ularni ajratish muhim, chunki har biri boshqa vaqtda paydo bo'ladi.

Ovqat pishirishga o'xshating:

  • Parametr — retseptdagi miqdorlar. Ularni boshlashdan oldin bilasiz: 200 gramm un, 180 daraja, 40 daqiqa.
  • Metrika — tayyor taomning bahosi. Uni oxirida olasiz: mazasi 8/10.
  • Artefakt — taomning o'zi va surati. Fayl.
Tushuncha Nima Qachon ma'lum Misol
Parametr Kirish sozlamasi O'qitishdan oldin n_estimators=150
Metrika Natija, o'lchov O'qitishdan keyin f1=0.8603
Artefakt Fayl: model, grafik O'qitishdan keyin model/

Nega bu ajratish muhim? Chunki savollaringiz shu bo'yicha tuziladi:

"F1 eng yuqori (metrika) bo'lgan tajribada daraxtlar soni (parametr) qancha edi?"

Agar hammasi bitta qopga tashlansa, bunday savol berib bo'lmaydi. Ajratilgan bo'lsa — bu oddiy so'rov.

Parametrni metrika deb yozib yubormang

Eng ko'p uchraydigan chalkashlik: train_size=0.75 ni metrika sifatida yozish.

U son, lekin u natija emas — siz uni o'zingiz tanlagansiz. Metrika deb yozsangiz, "eng yaxshi natija" ro'yxatida u ham paydo bo'ladi va jadvalni chalkashtiradi.

Oddiy qoida: men tanladimmi — parametr. Model menga berdimi — metrika.

python1 qator
python3 -c "import mlflow; print('MLflow', mlflow.__version__)" 2>/dev/null
Chiqish (qaytish kodi 0, 1057 ms)
MLflow 3.16.1

Fayl ombori (`./mlruns`) endi eskirgan

Ko'p darslikda mlflow.set_tracking_uri("file:./mlruns") yoziladi. MLflow 3.x da bu xato beradi:

python2 qator
The filesystem tracking backend is in maintenance mode and will not receive
further updates. Please migrate to a database backend (e.g. 'sqlite:///mlflow.db')

Shuning uchun biz boshidanoq SQLite ishlatamiz. Foydasi ikki tomonlama: eskirgan yo'lga kirmaymiz va lokal ombor serverdagi Postgres bilan bir xil turda bo'ladi — faqat manzil farq qiladi.

Birinchi tajriba

shu faylni yaratingsrc/quvur/kuzatuv.py

python38 qator
"""MLflow bilan tajriba kuzatuvi.

Kitobda kuzatuv ombori LOKAL SQLite faylida — server kerak emas, lekin
ma'lumotlar bazasi imkoniyatlari bor. Ishlab chiqarishda `MLFLOW_TRACKING_URI`
ni Postgres li serverga yo'naltiriladi va KOD O'ZGARMAYDI.
"""
import os
from contextlib import contextmanager
from pathlib import Path
from typing import Any, Iterator

import mlflow


def omborni_sozla(db: str | Path = "mlflow.db",
                  artefakt: str | Path = "mlartefaktlar") -> str:
    """Kuzatuv omborini belgilaydi. Muhit o'zgaruvchisi ustun turadi (11-bob qoidasi)."""
    uri = os.environ.get("MLFLOW_TRACKING_URI")
    if not uri:
        uri = f"sqlite:///{Path(db).absolute()}"
    Path(artefakt).mkdir(parents=True, exist_ok=True)
    mlflow.set_tracking_uri(uri)
    return uri


@contextmanager
def tajriba(nom: str, yugurish: str | None = None,
            teglar: dict[str, str] | None = None) -> Iterator[Any]:
    """Tajriba konteksti. Xato bo'lsa ham yugurish yopiladi va holati yoziladi."""
    mlflow.set_experiment(nom)
    with mlflow.start_run(run_name=yugurish) as r:
        if teglar:
            mlflow.set_tags(teglar)
        try:
            yield r
        except Exception as e:
            mlflow.set_tag("xato", f"{type(e).__name__}: {e}"[:250])
            raise

shu faylni yaratingoqit_mlflow.py

python59 qator
"""MLflow bilan o'qitish: parametr, metrika va artefakt yoziladi."""
import sys
from pathlib import Path

sys.path.insert(0, "src")

import joblib
import mlflow
import pandas as pd
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import f1_score, precision_score, recall_score, roc_auc_score

from quvur.kuzatuv import omborni_sozla, tajriba
from quvur.manifest import fayl_hash
from quvur.takrorlanish import seedni_qulfla

MALUMOT = "../datasets/ijara.csv"
XUS = ["xonalar", "maydon", "qavat", "jami_qavat", "narx_mln", "tavsif_uzunligi",
       "rasmlar_soni", "telefon_takrorlanishi", "kunlik_elonlar", "egasi_tasdiqlangan"]
SEED = 42


def bitta_yugurish(param: dict, nom: str) -> dict:
    seedni_qulfla(SEED)
    d = pd.read_csv(MALUMOT)
    Xtr, Xte, ytr, yte = train_test_split(d[XUS], d["broker"], test_size=0.25,
                                          stratify=d["broker"], random_state=SEED)
    with tajriba("broker-aniqlash", nom, teglar={"model_turi": "random_forest"}):
        mlflow.log_params({**param, "seed": SEED, "oqitish_qatorlari": len(Xtr)})
        # 2-bobdagi pasport: ma'lumot qaysi versiya edi
        mlflow.set_tag("malumot_sha256", fayl_hash(MALUMOT)[:16])

        m = RandomForestClassifier(**param, random_state=SEED, n_jobs=1).fit(Xtr, ytr)
        p, e = m.predict(Xte), m.predict_proba(Xte)[:, 1]
        metrikalar = {
            "f1": float(f1_score(yte, p)),
            "aniqlik": float(precision_score(yte, p)),
            "toliqlik": float(recall_score(yte, p)),
            "auc": float(roc_auc_score(yte, e)),
        }
        mlflow.log_metrics(metrikalar)

        # MUHIM: log_artifact EMAS, log_model.
        # log_artifact oddiy fayl saqlaydi; log_model esa MLmodel tavsifi bilan
        # to'liq model artefaktini yasaydi — 23-bobdagi registr faqat shuni qabul qiladi.
        mlflow.sklearn.log_model(
            m, name="model", input_example=Xtr.head(3),
            # MLflow 3.x sklearn modelini `skops` bilan saqlaydi va daraxt turlarini
            # XAVFSIZLIK sababli rad etadi. Nega — quyidagi izohda.
            skops_trusted_types=["sklearn.tree._tree.Tree"],
        )
        return metrikalar


if __name__ == "__main__":
    print("ombor:", omborni_sozla())
    n = bitta_yugurish({"n_estimators": 150, "min_samples_leaf": 3}, "asosiy")
    print("metrikalar:", {k: round(v, 4) for k, v in n.items()})
matn1 qator
python3 oqit_mlflow.py
Chiqish (qaytish kodi 0, 15279 ms)
ombor: sqlite:////mnt/c/Users/Admin/Desktop/Course Material/MLOps_Kitob/ish/mlflow.db
metrikalar: {'f1': 0.8603, 'aniqlik': 0.8947, 'toliqlik': 0.8285, 'auc': 0.9148}
/home/abulqosim/.local/lib/python3.10/site-packages/requests/__init__.py:113: RequestsDependencyWarning: urllib3 (2.6.3) or chardet (6.0.0.post1)/charset_normalizer (3.4.4) doesn't match a supported version!
  warnings.warn(
2026/09/29 18:24:57 INFO mlflow.agent.hint: Load the `instrumenting-with-mlflow-tracing` skill at /home/abulqosim/.local/lib/python3.10/site-packages/mlflow/assistant/skills/instrumenting-with-mlflow-tracing/SKILL.md before writing any tracing code; it ships with this MLflow install. Set MLFLOW_DISABLE_AGENT_HINT=1 to silence this.
2026/09/29 18:24:58 INFO mlflow.store.db.utils: Creating initial MLflow database tables...
2026/09/29 18:24:58 INFO mlflow.store.db.utils: Updating database tables
2026/09/29 18:25:02 INFO mlflow.tracking.fluent: Experiment with name 'broker-aniqlash' does not exist. Creating a new experiment.
/home/abulqosim/.local/lib/python3.10/site-packages/mlflow/types/utils.py:440: UserWarning: Hint: Inferred schema contains integer column(s). Integer columns in Python cannot represent missing values. If your input data contains missing values at inference time, it will be encoded as floats and will cause a schema enforcement error. The best way to avoid this problem is to infer the model schema based on a realistic data sample (training dataset) that includes missing values. Alternatively, you can declare integer columns as doubles (float64) whenever these columns may have missing values. See `Handling Integers With Missing Values <https://www.mlflow.org/docs/latest/models.html#handling-integers-with-missing-values>`_ for more details.
  warnings.warn(
/home/abulqosim/.local/lib/python3.10/site-packages/mlflow/types/utils.py:440: UserWarning: Hint: Inferred schema contains integer column(s). Integer columns in Python cannot represent missing values. If your input data contains missing values at inference time, it will be encoded as floats and will cause a schema enforcement error. The best way to avoid this problem is to infer the model schema based on a realistic data sample (training dataset) that includes missing values. Alternatively, you can declare integer columns as doubles (float64) whenever these columns may have missing values. See `Handling Integers With Missing Values <https://www.mlflow.org/docs/latest/models.html#handling-integers-with-missing-values>`_ for more details.
  warnings.warn(
2026/09/29 18:25:10 WARNING mlflow.utils.requirements_utils: Found torch version (2.9.1+cu128) contains a local version label (+cu128). MLflow logged a pip requirement for this package as 'torch==2.9.1' without the local version label to make it installable from PyPI. To specify pip requirements containing local version labels, please use `conda_env` or `pip_requirements`.

Yozilganini tekshiramiz — MLflow ning o'z API si orqali:

python12 qator
python3 -c "
import sys; sys.path.insert(0, 'src')
import mlflow
from quvur.kuzatuv import omborni_sozla
omborni_sozla()
y = mlflow.search_runs(experiment_names=['broker-aniqlash'])
print('yugurishlar:', len(y))
ustunlar = [c for c in y.columns if c.startswith(('params.','metrics.','tags.malumot'))]
print()
for c in sorted(ustunlar):
    print(f'  {c:36} {y.iloc[0][c]}')
"
Chiqish (qaytish kodi 0, 1836 ms)
yugurishlar: 1

  metrics.aniqlik                      0.8947368421052632
  metrics.auc                          0.9147708787977373
  metrics.f1                           0.8603406326034063
  metrics.toliqlik                     0.8284910965323337
  params.min_samples_leaf              3
  params.n_estimators                  150
  params.oqitish_qatorlari             9000
  params.seed                          42
  tags.malumot_sha256                  03dbeed95e47e74c
/home/abulqosim/.local/lib/python3.10/site-packages/requests/__init__.py:113: RequestsDependencyWarning: urllib3 (2.6.3) or chardet (6.0.0.post1)/charset_normalizer (3.4.4) doesn't match a supported version!
  warnings.warn(
2026/09/29 18:25:12 INFO mlflow.agent.hint: Load the `instrumenting-with-mlflow-tracing` skill at /home/abulqosim/.local/lib/python3.10/site-packages/mlflow/assistant/skills/instrumenting-with-mlflow-tracing/SKILL.md before writing any tracing code; it ships with this MLflow install. Set MLFLOW_DISABLE_AGENT_HINT=1 to silence this.

Bitta chaqiruv bilan hamma narsa saqlandi: parametrlar, to'rt metrika, ma'lumot hash i va model.

Daraxt modellari uchun `skops_trusted_types` kerak

MLflow 3.x sklearn modellarini skops formatida saqlaydi va daraxtga asoslangan modellarni sukut bo'yicha rad etadi:

matn2 qator
The saved sklearn model references untrusted types...
Untrusted types found in the file: ['sklearn.tree._tree.Tree']

Bu bezorilik emas, xavfsizlik chorasi. sklearn.tree._tree.Tree tugun indekslarini xom massivda saqlaydi va sklearn ularni chegara tekshiruvisiz ishlatadi. Buzib yozilgan fayl .predict() chaqirilganda jarayonni yiqitishi yoki begona xotirani o'qishi mumkin.

Shuning uchun o'zingiz yaratgan modelga skops_trusted_types=["sklearn.tree._tree.Tree"] beriladi. Tashqaridan kelgan model fayliga esa bu ishonchni bermang — bu 26-bobdagi pickle xavfining aynan o'sha turdagi muammosi.

`log_artifact` va `log_model` — bir xil emas

mlflow.log_artifact("model.joblib") shunchaki faylni yuklaydi. MLflow uning ichida nima borligini bilmaydi.

mlflow.sklearn.log_model(m, name="model") esa MLmodel tavsifini yasaydi: qaysi kutubxona, qanday kirish shakli, qanday muhit kerak. 23-bobdagi registr faqat shunday artefaktni qabul qiladi — log_artifact bilan saqlangan modelni ro'yxatga olib bo'lmaydi.

Bir necha tajribani taqqoslash

Endi bob boshidagi hikoyaga qaytamiz. Seshanba kuni siz to'rt variantni sinab ko'rgan edingiz va payshanbaga qadar qaysi biri 0.87 berganini unutdingiz.

Bu safar boshqacha bo'ladi. To'rt variantni ishga tushiramiz — lekin hech narsani yozib olmaymiz, hech qayerga ko'chirmaymiz. Faqat ishga tushiramiz:

python15 qator
python3 -c "
import sys; sys.path.insert(0, 'src')
sys.argv = ['x']
exec(open('oqit_mlflow.py').read().split('if __name__')[0])
omborni_sozla()
VARIANTLAR = [
    ({'n_estimators': 30,  'min_samples_leaf': 1},  'kichik-30'),
    ({'n_estimators': 150, 'min_samples_leaf': 3},  'asosiy'),
    ({'n_estimators': 400, 'min_samples_leaf': 3},  'katta-400'),
    ({'n_estimators': 150, 'min_samples_leaf': 20}, 'sodda-barg20'),
]
for p, nom in VARIANTLAR:
    m = bitta_yugurish(p, nom)
    print(f\"  {nom:14} F1={m['f1']:.4f}  AUC={m['auc']:.4f}\")
"
Chiqish (qaytish kodi 0, 36538 ms)
  kichik-30      F1=0.8585  AUC=0.9156
  asosiy         F1=0.8603  AUC=0.9148
  katta-400      F1=0.8583  AUC=0.9152
  sodda-barg20   F1=0.8630  AUC=0.9139
/home/abulqosim/.local/lib/python3.10/site-packages/requests/__init__.py:113: RequestsDependencyWarning: urllib3 (2.6.3) or chardet (6.0.0.post1)/charset_normalizer (3.4.4) doesn't match a supported version!
  warnings.warn(
2026/09/29 18:25:15 INFO mlflow.agent.hint: Load the `instrumenting-with-mlflow-tracing` skill at /home/abulqosim/.local/lib/python3.10/site-packages/mlflow/assistant/skills/instrumenting-with-mlflow-tracing/SKILL.md before writing any tracing code; it ships with this MLflow install. Set MLFLOW_DISABLE_AGENT_HINT=1 to silence this.
/home/abulqosim/.local/lib/python3.10/site-packages/mlflow/types/utils.py:440: UserWarning: Hint: Inferred schema contains integer column(s). Integer columns in Python cannot represent missing values. If your input data contains missing values at inference time, it will be encoded as floats and will cause a schema enforcement error. The best way to avoid this problem is to infer the model schema based on a realistic data sample (training dataset) that includes missing values. Alternatively, you can declare integer columns as doubles (float64) whenever these columns may have missing values. See `Handling Integers With Missing Values <https://www.mlflow.org/docs/latest/models.html#handling-integers-with-missing-values>`_ for more details.
  warnings.warn(
/home/abulqosim/.local/lib/python3.10/site-packages/mlflow/types/utils.py:440: UserWarning: Hint: Inferred schema contains integer column(s). Integer columns in Python cannot represent missing values. If your input data contains missing values at inference time, it will be encoded as floats and will cause a schema enforcement error. The best way to avoid this problem is to infer the model schema based on a realistic data sample (training dataset) that includes missing values. Alternatively, you can declare integer columns as doubles (float64) whenever these columns may have missing values. See `Handling Integers With Missing Values <https://www.mlflow.org/docs/latest/models.html#handling-integers-with-missing-values>`_ for more details.
  warnings.warn(
2026/09/29 18:25:24 WARNING mlflow.utils.requirements_utils: Found torch version (2.9.1+cu128) contains a local version label (+cu128). MLflow logged a pip requirement for this package as 'torch==2.9.1' without the local version label to make it installable from PyPI. To specify pip requirements containing local version labels, please use `conda_env` or `pip_requirements`.
/home/abulqosim/.local/lib/python3.10/site-packages/mlflow/types/utils.py:440: UserWarning: Hint: Inferred schema contains integer column(s). Integer columns in Python cannot represent missing values. If your input data contains missing values at inference time, it will be encoded as floats and will cause a schema enforcement error. The best way to avoid this problem is to infer the model schema based on a realistic data sample (training dataset) that includes missing values. Alternatively, you can declare integer columns as doubles (float64) whenever these columns may have missing values. See `Handling Integers With Missing Values <https://www.mlflow.org/docs/latest/models.html#handling-integers-with-missing-values>`_ for more details.
  warnings.warn(
/home/abulqosim/.local/lib/python3.10/site-packages/mlflow/types/utils.py:440: UserWarning: Hint: Inferred schema contains integer column(s). Integer columns in Python cannot represent missing values. If your input data contains missing values at inference time, it will be encoded as floats and will cause a schema enforcement error. The best way to avoid this problem is to infer the model schema based on a realistic data sample (training dataset) that includes missing values. Alternatively, you can declare integer columns as doubles (float64) whenever these columns may have missing values. See `Handling Integers With Missing Values <https://www.mlflow.org/docs/latest/models.html#handling-integers-with-missing-values>`_ for more details.
  warnings.warn(
2026/09/29 18:25:31 WARNING mlflow.utils.requirements_utils: Found torch version (2.9.1+cu128) contains a local version label (+cu128). MLflow logged a pip requirement for this package as 'torch==2.9.1' without the local version label to make it installable from PyPI. To specify pip requirements containing local version labels, please use `conda_env` or `pip_requirements`.
/home/abulqosim/.local/lib/python3.10/site-packages/mlflow/types/utils.py:440: UserWarning: Hint: Inferred schema contains integer column(s). Integer columns in Python cannot represent missing values. If your input data contains missing values at inference time, it will be encoded as floats and will cause a schema enforcement error. The best way to avoid this problem is to infer the model schema based on a realistic data sample (training dataset) that includes missing values. Alternatively, you can declare integer columns as doubles (float64) whenever these columns may have missing values. See `Handling Integers With Missing Values <https://www.mlflow.org/docs/latest/models.html#handling-integers-with-missing-values>`_ for more details.
  warnings.warn(
/home/abulqosim/.local/lib/python3.10/site-packages/mlflow/types/utils.py:440: UserWarning: Hint: Inferred schema contains integer column(s). Integer columns in Python cannot represent missing values. If your input data contains missing values at inference time, it will be encoded as floats and will cause a schema enforcement error. The best way to avoid this problem is to infer the model schema based on a realistic data sample (training dataset) that includes missing values. Alternatively, you can declare integer columns as doubles (float64) whenever these columns may have missing values. See `Handling Integers With Missing Values <https://www.mlflow.org/docs/latest/models.html#handling-integers-with-missing-values>`_ for more details.
  warnings.warn(
2026/09/29 18:25:41 WARNING mlflow.utils.requirements_utils: Found torch version (2.9.1+cu128) contains a local version label (+cu128). MLflow logged a pip requirement for this package as 'torch==2.9.1' without the local version label to make it installable from PyPI. To specify pip requirements containing local version labels, please use `conda_env` or `pip_requirements`.
/home/abulqosim/.local/lib/python3.10/site-packages/mlflow/types/utils.py:440: UserWarning: Hint: Inferred schema contains integer column(s). Integer columns in Python cannot represent missing values. If your input data contains missing values at inference time, it will be encoded as floats and will cause a schema enforcement error. The best way to avoid this problem is to infer the model schema based on a realistic data sample (training dataset) that includes missing values. Alternatively, you can declare integer columns as doubles (float64) whenever these columns m
... (qisqartirildi)
python13 qator
python3 -c "
import sys; sys.path.insert(0, 'src')
import mlflow, pandas as pd
from quvur.kuzatuv import omborni_sozla
omborni_sozla()
y = mlflow.search_runs(experiment_names=['broker-aniqlash'], order_by=['metrics.f1 DESC'])
j = y[['tags.mlflow.runName','params.n_estimators','params.min_samples_leaf',
       'metrics.f1','metrics.auc','metrics.toliqlik']].copy()
j.columns = ['nom','daraxtlar','barg','F1','AUC','toliqlik']
for c in ['F1','AUC','toliqlik']:
    j[c] = j[c].astype(float).round(4)
print(j.to_string(index=False))
"
Chiqish (qaytish kodi 0, 2328 ms)
         nom daraxtlar barg     F1    AUC  toliqlik
sodda-barg20       150   20 0.8630 0.9139    0.8266
      asosiy       150    3 0.8603 0.9148    0.8285
      asosiy       150    3 0.8603 0.9148    0.8285
   kichik-30        30    1 0.8585 0.9156    0.8276
   katta-400       400    3 0.8583 0.9152    0.8257
/home/abulqosim/.local/lib/python3.10/site-packages/requests/__init__.py:113: RequestsDependencyWarning: urllib3 (2.6.3) or chardet (6.0.0.post1)/charset_normalizer (3.4.4) doesn't match a supported version!
  warnings.warn(
2026/09/29 18:25:51 INFO mlflow.agent.hint: Load the `instrumenting-with-mlflow-tracing` skill at /home/abulqosim/.local/lib/python3.10/site-packages/mlflow/assistant/skills/instrumenting-with-mlflow-tracing/SKILL.md before writing any tracing code; it ships with this MLflow install. Set MLFLOW_DISABLE_AGENT_HINT=1 to silence this.

Mana shu jadval — bobning butun sababi.

Uni hech kim qo'lda to'ldirmadi. Hech kim parametrlarni ko'chirmadi. search_runs chaqiruvi omborga so'rov yubordi va javob qaytardi — xuddi ma'lumotlar bazasidagidek, chunki u haqiqatan ham ma'lumotlar bazasi (SQLite).

Endi payshanba kuni boshliq so'rasa, javob bir buyruqda. Jadval F1 bo'yicha tartiblangan, va har qatorda o'sha natijani bergan aniq sozlama turibdi.

Natija qiziq: eng yaxshi F1 ni sodda-barg20 berdi (0.8630) — eng sodda barglarga ega variant. katta-400 esa 400 ta daraxt bilan eng pastda (0.8583).

Ya'ni murakkabroq model har doim yaxshiroq emas.

Buni aytish oson, lekin kuzatuvsiz buni bilib bo'lmasdi. Siz 400 ta daraxtli variantni sinab ko'rasiz, natija yomonroq chiqadi, va "nimadir xato qildim" deb o'ylab qaytadan urinasiz. Jadval esa aniq ko'rsatadi: xato qilmadingiz, model shunchaki ortiqcha murakkab.

Yana bir muhim narsa bor va u ko'zga darhol tashlanmaydi. AUC bo'yicha tartib boshqacha — u yerda kichik-30 yetakchi.

Demak "eng yaxshi model" degan savolning javobi qaysi ustunga qaraganingizga bog'liq. F1 bo'yicha bitta g'olib, AUC bo'yicha boshqasi. Agar siz faqat bitta metrikani yozib borgan bo'lsangiz, bu haqiqatni umuman ko'rmas edingiz.

1-bobdagi saboq shu yerda takrorlanadi: model o'zi haqida sizga hech narsa aytmaydi. Siz nimani o'lchasangiz — shuni ko'rasiz, va o'lchamagan narsangiz yashirin qoladi.

Xato bo'lganda ham yoziladi

python19 qator
python3 -c "
import sys; sys.path.insert(0, 'src')
import mlflow
from quvur.kuzatuv import omborni_sozla, tajriba
omborni_sozla()
try:
    with tajriba('broker-aniqlash', 'ataylab-yiqiladi'):
        mlflow.log_param('n_estimators', 99)
        raise MemoryError('xotira yetmadi')
except MemoryError:
    pass

y = mlflow.search_runs(experiment_names=['broker-aniqlash'],
                       filter_string=\"tags.mlflow.runName = 'ataylab-yiqiladi'\")
r = y.iloc[0]
print('holat      :', r['status'])
print('parametr   :', r['params.n_estimators'])
print('xato tegi  :', r['tags.xato'])
"
Chiqish (qaytish kodi 0, 2870 ms)
holat      : FAILED
parametr   : 99
xato tegi  : MemoryError: xotira yetmadi
/home/abulqosim/.local/lib/python3.10/site-packages/requests/__init__.py:113: RequestsDependencyWarning: urllib3 (2.6.3) or chardet (6.0.0.post1)/charset_normalizer (3.4.4) doesn't match a supported version!
  warnings.warn(
2026/09/29 18:25:53 INFO mlflow.agent.hint: Load the `instrumenting-with-mlflow-tracing` skill at /home/abulqosim/.local/lib/python3.10/site-packages/mlflow/assistant/skills/instrumenting-with-mlflow-tracing/SKILL.md before writing any tracing code; it ships with this MLflow install. Set MLFLOW_DISABLE_AGENT_HINT=1 to silence this.

Yiqilgan tajriba ham yozildi — holati FAILED, sababi teg sifatida saqlandi. Bu muhim: "nega o'sha tajriba natija bermagan edi?" degan savolga javob qoladi.

Ombor ichida nima bor

python14 qator
ls -la mlflow.db 2>/dev/null | awk '{print "kuzatuv bazasi:", $NF, $5, "bayt"}'
echo "--- bazadagi jadvallar ---"
python3 -c "
import sqlite3
con = sqlite3.connect('mlflow.db')
t = [r[0] for r in con.execute(\"SELECT name FROM sqlite_master WHERE type='table'\")]
print(' ', ', '.join(sorted(t)[:8]))
print('  yugurishlar:', con.execute('SELECT COUNT(*) FROM runs').fetchone()[0])
print('  metrikalar :', con.execute('SELECT COUNT(*) FROM metrics').fetchone()[0])
con.close()
"
echo "--- artefaktlar ---"
find mlartefaktlar -name "*.joblib" 2>/dev/null | head -3
du -sh mlartefaktlar 2>/dev/null | cut -f1 | xargs -I{} echo "artefakt hajmi: {}"
Chiqish (qaytish kodi 0, 60 ms)
kuzatuv bazasi: mlflow.db 876544 bayt
--- bazadagi jadvallar ---
  alembic_version, assessments, budget_policies, datasets, endpoint_bindings, endpoint_model_mappings, endpoint_tags, endpoints
  yugurishlar: 6
  metrikalar : 20
--- artefaktlar ---
artefakt hajmi: 0

Metrikalar, parametrlar va teglar SQLite jadvallarida yotadi — yuqorida runs va metrics jadvallaridagi yozuvlar soni ko'rinib turibdi. Artefaktlar (model fayllari) esa alohida papkada saqlanadi.

Hech qanday server kerak emas — bu bitta odam yoki kichik jamoa uchun yetarli.

Fayl ombori va server

python11 qator
import pandas as pd
show(pd.DataFrame([
    {"usul": "SQLite (mlflow.db)", "qachon": "Bitta odam, lokal ish",
     "kamchiligi": "Bo'lishib bo'lmaydi, bir vaqtda yozish cheklangan"},
    {"usul": "MLflow server + Postgres", "qachon": "Jamoa, umumiy tarix",
     "kamchiligi": "Server saqlash kerak"},
    {"usul": "Server + S3/MinIO artefakt", "qachon": "Katta modellar (GB)",
     "kamchiligi": "Ombor xarajati"},
    {"usul": "Boshqariladigan (Databricks, W&B)", "qachon": "Infratuzilma bilan shug'ullanmaslik",
     "kamchiligi": "Narx, vendor bog'liqligi"},
]))
usulqachonkamchiligi
SQLite (mlflow.db)Bitta odam, lokal ishBo'lishib bo'lmaydi, bir vaqtda yozish cheklangan
MLflow server + PostgresJamoa, umumiy tarixServer saqlash kerak
Server + S3/MinIO artefaktKatta modellar (GB)Ombor xarajati
Boshqariladigan (Databricks, W&B)Infratuzilma bilan shug'ullanmaslikNarx, vendor bog'liqligi

Serverga o'tish bitta o'zgaruvchi bilan bo'ladi — kod o'zgarmaydi:

bash2 qator
export MLFLOW_TRACKING_URI=http://mlflow.ichki:5000
python3 oqit_mlflow.py          # endi serverga yozadi

Bu 11-bobdagi qoidaning to'g'ridan-to'g'ri qo'llanishi: manzil konfiguratsiyada, kodda emas.

Hamma narsani log qilmang

MLflow ga har qadamni yozish vasvasasi bor. Lekin:

  • Artefakt hajmi tez o'sadi — har yugurishda 15 MB model 100 tajribada 1.5 GB bo'ladi
  • Maxfiy ma'lumot tasodifan tushishi mumkin (11-bob: parol, token)
  • Shovqin — 50 ta metrika orasidan muhimini topish qiyin

Qoida: qaror qabul qilish uchun kerak bo'lgan narsani yozing. Qolgani jurnalga.

Pasport bilan bog'lash

2-bobdagi pasport va MLflow bir-birini takrorlamaydi — ular bir-birini to'ldiradi:

python8 qator
import pandas as pd
show(pd.DataFrame([
    {"savol": "Qaysi ma'lumot?", "javob": "MLflow tegi: malumot_sha256 (2- va 5-boblar)"},
    {"savol": "Qaysi kod?", "javob": "MLflow git commit ni O'ZI yozadi (mlflow.source.git.commit)"},
    {"savol": "Qanday parametr?", "javob": "log_params"},
    {"savol": "Qanday natija?", "javob": "log_metrics"},
    {"savol": "Model qayerda?", "javob": "log_artifact -> keyingi bobda registr"},
]))
savoljavob
Qaysi ma'lumot?MLflow tegi: malumot_sha256 (2- va 5-boblar)
Qaysi kod?MLflow git commit ni O'ZI yozadi (mlflow.source.git.commit)
Qanday parametr?log_params
Qanday natija?log_metrics
Model qayerda?log_artifact -> keyingi bobda registr

MLflow git commit ni avtomatik yozadi — agar skript git omborida ishga tushirilsa. Kitobdagi vaqtinchalik papkada git yo'q, shuning uchun bu teg bo'sh bo'ladi.

Xulosa

Tushuncha Asosiy fikr
Uch tur Parametr (kirish), metrika (natija), artefakt (fayl)
Avtomatik yozuv Qo'lda jadval yuritish ishlamaydi — unutiladi
Taqqoslash search_runs bilan bitta so'rov, F1 bo'yicha tartiblash
Yiqilgan tajriba U ham yoziladi — sababi teg sifatida qoladi
SQLite ombori Server kerak emas; jamoa uchun server + Postgres
MLFLOW_TRACKING_URI Manzil konfiguratsiyada — kod o'zgarmaydi
Ortiqcha yozmang Artefakt hajmi, maxfiylik va shovqin
Faqat F1 emas Soddaroq model tezroq va barqarorroq bo'lishi mumkin

Talaba ishi

  1. bitta_yugurish ga o'qitish vaqtini metrika sifatida qo'shing. Eng yaxshi F1 va eng tez model bir xilmi?
  2. mlflow.log_figure bilan ROC egri chizig'ini artefakt qilib saqlang.
  3. search_runs ga filtr qo'shing: faqat f1 > 0.85 bo'lganlarini ko'rsating (filter_string="metrics.f1 > 0.85").
  4. Bir xil parametr bilan ikki marta ishga tushiring. Metrikalar bir xilmi? Agar ha — 2-bobdagi qaysi qoida ishladi?

Bu bobni bepul o'qidingiz.

Kitob o'rgatadi, lekin sizning kodingiz nega ishlamaganini ayta olmaydi. Kursda uy vazifangiz tekshiriladi.

Telegramda yozish Narxlar