Feature store
| Появление | Uber Michelangelo (2017) |
|---|---|
| Компоненты | офлайн-хранилище, онлайн-хранилище, реестр признаков |
| Ключевая задача | устранить training-serving skew |
| Open source | Feast, Hopsworks, Featureform |
| Коммерческие | Tecton, Databricks Feature Store, SageMaker Feature Store, Vertex AI |
| Онлайн-хранилища | Redis, DynamoDB, Cassandra |
Feature store (хранилище признаков) — компонент MLOps-платформы, который хранит признаки (features) для моделей машинного обучения и выдаёт их в двух режимах: большими историческими выборками для обучения и по одной сущности с минимальной задержкой для онлайн-предсказаний. Признак — например, «число заказов пользователя за 30 дней» — описывается один раз, а все модели и команды используют одно и то же определение. Главная цель — чтобы модель в продакшене получала признаки, вычисленные ровно так же, как при обучении.
Проблема
Без общего хранилища каждая команда пишет свои SQL-запросы для обучения в ноутбуке, а затем отдельный код на сервисе для онлайн-вычислений. Возникают типичные проблемы:
- training-serving skew — признак в продакшене считается иначе, чем при обучении (другой часовой пояс, другая обработка пропусков), и модель тихо деградирует;
- утечка из будущего — при сборке обучающей выборки к событию присоединяется значение признака, известное только позже;
- дублирование — десять команд по-разному считают «активность пользователя»;
- задержка — тяжёлые агрегаты невозможно вычислить за миллисекунды во время запроса.
Идею хранилища признаков популяризировала Uber, описав в 2017 году платформу Michelangelo с общим Feature Store.[2]
Архитектура
| Компонент | Что хранит | Для чего | Примеры |
|---|---|---|---|
| Офлайн-хранилище | полная история значений признаков | обучение, бэктесты, батч-инференс | BigQuery, Snowflake, ClickHouse, Parquet в S3 |
| Онлайн-хранилище | последнее значение для каждой сущности | инференс за миллисекунды | Redis, DynamoDB, Cassandra |
| Реестр | определения, владельцы, версии | поиск и повторное использование | метаданные в базе |
| Конвейеры | вычисление и загрузка (materialization) | пакетные и потоковые расчёты | Spark, Flink, dbt |
Признаки вычисляются конвейерами из исходных данных, пишутся в офлайн-хранилище и периодически материализуются в онлайн-хранилище. Потоковые признаки (например, «число транзакций за последние 5 минут» для антифрода) обновляются в реальном времени из Kafka.
Point-in-time join
Ключевая функция для обучения — соединение на момент времени: для каждого примера (пользователь, момент события) берётся значение признака, актуальное именно тогда, а не последнее.[3] Если модель предсказывает отток на 1 марта, признак «число заказов за 30 дней» должен быть посчитан на 1 марта, а не на сегодня. Ручная реализация таких соединений — частый источник ошибок, и feature store берёт её на себя.
Пример: Feast
Feast — самый распространённый открытый feature store; признаки описываются кодом на Python:[1]
from datetime import timedelta
from feast import Entity, FeatureView, Field, FileSource
from feast.types import Float32, Int64
user = Entity(name="user", join_keys=["user_id"])
user_stats = FeatureView(
name="user_stats",
entities=[user],
ttl=timedelta(days=1),
schema=[Field(name="orders_30d", dtype=Int64),
Field(name="avg_check", dtype=Float32)],
source=FileSource(path="data/user_stats.parquet",
timestamp_field="event_ts"),
)
Обучающая выборка и онлайн-запрос:
# обучение: point-in-time join к таблице событий
train_df = store.get_historical_features(
entity_df=events_df, features=["user_stats:orders_30d", "user_stats:avg_check"]
).to_df()
# инференс: последнее значение из онлайн-хранилища
store.get_online_features(
features=["user_stats:orders_30d"], entity_rows=[{"user_id": 42}]
).to_dict()
Команда feast materialize-incremental переносит свежие значения в онлайн-хранилище.
Когда нужен
Feature store оправдан, когда:
- модели работают онлайн и требуют свежих признаков с малой задержкой (рекомендации, антифрод, ценообразование);
- одни и те же признаки используют несколько моделей и команд;
- уже были инциденты из-за расхождения обучения и продакшена.
Для одной модели с пакетным инференсом раз в сутки обычно достаточно витрины данных в хранилище, SQL-трансформаций в dbt и версионирования данных. Внедрение feature store — заметная инфраструктурная работа, и начинать её стоит с конкретной боли, а не «на вырост».
Связь с другими инструментами
Feature store дополняет реестр моделей и трекинг экспериментов (MLflow), системы сервинга запрашивают из него признаки при каждом предсказании, а мониторинг сравнивает распределения признаков в продакшене с обучающими, чтобы ловить дрейф данных. Похожая идея применяется и к эмбеддингам: векторные представления пользователей и товаров хранятся и отдаются так же, как обычные признаки.