Feature Store и фичи для RecSys
Пользовательские, айтемные, контекстные фичи. Feast, онлайн/оффлайн фичи.
Feature Store — единый источник правды для ML-фичей
Представь: в компании пять ML-команд. Антифрод считает фичу «количество транзакций за 7 дней» в Spark-джобе. Рекомендации — ту же фичу, но в другом пайплайне, чуть по-другому (включая текущий день или нет?). Скоринг — третий вариант. Поиск — четвёртый. Маркетинг — пятый. Пять реализаций одной фичи — пять источников багов, пять мест для поддержки, и ни одна команда не уверена, что считает правильно.
Feature Store — это централизованное хранилище, где фичи определяются один раз, вычисляются одним пайплайном и отдаются всем потребителям. Аналогия: вместо того чтобы каждый отдел компании готовил свой отчёт о продажах, есть один бухгалтерский отдел, который считает цифры и публикует единый отчёт. Все пользуются одним источником правды.
Но Feature Store — это не просто общая таблица. Его главная суперсила: гарантия, что модель на проде получает точно такие же фичи, как при обучении. Без этой гарантии даже идеальная модель может работать плохо — и ты даже не поймёшь почему.
Большая картина: define once → compute → store → serve
Feature Store работает в четыре шага:
1. Define — описываешь фичу декларативно: «средний чек пользователя за 30 дней». Указываешь entity (user_id), источник данных, тип агрегации. Определение хранится как код — версионируется в Git. 2. Compute — пайплайн (Spark, Airflow, стриминг) вычисляет фичи по расписанию или в реальном времени. Одна реализация — все потребители получают одинаковый результат. 3. Store — вычисленные значения попадают в два хранилища: offline store (S3, BigQuery) для обучения и online store (Redis, DynamoDB) для инференса. Offline хранит историю, online — только последние значения. 4. Serve — модель запрашивает фичи по entity_id. При обучении идёт в offline store (исторические данные). При инференсе — в online store (актуальные значения за миллисекунды).

Ключевой инсайт: offline и online store хранят одни и те же фичи, вычисленные одним кодом. Это то, что устраняет рассинхронизацию между обучением и инференсом.
Training-serving skew: проблема №1 без Feature Store
Training-serving skew — это когда фичи при обучении и на инференсе вычисляются по-разному. Это одна из самых коварных ошибок в ML: модель не падает, не выдаёт NaN, просто тихо работает хуже.
Как это происходит на практике:
• Разный код предобработки. DS обучал модель в ноутбуке и писал df["amount"].rolling(7).mean(). Backend-разработчик реализовал ту же логику на Java — но посчитал окно чуть иначе (включая текущий день или нет, включая нули или нет).
• Разные источники данных. При обучении фичи считали из Hive-таблицы. На проде — из PostgreSQL. Данные немного отличаются: разная гранулярность, разные задержки обновления.
• Time leakage. При обучении случайно использовали «будущие» данные: средний чек *включая* целевое событие. На проде этой информации ещё нет — модель получает другие значения.
Как ловить skew
Feature Store решает training-serving skew архитектурно: определение фичи задаётся один раз, а compute-пайплайн заполняет и offline, и online store. DS достаёт фичи из offline store для обучения, а inference-сервис — из online store. Код вычисления общий → skew невозможен.
Online vs Offline store: два режима для разных задач
Offline store — для обучения и batch-аналитики. Хранит полную историю значений фичей: «какой был средний чек пользователя 42 на 15 марта 2024?». Реализация: файлы в S3 (Parquet), таблицы в BigQuery, Hive, Snowflake. Latency не важна — запрос может выполняться секунды или минуты. Важен объём: миллиарды строк за месяцы и годы.
Online store — для real-time инференса. Хранит только последние значения фичей: «какой средний чек пользователя 42 прямо сейчас?». Реализация: Redis, DynamoDB, Bigtable. Latency критична — ответ за 1-10ms. Объём меньше: по одной строке на entity.
Сравнение:
Offline Store Online Store
: , real-time inference
:
Latency: / 110 ms
: S3, BigQuery, Hive Redis, DynamoDB
:
: "все пользователи "user_id=42
X" прямо сейчас"Как они связаны: compute-пайплайн записывает фичи в оба хранилища. Batch-джоба (Spark, Airflow) заполняет offline store раз в час/день. Отдельный процесс (materialization) берёт последние значения из offline store и загружает в online store. Некоторые фичи вычисляются стримингом (Kafka, Flink) и попадают в online store напрямую — это «свежие» real-time фичи.
Point-in-time correctness: путешествие назад во времени
Допустим, ты обучаешь модель оттока. Нужна обучающая выборка: для каждого пользователя — фичи на момент целевого события. Пользователь ушёл 10 марта — значит, нужны его фичи на 9 марта (до события), а не на сегодня.
Если просто взять текущие значения из базы — произойдёт time leakage: в фичах окажется информация из будущего относительно момента предсказания. Модель выучит паттерны, которых не будет на проде, и метрики в проде будут хуже.
Point-in-time correctness (point-in-time join) — это способность Feature Store выдавать значения фичей строго на указанный момент времени. Ты передаёшь список (entity_id, timestamp) — Feature Store возвращает значения фичей, которые были актуальны именно на этот timestamp, игнорируя всё, что появилось позже.
# Point-in-time join: правильная обучающая выборка
import pandas as pd
from feast import FeatureStore
store = FeatureStore("feature_repo/")
# Целевые события: user_id + дата события
entity_df = pd.DataFrame({
"user_id": [101, 102, 103],
"event_timestamp": [
"2024-03-09", # фичи НА ЭТУ дату
"2024-03-12", # без утечки из будущего
"2024-03-15",
],
})
# Feast вернёт значения фичей СТРОГО на указанные даты
training_df = store.get_historical_features(
entity_df=entity_df,
features=[
"user_stats:avg_order_30d",
"user_stats:num_sessions_7d",
"user_stats:days_since_last_purchase",
],
).to_df()
# training_df: user_id | event_timestamp | avg_order_30d | ...
# Каждая строка — фичи БЕЗ утечки из будущегоБез Feature Store point-in-time join приходится реализовывать вручную через window-функции в SQL — это сложно, хрупко и часто содержит баги. Feature Store делает это из коробки: каждая запись фичи хранит entity timestamp, и join учитывает его автоматически.
Feast: open-source, быстрый старт
Feast (Feature Store) — самый популярный open-source Feature Store. Изначально создан в Gojek, сейчас развивается как независимый проект. Feast легковесный: можно запустить локально за 10 минут без Kubernetes и облака.
Как устроен Feast:
• Feature definitions — Python-код, описывающий сущности (Entity), источники данных (FileSource, BigQuerySource) и представления фичей (FeatureView). Хранится в Git.
• Offline store — по умолчанию файлы (Parquet), можно подключить BigQuery, Snowflake, Redshift. Используется для get_historical_features() — point-in-time join.
• Online store — по умолчанию SQLite (для разработки), в проде — Redis, DynamoDB, PostgreSQL. Используется для get_online_features() — real-time запросы.
• Materialization — команда feast materialize, которая переносит данные из offline store в online store. Запускается по cron.
# feature_repo/features.py — определение фичей в Feast
from feast import Entity, FeatureView, Field, FileSource
from feast.types import Float32, Int64
from datetime import timedelta
# Сущность — ключ для запроса
user = Entity(name="user_id", join_keys=["user_id"])
# Источник данных — откуда брать значения
user_stats_source = FileSource(
path="data/user_stats.parquet",
timestamp_field="event_timestamp",
)
# FeatureView — набор фичей с привязкой к сущности
user_stats_view = FeatureView(
name="user_stats",
entities=[user],
schema=[
Field(name="avg_order_30d", dtype=Float32),
Field(name="num_sessions_7d", dtype=Int64),
Field(name="days_since_last_purchase", dtype=Int64),
],
source=user_stats_source,
ttl=timedelta(days=1), # фичи устаревают через 1 день
)# Использование Feast: online inference
from feast import FeatureStore
store = FeatureStore("feature_repo/")
# Real-time: получить фичи для конкретных пользователей
features = store.get_online_features(
features=[
"user_stats:avg_order_30d",
"user_stats:num_sessions_7d",
],
entity_rows=[
{"user_id": 101},
{"user_id": 102},
],
).to_dict()
# features = {
# "user_id": [101, 102],
# "avg_order_30d": [4250.0, 1800.0],
# "num_sessions_7d": [12, 3],
# }Типичный workflow с Feast: описал фичи в Python → feast apply (создаёт/обновляет инфраструктуру) → заполнил offline store данными → feast materialize (загрузил в online store) → используешь get_historical_features() для обучения и get_online_features() для инференса.
Альтернативы: Tecton, Hopsworks, in-house
Tecton — managed Feature Store от создателей Feast. Полностью serverless: стриминг-фичи, автоматическая materialization, monitoring фичей. Дорого, но снимает всю инфраструктурную сложность. Подходит для компаний, где ML — основной бизнес.
Hopsworks — open-source ML-платформа, Feature Store — одна из ключевых компонент. Сильная сторона: встроенная интеграция с PySpark и Kafka для стриминг-фичей. Есть managed-версия и self-hosted.
Vertex AI Feature Store (GCP), SageMaker Feature Store (AWS) — облачные решения, тесно интегрированные с экосистемами своих облаков. Удобно, если ты уже в GCP/AWS, но создают vendor lock-in.
In-house решения. Многие крупные компании строят свои Feature Store: это Redis + cron-джоба + пайплайн вычисления фичей. Плюс: полный контроль, точное соответствие инфраструктуре. Минус: месяцы разработки и поддержка. Для небольших команд (1-3 ML-инженера) in-house — оверинжиниринг; достаточно Feast или даже просто Redis + Parquet-файлы.
Когда Feature Store НЕ нужен
🎯 На собеседовании
Junior
Middle
Senior
Собираем всё вместе
Feature Store решает три проблемы: дублирование кода фичей между командами (define once), training-serving skew (единый пайплайн для offline и online), и time leakage при обучении (point-in-time correctness). Архитектура — четыре шага: define → compute → store (offline + online) → serve.
Если запомнить одну вещь: Feature Store — это не про хранение, а про consistency. Главная ценность — гарантия, что модель на проде видит точно такие же фичи, как при обучении. Без этой гарантии даже лучшая модель деградирует на проде.
Дальше на роадмапе: Model Serving — как отдавать предсказания в batch и online, Monitoring — как ловить data drift и деградацию модели на проде.
Материалы
Обзор: зачем нужен Feature Store, какие проблемы решает, как устроен Feast.
Документация Feast: quickstart, concepts, API reference.
Глубокий обзор от создателей Feast/Tecton: online vs offline, point-in-time join.
Почему Feature Store — недостающий слой ML-инфраструктуры.
Прагматичный взгляд: когда Feature Store нужен, а когда — оверинжиниринг.