fix: mlflow run — guard set_experiment под MLFLOW_RUN_ID + рецепт (tracking URI, venv, --env-manager local)

This commit is contained in:
2026-07-21 01:19:40 +03:00
parent ae62641cbc
commit c8043ad7c4
5 changed files with 34 additions and 10 deletions
+6 -3
View File
@@ -106,9 +106,11 @@ python src/hyperparam_sweep.py --max-combos 20
python src/serve_model.py --port 5001
python src/grid_search_cv.py
# Через MLflow Projects (изолированное окружение по MLproject)
mlflow run . -P n_estimators=100 -P max_depth=8
mlflow run . -P epochs=10 -P batch_size=256 -P lr=0.001 --entry-point gpu
# Через MLflow Projects (нужны MLFLOW_TRACKING_URI + активный venv)
source .venv/bin/activate
export MLFLOW_TRACKING_URI=http://localhost:5555
mlflow run . --env-manager local --experiment-name digits_classification -P n_estimators=100 -P max_depth=8
mlflow run . --env-manager local -e gpu --experiment-name mnist_cnn_gpu -P epochs=10 -P batch_size=256 -P lr=0.001
```
---
@@ -142,6 +144,7 @@ mlflow run . -P epochs=10 -P batch_size=256 -P lr=0.001 --entry-point gpu
- `train_gpu.py` передаёт `input_example` → сигнатура авто-infer'ится.
- `autolog_demo.py` намеренно отключает сигнатуры (`log_model_signatures=False`) как демо опций autolog — там warning ожидаем.
- **INFO про переменные окружения** (`OPENAI_API_KEY` и т.п.) при логировании подавлено через `MLFLOW_RECORD_ENV_VARS_IN_MODEL_LOGGING=false` в скриптах, логирующих модели.
- **`mlflow run` (MLflow Projects) — три условия**, иначе падает: (1) нужно `export MLFLOW_TRACKING_URI=http://localhost:5555` (сервер работает) — иначе `mlflow run` создаёт run в дефолтном file-store → maintenance mode; (2) venv активирован (`source .venv/bin/activate`) — иначе `python: command not found` в подпроцессе entry-point; (3) `--env-manager local` — иначе MLflow создаёт новый venv из `python_env.yaml` (python 3.10, медленно, может не быть нужного интерпретатора). Скрипты `train_simple/train_gpu/hyperparam_sweep` не вызывают `set_experiment` под `mlflow run` (детект `MLFLOW_RUN_ID`), поэтому `--experiment-name` опционален.
- **`python -m venv` падает на Linux (ensurepip)**: на Debian/Ubuntu без пакета `python3.13-venv` (или `python3-venv`) создание venv падает на шаге `ensurepip` (`non-zero exit status 1`). `setup_server.sh` ловит это и пробует fallback: `venv --without-pip` + bootstrap pip через `get-pip.py`. Альтернатива руками — `sudo apt-get install -y python3.13-venv python3.13-dev`.
- **File-store как tracking backend запрещён в MLflow 3.x** (maintenance mode): падает и `mlflow server --backend-store-uri file://...`, и клиент-скрипт с дефолтным `./mlruns` — оба с `MlflowException ... in maintenance mode`. Поэтому проект использует **SQLite** (`sqlite:///mlflow.db`) как tracking backend, а скрипты логируют на сервер по HTTP. Опциональный opt-out `MLFLOW_ALLOW_FILE_STORE=true` НЕ используем (он может быть убран в будущем). Артефакты при этом лежат на локальном диске (`./artifacts`, file artifact repository — он НЕ в maintenance mode).
- **MNIST: `yann.lecun.com/exdb/mnist/` умер (HTTP 404)** — `torchvision.MNIST (download=True)` падает при скачивании. В `train_gpu.py` есть `ensure_mnist()`: качает 4 gz-файла с рабочего зеркала `https://ossci-datasets.s3.amazonaws.com/mnist/` и **распаковывает их** (gunzip) в `data/MNIST/raw/` в файлы без `.gz`. Важно: torchvision.MNIST._check_exists() ищет именно РАСПАКОВАННЫЕ файлы (`train-images-idx3-ubyte` и т.п.), а не архивы — поэтому просто положить gz недостаточно, нужен gunzip. Если и S3 недоступен — положите 4 MNIST gz-файла вручную в `data/MNIST/raw/` (скрипт распакует их сам).
+16 -4
View File
@@ -97,13 +97,25 @@ python src/grid_search_cv.py
### 4. MLflow Projects (воспроизводимый запуск)
`mlflow run` нужен установленный `MLFLOW_TRACKING_URI` и активированный venv
(иначе: file-store maintenance mode и `python: command not found`).
```bash
# Запуск через MLproject — MLflow сам создаст окружение
mlflow run . -P n_estimators=200 -P max_depth=12
mlflow run . -e gpu -P epochs=10 -P batch_size=256 -P lr=0.001
mlflow run . -e sweep -P max_combos=30
source .venv/bin/activate
export MLFLOW_TRACKING_URI=http://localhost:5555 # сервер MLflow должен работать
# --env-manager local — использовать текущий venv (не создавать новый из python_env.yaml)
mlflow run . --env-manager local --experiment-name digits_classification \
-P n_estimators=200 -P max_depth=12
mlflow run . --env-manager local -e gpu --experiment-name mnist_cnn_gpu \
-P epochs=10 -P batch_size=256 -P lr=0.001
mlflow run . --env-manager local -e sweep --experiment-name sweep_digits \
-P max_combos=30
```
> `--experiment-name` теперь опционален (скрипты не конфликтуют с run'ом от
> `mlflow run`), но полезен, чтобы запуск попал в нужный эксперимент, а не в Default.
---
## 📚 Что изучает каждый урок
+3
View File
@@ -69,6 +69,9 @@ def main():
X, y, test_size=0.2, random_state=42
)
# под `mlflow run` эксперимент уже задан Projects (MLFLOW_RUN_ID) —
# не переопределяем, иначе конфликт "active experiment ID does not match".
if not os.environ.get("MLFLOW_RUN_ID"):
mlflow.set_experiment(args.experiment_name)
best_acc = 0.0
+3
View File
@@ -145,6 +145,9 @@ def main():
print(" Apple Silicon GPU (MPS)")
# ─── MLflow эксперимент ───
# под `mlflow run` эксперимент уже задан Projects (MLFLOW_RUN_ID) —
# не переопределяем, иначе конфликт "active experiment ID does not match".
if not os.environ.get("MLFLOW_RUN_ID"):
mlflow.set_experiment(args.experiment_name)
# ─── Данные ───
+3
View File
@@ -36,6 +36,9 @@ def main():
args = parser.parse_args()
# --- MLflow: задаём эксперимент ---
# под `mlflow run` эксперимент уже задан Projects (MLFLOW_RUN_ID) —
# не переопределяем, иначе конфликт "active experiment ID does not match".
if not os.environ.get("MLFLOW_RUN_ID"):
mlflow.set_experiment(args.experiment_name)
# --- Данные ---