ML-эксперименты и работа с пайплайнами

ML-цикл принципиально отличается от обычной разработки: здесь нет «готово» — есть метрика, гипотеза, эксперимент и снова гипотеза. Переключение между чтением данных, написанием трансформаций, настройкой трекинга и отладкой пайплайна занимает непропорционально много времени — и именно здесь Claude Code вставляет агентный слой. Но у этого инструмента есть чёткая граница: он умеет писать код, читать файлы и запускать команды, но не видит числа в реальном времени и не интерпретирует метрики за вас.


Где агент действительно ускоряет ML-цикл

Practitioners обычно теряют время не на самом обучении, а вокруг него: скаффолдинг конфигов, подготовка данных, написание повторяющегося boilerplate, отладка упавшего шага пайплайна. Это именно то, на что Claude Code тратит секунды вместо часов.

Подготовка данных. Агент хорошо читает структуру датасета и пишет чистую трансформацию:

Посмотри на @data/raw/train.parquet и @src/features/config.yaml.

Напиши скрипт src/features/build_features.py, который:
- нормализует числовые колонки по списку из конфига
- энкодит категориальные через target encoding (используй category_encoders)
- разбивает на train/val по стратифицированному сплиту (stratify по label)
- сохраняет в data/processed/ в формате parquet

В начале скрипта — assert-проверки на ожидаемые колонки и типы.

Агент пишет такой скрипт в стиле уже существующего кода рядом — если дать ему примеры из проекта через @. Это тот же принцип «схема первая», что работал с SQL, только теперь вместо схемы БД — структура датасета и конфиг фич.

Скаффолдинг эксперимента. Создание нового эксперимента с MLflow — рутина, которая занимает 20–30 минут вручную (конфиги, логирование, сохранение артефактов). Агент делает это по образцу:

В проекте уже есть experiments/baseline/ с MLflow-трекингом.
Создай experiments/attention_pooling/ по той же структуре:
- train.py с логированием гиперпараметров, метрик per epoch и финального val_f1
- config.yaml с параметрами модели
- README.md с описанием гипотезы

Гипотеза: замена mean pooling на attention pooling в классификаторе улучшит F1 на несмотря на +15% параметров.

Важно: гипотезу и интерпретацию результатов пишете вы. Агент создаёт инфраструктуру для её проверки.

Check yourself
Агент написал скрипт для подготовки данных с target encoding. Вы запустили его и получили val_f1 = 0.89 — что кажется хорошим. Какой потенциальный риск нужно проверить до того, как доверять этой цифре?

Jupyter vs. marimo: что работает с агентом

Предыдущая статья о Данных, SQL и аналитике описала два пути для Jupyter: встроенный NotebookEdit (без доступа к ядру) и Jupyter MCP Server (с полным циклом «написал → запустил → прочитал вывод»). В ML-контексте к этому добавляется ещё одна рекомендация.

marimo — реактивная замена Jupyter, которая хранит ноутбуки как обычный .py-файл. Claude Code работает с ним как с любым Python-файлом: читает, редактирует, запускает через bash. Никакого JSON, никаких спрятанных состояний ячеек — и никакого специального MCP-сервера для базового цикла. Команда marimo run notebook.py запускает воспроизводимый ноутбук без «грязи» от порядка исполнения ячеек.

# Установка
pip install marimo

# Запуск существующего ноутбука в Claude Code
claude
# затем в диалоге:
# > запусти marimo run experiments/eda.py и покажи вывод

Для тяжёлого EDA, где нужно видеть графики в реальном времени — всё же лучше Jupyter MCP Server. Для ML-скриптов, где важна воспроизводимость — marimo или чистые .py-файлы.

flowchart TD A[Данные / raw] --> B[Подготовка фичей<br/>агент пишет скрипт] B --> C[data/processed/] C --> D[Скаффолдинг эксперимента<br/>агент создаёт структуру] D --> E[train.py + config.yaml<br/>+ MLflow/W&B логирование] E --> F[Запуск обучения<br/>вы / CI] F --> G[Артефакты и метрики<br/>MLflow / W&B] G --> H{Анализ результатов<br/>агент или вы?} H -->|Структурированный анализ| I[claude -p на mlruns/] H -->|Интерпретация| J[Вы: выбор гипотезы] J --> D E --> K[Воспроизводимость<br/>агент проверяет seeds,<br/>конфиги, версии] style H fill:#f5a623,color:#000 style J fill:#d0021b,color:#fff
flowchart TD
    A[Данные / raw] --> B[Подготовка фичей<br/>агент пишет скрипт]
    B --> C[data/processed/]
    C --> D[Скаффолдинг эксперимента<br/>агент создаёт структуру]
    D --> E[train.py + config.yaml<br/>+ MLflow/W&B логирование]
    E --> F[Запуск обучения<br/>вы / CI]
    F --> G[Артефакты и метрики<br/>MLflow / W&B]
    G --> H{Анализ результатов<br/>агент или вы?}
    H -->|Структурированный анализ| I[claude -p на mlruns/]
    H -->|Интерпретация| J[Вы: выбор гипотезы]
    J --> D
    E --> K[Воспроизводимость<br/>агент проверяет seeds,<br/>конфиги, версии]
    style H fill:#f5a623,color:#000
    style J fill:#d0021b,color:#fff
ML-цикл с Claude Code: где агент автоматизирует, где нужен человек

Quick recall
Почему в ML-работе с Claude Code выбирают marimo вместо Jupyter?

Трекинг экспериментов: настройка через агента

Настроить MLflow или Weights & Biases в новом проекте — задача с множеством мелких шагов, которые легко делегировать:

Проект на PyTorch, используем MLflow для трекинга.
Сейчас в train.py нет никакого логирования.

1. Добавь mlflow.start_run() с автоматическим именем run из конфига
2. Логируй все поля из config.yaml как params
3. Логируй train_loss и val_loss каждую эпоху
4. В конце — log_metric("best_val_f1", ...) и mlflow.pytorch.log_model()
5. Добавь в requirements.txt mlflow>=2.10

Образец структуры конфига: @configs/baseline.yaml
Образец train.py: @experiments/baseline/train.py

Агент напишет боilerplate, сохранит стиль существующего кода и не забудет mlflow.end_run() в finally-блоке — что часто забывает человек. После — проверяете код глазами и запускаете.

W&B — аналогично, только синтаксис другой. Если в проекте уже есть один интегрированный скрипт, дайте его агенту как образец и попросите портировать трекинг на новый эксперимент.

Check yourself
Вы попросили агента добавить MLflow-трекинг в train.py. Агент вставил `mlflow.start_run()` в начало скрипта и `mlflow.end_run()` в конце. Что произойдёт, если обучение упадёт с исключением на середине — и как правильно это исправить?

Пайплайны: отладка и расширение

ML-пайплайны на Airflow, Prefect или Metaflow обычно падают в самый неожиданный момент. Claude Code хорошо справляется с двумя сценариями.

Дебаг упавшего пайплайна. Дайте агенту лог и код:

Vот лог упавшего DAG в Airflow:
<paste traceback>

Файл DAG: @dags/training_pipeline.py
Файл задачи: @src/pipeline/train_task.py

Найди причину, предложи фикс и добавь обработку этой ошибки.

Агент видит контекст обоих файлов, читает трейсбэк и часто сразу указывает на корень проблемы — неправильный путь к артефакту, несовпадение типов, пропущенная зависимость между тасками.

Добавление нового шага. Если пайплайн нужно расширить — дайте агенту существующий DAG как образец:

Посмотри на структуру @dags/training_pipeline.py.
Добавь новый шаг evaluate_on_holdout после задачи train_model:
- загружает лучший checkpoint из MLflow по run_id
- прогоняет инференс на @data/holdout.parquet
- сохраняет отчёт в reports/holdout_metrics.json
- при метрике f1 < 0.75 помечает таск как failed

Сохрани стиль: те же паттерны retry, те же переменные Airflow, тот же формат логирования.

Символ @ для подгрузки файлов в контекст — это всё тот же механизм из CLAUDE.md и система памяти. Здесь он работает как «передать образец стиля».


Quick recall
Вы даете Claude Code лог упавшего DAG в Airflow и код задачи. Что дальше?

Воспроизводимость: агент как контролёр гигиены

Воспроизводимость ML-эксперимента зависит от множества мелочей, которые легко упустить: random seed, версии библиотек, фиксированный порядок данных. Claude Code можно попросить пройтись по коду и найти проблемы:

Проверь experiments/attention_pooling/train.py на воспроизводимость:
- Все random seed зафиксированы? (torch, numpy, random, cuda)
- Версии зависимостей пришпилены в requirements.txt?
- Путь к данным не хардкодится в коде?
- Результаты сохраняются с run_id, а не перезаписывают предыдущие?

Внеси необходимые правки.

Типичный результат: агент добавляет torch.backends.cudnn.deterministic = True, заменяет хардкодированный путь на Path(config.data_dir) и дополняет requirements.txt точными версиями.

Конфиги вместо аргументов командной строки. Если в проекте параметры передаются через десятки argparse-аргументов — это сигнал перейти на YAML-конфиги (Hydra, OmegaConf). Агент умеет делать этот рефакторинг:

Портируй @experiments/baseline/train.py с argparse на Hydra.
Конфиги должны лежать в configs/, базовый конфиг — configs/default.yaml.
Групповые конфиги: configs/model/, configs/data/.
Сохрани все существующие параметры.

После рефакторинга каждый запуск эксперимента имеет зафиксированный конфиг-файл — воспроизвести прогон с теми же параметрами становится тривиальной задачей.

Check yourself
После перехода с argparse на Hydra конфиги хранятся в configs/. Коллега запускает ваш эксперимент командой `python train.py lr=0.001 batch_size=32`. Что меняется с точки зрения воспроизводимости по сравнению с argparse?

Headless-режим для запуска серий экспериментов

Когда нужно прогнать серию конфигов — например, grid search по learning rate и batch size — можно использовать headless-режим Claude Code в связке с shell-скриптом. Подробнее о headless-режиме — в Headless-режим и скриптинг через CLI, здесь только ML-паттерн:

# Прогнать анализ результатов после серии экспериментов
claude -p "
Посмотри на mlruns/ и найди все run-ы с тегом experiment=attention_pooling.
Сравни val_f1 по learning_rate и batch_size.
Выведи таблицу: lr | batch | best_val_f1 | best_epoch
Выдели конфиг с наилучшим val_f1.
" --output-format json > results/sweep_analysis.json

Агент читает артефакты MLflow напрямую из файловой системы и возвращает структурированный результат. Не нужно открывать UI или писать pandas-скрипт для анализа.


Где нужен надзор человека

МL — область, где неправильная интерпретация стоит дорого. Вот где агент требует явного контроля:

Выбор метрики. Claude Code сгенерирует код для любой метрики, которую попросите, — но выбор правильной (precision vs. recall при несбалансированных классах, NDCG vs. MAP для ранжирования) остаётся за вами. Агент не знает, что важнее для вашего продукта.

Интерпретация результатов. «val_loss перестала падать на эпохе 8» — это ранняя остановка или переобучение? Агент видит числа, но не понимает контекста: сколько данных, насколько сложная задача, приемлем ли такой val_f1 для деплоя.

Data leakage. Агент пишет сплиты и трансформации честно в рамках того, что вы описали — но не всегда обнаруживает утечку фичей из будущего. Сложный leakage (e.g., target encoding сделан до сплита) требует ревью человека.

Производственные данные. Правило из предыдущей статьи работает здесь вдвойне: агент с доступом к S3 или удалённой БД может изменить данные, если попросить неосторожно. Отдельный read-only IAM-пользователь для агента — не паранойя, а стандарт.


Quick recall
Интерпретацию каких результатов Claude Code не должен делать?

See also

Sources

  1. Building Data Pipelines with Claude Code: Engineering Reliable, Reproducible LLM Systems
  2. Using Claude Code with marimo
  3. Can Claude Code Analyze Jupyter Notebooks for Data Science? What It Actually Does – Kanaries
  4. Getting Started with Claude Code for Data Scientists – Dataquest
  5. ML Experiment Tracker: Claude Code Skill
  6. Best practices for Claude Code