В мире онлайн-рекламы кликабельность (Click-Through Rate или CTR) является очень важной метрикой для оценки эффективности рекламы. В связи с этим, системы предсказания кликов имеют большое значение и широко используются для спонсорского поиска и ставок в режиме реального времени (real time bidding).
В данном проекте мы построим production-ready пайплайн по предсказанию кликов пользователя для мобильной Web рекламы. За основу возьмем данные соревнования Kaggle Avazu CTR Prediction.
Пайплайн с моделью состоит из трех основных элементов
make_dataset
: чтения данныхfeatures/build_transformers
: обработки признаков, в которую входятDeviceCountTransformer
,UserCountTransformer
: трансформы для расчета количества рекламных объявлений на пользователя или девайсCtrTransformer
: трансформы, с помощью которых кодируем категориальные переменные средним CTR
model_fit_predict
: обучаем классическую модельCatboost
`а на предсказание вероятности клика для данной сессии пользователя.
Поскольку целью данного курса являются не сами эксперименты или файнтюнинг модели, а построение пайплайна то будем исходить из предположения, что это некоторая готовая версия модели, и нас просят катить ее в прод. Поэтому мы сосредоточим усилия на воспроизводимости, поддерживаемости, развертке и мониторинге.
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
python ctr_project/train_pipeline.py --configs configs/train_config.yaml
pytest
Наш пайплайн будет достаточно прямолинейным и будет содержать элементы описанные ранее.
Кастомные обработки фичей обернуты в формат sklearn transformer
для единооборазия.
В этом занятии мы затроним вопрос воспроизводимости экспериментов в ML. Рассмотрим 2 инструмента воспроизводимости экспериментов над моделями:
- DVC : для версионирования данных и артефактов при помощи Git синтаксиса
- MLFlow: для логирования экспериментов над моделью.
Также поднимем удаленное S3 объектное хранилище в VK Cloud.
pip install dvc
pip install mlflow
В процессе занятия нам потребуются следующие команды для настройка MLFLow UI и DVC и добавления данных в удаленное хранилище.
mlflow ui
# setup DVC
dvc init
dvc add data/raw/sampled_train_5m.csv
dvc add data/raw/sampled_train_50k.csv
# create and setup remote
dvc remote add s3 s3://sem3-repro/ctr-project-train/
dvc remote modify s3 endpointurl https://hb.ru-msk.vkcs.cloud
dvc remote modify s3 region ru-msk
# push/ pull to remote
dvc push -r s3
dvc pull -r s3
dvc repro
После прогона пайплайн у нас должна залогироваться их история в списке экспериметнов.
В каждом эксперименте будет записан свой список метрик, параметров модели и артефактов.
Мы будем иметь возможность сравнивать между собой отдельные запуски для выбора наиболее оптимального.
При этом в удаленном хранилище будут записаны обучающие данные, .pkl
модели и .json
метрики.
Артефакты с каждого прогона сохранены под своим собственным md5
хэшом.
При этом md5
хэши для каждого эксперимента будут доступны в файле dvc.lock
, который обновляется после каждого нового
эксперимента. Его мы тоже логируем в MLFlow, что дает нам возможность всегда иметь ссылку на состояние пайплайна
в каждом эксперименте.
schema: '2.0'
stages:
train:
cmd: python train_pipeline.py --config configs/train_config.yaml
deps:
- path: configs/train_config.yaml
hash: md5
md5: 37cbcef657312c588f872fae924d1c26
size: 969
- path: data/raw/
hash: md5
md5: 75f77c6ca378b83b4d199c58e68d213f.dir
size: 1762301353
nfiles: 8
outs:
- path: models/catclf.pkl
hash: md5
md5: bef120e799a37fc607c97ec475285368
size: 37030
- path: models/metrics.json
hash: md5
md5: 7cac56ee734d1e973b3a13c392cd15e8
size: 167
В этом занятии мы рассмотрим, как обернуть обученную ранее модель в REST сервис. Для этого нам познакомимся с Fast API. Также сделаем сервис доступным для запуска с любой машины, для этого мы соберем Docker образ и запустим его локально. Далее поднимем виртуальную машину на VKCLoud и развернем сервис удаленно.
pip install fastapi
pip install unicorn
apt install docker.io
# run uvicron server
uvicorn app:app --host 0.0.0.0 --port 8000
# build docker image
docker build -t evgeniimunin/ctr_online_inference:v1 .
# run fastapi app in docker container
docker run -p 8000:8000 evgeniimunin/ctr_online_inference:v1
# generate inference data on client side
python src/inference/make_requests.py
# push docker image to dcoker hub
docker tag evgeniimunin/ctr_online_inference:v1 evgeniimunin/ctr_online_inference:v1
docker push evgeniimunin/ctr_online_inference:v1
# resrict rights for .pem key pair VM access file
chmod 400 your_key_pair.pem
# connect to VM by SSH
ssh -i your_key_pair.pem ubuntu@your_external_ip
# pull docker image from docker hub
docker pull evgeniimunin/ctr_online_inference:v1
# run fastapi app in docker container
docker run -p 8000:8000 evgeniimunin/ctr_online_inference:v1
После написания REST сервиса на FastAPI мы можем его протестировать, отправив запросы на инференс.
В качестве ответа мы получим код 200, означающий успешный ответ с сервера, а тело ответа будет содержать
device_ip
и предсказанную вероятность клика для данной сессии click_proba
.
response.status_code: 200
response.json(): [{'device_ip': '7061f023', 'click_proba': 0.2136}]
В этом занятии мы рассмотрим, как настроить мониторинг REST сервиса на инференсе. В качестве инструментов мы воспользуемся
- Grafana: инструмент для визуализации метрик
- Prometheus: система мониторинга которая будет собирать метрики у приложения и передавать их в Grafana
Для передачи метрик в Prometheus нам понадобятся библиотеки
- prometheus-fastapi-instrumentator, чтобы Prometheus знал endpoint
/metrics
, откуда забирать метрики. - prometheus-client для определения метрик.
В качестве метрик выведем:
predict_proba
: значение вероятности клика с каждого предсказанияpredicted_proba_hist
: гистограмма вероятностейhttp_predict_request_total
: счетчик входящих запросов на endpoint/predict
Для настройки Prometheus мы пропишем конфиг,
где среди прочего укажем расписание сбора метрик по endpoint'у localhost:8000/metrics
.
global:
scrape_interval: 5s
scrape_configs:
- job_name: 'prometheus'
honor_timestamps: true
scrape_interval: 5s
scrape_timeout: 4s
metrics_path: /metrics
scheme: http
follow_redirects: true
static_configs:
- targets:
- localhost:9090
- job_name: 'fastapi-app'
scrape_interval: 5s
metrics_path: /metrics
static_configs:
- targets: ['app:8000']
Для работы нам будет необходимо поднять docker образы приложения, Prometheus, grafana.
Делать мы это будем с помощью docker-compose
.
docker compose up
После сборки образов и запуска контейнеров мы можем обратиться к серверу Prometheus
по адресу localhost:9090
. В поле выбора метрик
мы сможем увидеть введенные нами метрики и их текущие занчения.
Далее по адресу localhost:9090/targets
мы сможем проверить endpoint,
с которого Prometheus забирает метрики и его статус UP.
Grafana будет доступна по адресу localhost:3000
. После создания datasource Prometheus
мы сможем создать дашборд, куда и вынесем необходимые метрики.
├── LICENSE
├── Makefile <- Makefile with commands like `make data` or `make train`
├── README.md <- The top-level README for developers using this project.
├── data
│ ├── external <- Data from third party sources.
│ ├── interim <- Intermediate data that has been transformed.
│ ├── processed <- The final, canonical data sets for modeling.
│ └── raw <- The original, immutable data dump.
│
├── docs <- A default Sphinx project; see sphinx-doc.org for details
│
├── models <- Trained and serialized models, model predictions, or model summaries
│
├── notebooks <- Jupyter notebooks. Naming convention is a number (for ordering),
│ the creator's initials, and a short `-` delimited description, e.g.
│ `1.0-jqp-initial-data-exploration`.
│
├── references <- Data dictionaries, manuals, and all other explanatory materials.
│
├── reports <- Generated analysis as HTML, PDF, LaTeX, etc.
│ └── figures <- Generated graphics and figures to be used in reporting
│
├── requirements.txt <- The requirements file for reproducing the analysis environment, e.g.
│ generated with `pip freeze > requirements.txt`
│
├── setup.py <- makes project pip installable (pip install -e .) so src can be imported
├── src <- Source code for use in this project.
│ ├── __init__.py <- Makes src a Python module
│ │
│ ├── data <- Scripts to download or generate data
│ │ └── make_dataset.py
│ │
│ ├── features <- Scripts to turn raw data into features for modeling
│ │ └── build_features.py
│ │
│ ├── models <- Scripts to train models and then use trained models to make
│ │ │ predictions
│ │ ├── predict_model.py
│ │ └── train_model.py
│ │
│ └── visualization <- Scripts to create exploratory and results oriented visualizations
│ └── visualize.py
│
└── tox.ini <- tox file with settings for running tox; see tox.readthedocs.io
Project based on the cookiecutter data science project template. #cookiecutterdatascience