Перейти к содержанию

one_to_many_pipeline

featminer.pipelines.one_to_many.one_to_many_pipeline

one_to_many_pipeline(
    *,
    df: DataFrame,
    target_col: str,
    aggregation_key: str,
    event_times: Collection[str] | None = None,
    prediction_time: str | None = None,
    cutoff_by: str | None = None,
    relative_time_columns: Collection[RelativeTime]
    | None = None,
    sampling_key: str | None = None,
    max_sampling_groups: int | None = None,
    max_cells_threshold: int = 100000000,
    candidate_screening: CandidateScreening | None = None,
    cat_features: Collection[str] | None = None,
    baseline_features: DataFrame | None = None,
    min_category_fraction: float = 0.01,
    selection: SelectionConfig | None = None,
    formulas: FormulaSet
    | Sequence[OneToManyFormula] = "basic",
    derived_columns: DerivedColumnsConfig = DEFAULT_DERIVED_COLUMNS,
    generate_report: bool = True,
    open_browser: bool = True,
    verbose: Literal[
        "off", "warning", "info", "debug"
    ] = "info",
) -> pd.DataFrame

Генерирует и отбирает агрегированные признаки по связанным строкам исторической таблицы. В результате возвращает по одной строке на каждый объект.

Параметры

Параметр По умолчанию Описание
df Исходная таблица, содержащая одну или несколько строк на каждый объект.
target_col Колонка с бинарным таргетом. Значение должно быть одинаковым внутри одного объекта.
aggregation_key Колонка, по которой строки объединяются в объекты.
event_times None Временные оси для time-aware формул. Могут включать известные заранее плановые даты из будущего.
prediction_time None Момент построения прогноза. Используется как опорное время формул и включает point-in-time-фильтрацию.
cutoff_by None Колонка из event_times, определяющая доступность строки. Строки после prediction_time исключаются. При единственной временной оси определяется автоматически.
relative_time_columns None Числовые временные смещения с явно заданными единицами измерения.
sampling_key None Ключ, полные группы которого сохраняются при формировании подвыборки. По умолчанию используется aggregation_key.
max_sampling_groups None Максимальное число полных групп для отбора признаков. None не ограничивает количество групп.
max_cells_threshold 100_000_000 Максимальный размер входной таблицы строки × колонки до автоматического downsampling.
candidate_screening None Необязательный быстрый предварительный отбор колонок и масок перед полным перебором.
cat_features None Колонки, которые нужно обрабатывать как категориальные. Если параметр не задан, категориальные колонки определяются по типам данных.
baseline_features None Существующие числовые признаки. Учитываются при корреляционном отборе, чтобы новые признаки не дублировали их.
min_category_fraction 0.01 Минимальная доля категории, необходимая для участия в генерации признаков.
selection None Декларативная политика отбора. None включает SelectionConfig.auc() с прежними порогами по умолчанию. Все пороги основного отбора задаются внутри конфига.
formulas "basic" Формулы для генерации: быстрый набор "basic", дополнительный "advanced", объединяющий их "all" или явная последовательность экземпляров формул (Sequence[OneToManyFormula]). Расширение набора может повысить качество ценой времени расчёта.
derived_columns DEFAULT_DERIVED_COLUMNS Настройки производных колонок и условий (DerivedColumnsConfig). По умолчанию создаются дни между парами дат и условия по одной колонке; попарные разности и отношения выключены.
generate_report True Формировать HTML-отчёт и воспроизводимый Python-код. Если False, отчёт не создаётся, а open_browser игнорируется.
open_browser True Открывать сформированный HTML-отчёт в браузере.
verbose "info" Уровень журналирования: "off", "warning", "info" или "debug".

Выбор формул

В API используется параметр formulas. Он принимает строковый пресет "basic", "advanced" или "all", а также явную последовательность экземпляров формул. По умолчанию используется "basic".

Выбор готового набора:

# Быстрый базовый набор используется по умолчанию.
features = one_to_many_pipeline(..., formulas="basic")

# Только дополнительные формулы.
features = one_to_many_pipeline(..., formulas="advanced")

# Базовые и дополнительные формулы вместе.
features = one_to_many_pipeline(..., formulas="all")

Если выбранной формуле не хватает временной конфигурации, pipeline выводит warning с именами таких формул, пропускает их и продолжает расчёт. Без event_times не запускаются формулы, которым нужен порядок событий. При календарных Date-осях без prediction_time пропускаются формулы, которые считают значения относительно момента прогноза. First и Last при этом продолжают работать, а RelativeTime использует нулевую точку прогноза.

Набор Формулы
basic Fraction, Count, Max, Sum, Mean, Min, Nunique, Std, First, Last
advanced NumMax, NumMin, Kurtosis, Skew, Mode, EventRange, FirstCategory, LastCategory, IntervalMax, IntervalMean, IntervalMin, IntervalStd, Trend, TimeSinceFirstMaximum, TimeSinceFirstMinimum, TimeSinceLastMaximum, TimeSinceLastMinimum, Quantile, Slope, Ewa, EwaFraction, Ews, EwsCount, EwmaTrend, WindowSum, WindowCount, WindowFraction, WindowMean, WindowMax, WindowMin, WindowStd
all basic + advanced

Можно собрать собственный набор:

from featminer import one_to_many_pipeline
from featminer.formulas import Count, Ews, Quantile, Slope, WindowSum

FORMULAS = (
    Count(),
    WindowSum(days=7),
    WindowSum(days=30),
    WindowSum(days=90),
    Ews(half_life_days=7),
    Ews(half_life_days=30),
    Quantile(q=0.33),
    Quantile(q=0.8),
    Slope(last_k=10),
    Slope(last_k=100),
)

features = one_to_many_pipeline(
    df=transactions,
    aggregation_key="client_id",
    target_col="target",
    event_times=("event_date",),
    prediction_time="prediction_date",
    formulas=FORMULAS,
)

Формулы без числовых параметров тоже передаются экземплярами: Count(), Mean(), EventRange(), IntervalMean() и так далее.

Готовый набор можно расширить явно:

from featminer.formulas import EventRange, WindowSum
from featminer.formulas.sets import BASIC_FORMULAS

FORMULAS = (
    *BASIC_FORMULAS,
    EventRange(),
    WindowSum(days=14),
    WindowSum(days=60),
)

Time-series формулы участвуют в генерации только при наличии event_times.

Производные колонки

Параметр derived_columns управляет арифметическими колонками, которые создаются до применения формул:

from featminer import DerivedColumnsConfig, one_to_many_pipeline

features = one_to_many_pipeline(
    df=transactions,
    aggregation_key="client_id",
    target_col="target",
    derived_columns=DerivedColumnsConfig(
        days_between=True,
        differences=True,
        ratios=False,
        conditions=True,
        max_condition_columns=1,
    ),
)

Параметры DerivedColumnsConfig

Параметр Тип По умолчанию Описание
days_between bool True Создавать разности в днях между всеми парами календарных дат.
differences bool False Создавать попарные разности совместимых числовых колонок.
ratios bool False Создавать безопасные попарные отношения совместимых числовых колонок.
conditions bool True Разрешать условные признаки, рассчитанные только по строкам, соответствующим категориальным условиям. False сохраняет обычные агрегаты без фильтрации.
max_condition_columns int 1 Максимальное число колонок в одном условии. Значение 2, например, разрешает условие status="active" and channel="web".

Значения по умолчанию сохраняют базовый режим:

DerivedColumnsConfig(
    days_between=True,
    differences=False,
    ratios=False,
    conditions=True,
    max_condition_columns=1,
)

conditions=False отключает условные признаки, но сохраняет обычные агрегаты без фильтрации. max_condition_columns задаёт максимальное число колонок в одном условии.

Подробнее о временных параметрах: Защита от утечки из будущего.

Подробнее о выборе AUC или корреляции Пирсона: Конфигурация отбора признаков.

Список формул

Формула Обязательные временные колонки Что считает
Fraction Долю строк внутри объекта, где выполнено условие.
Count Количество строк внутри объекта, где выполнено условие.
Max Максимум значения внутри объекта.
Sum Сумму значений внутри объекта.
Mean Среднее значение внутри объекта.
Min Минимум значения внутри объекта.
Nunique Количество уникальных значений внутри объекта.
Std Стандартное отклонение внутри объекта.
First event_times Значение в первой строке объекта по event_time.
Last event_times Значение в последней строке объекта по event_time.
Slope(last_k=...) event_times Линейный тренд последних last_k значений; 0 использует всю историю. Набор по умолчанию: 0, 10, 100.
Trend event_times + prediction_time Строит линейную регрессию значения по возрасту события и возвращает значение линии в prediction_time.
EwmaTrend(half_life_days=...) event_times + prediction_time Взвешенный Trend: вес события уменьшается вдвое каждые half_life_days. Набор по умолчанию: 1, 7, 30, 90, 365 дней.
Quantile(q=...) Квантиль значения внутри объекта. Набор q по умолчанию: 0.01, 0.05, 0.10, 0.25, 0.50, 0.75, 0.90, 0.95, 0.99; можно передать собственный q от 0 до 1.
Kurtosis Эксцесс распределения значений внутри объекта.
Skew Асимметрию распределения значений внутри объекта.
Mode Самое частое значение внутри объекта.
NumMax Количество строк со значением, равным максимуму внутри объекта.
NumMin Количество строк со значением, равным минимуму внутри объекта.
Ewa(half_life_days=...) event_times + prediction_time Экспоненциально взвешенное среднее. Набор по умолчанию: 1, 7, 30, 90, 365 дней.
EwaFraction(half_life_days=...) event_times + prediction_time Экспоненциально взвешенную долю строк, удовлетворяющих условию. Набор по умолчанию: 1, 7, 30, 90, 365 дней.
Ews(half_life_days=...) event_times + prediction_time Экспоненциально взвешенную сумму. Набор по умолчанию: 1, 7, 30, 90, 365 дней.
EwsCount(half_life_days=...) event_times + prediction_time Экспоненциально взвешенное количество событий. Набор по умолчанию: 1, 7, 30, 90, 365 дней.
EventRange event_times Время между первым и последним событием объекта.
IntervalMean event_times Средний интервал между соседними событиями.
IntervalMin event_times Минимальный интервал между соседними событиями.
IntervalMax event_times Максимальный интервал между соседними событиями.
IntervalStd event_times Стандартное отклонение интервалов между соседними событиями.
WindowSum(days=...) event_times + prediction_time Сумму значений в окне перед текущим событием. Набор по умолчанию: 1, 7, 30, 90, 365, 730, 1095 дней.
WindowCount(days=...) event_times + prediction_time Количество событий в окне. Набор по умолчанию: 1, 7, 30, 90, 365, 730, 1095 дней.
WindowFraction(days=...) event_times + prediction_time Долю строк, удовлетворяющих условию, в окне. Набор по умолчанию: 1, 7, 30, 90, 365, 730, 1095 дней.
WindowMean(days=...) event_times + prediction_time Среднее значение в окне перед текущим событием. Набор по умолчанию: 1, 7, 30, 90, 365, 730, 1095 дней.
WindowMax(days=...) event_times + prediction_time Максимум значения в окне перед текущим событием. Набор по умолчанию: 1, 7, 30, 90, 365, 730, 1095 дней.
WindowMin(days=...) event_times + prediction_time Минимум значения в окне перед текущим событием. Набор по умолчанию: 1, 7, 30, 90, 365, 730, 1095 дней.
WindowStd(days=...) event_times + prediction_time Стандартное отклонение в окне перед текущим событием. Набор по умолчанию: 1, 7, 30, 90, 365, 730, 1095 дней.
Ratio Зависит от формул в правилах Декларативные отношения, задаваемые списком RatioRule. Каждое правило независимо определяет допустимые формулы и колонки числителя и знаменателя.
TimeSinceFirstMaximum event_times + prediction_time Время от первого максимума до опорного события объекта.
TimeSinceLastMaximum event_times + prediction_time Время от последнего максимума до опорного события объекта.
TimeSinceFirstMinimum event_times + prediction_time Время от первого минимума до опорного события объекта.
TimeSinceLastMinimum event_times + prediction_time Время от последнего минимума до опорного события объекта.
FirstCategory event_times Бинарный признак: первая категория по event_time равна выбранному значению.
LastCategory event_times Бинарный признак: последняя категория по event_time равна выбранному значению.

Настраиваемые отношения Ratio

Ratio создаёт признаки вида «числитель / знаменатель» по декларативному списку правил. Декартово произведение строится только внутри одного RatioRule: формулы из разных правил никогда не смешиваются. Так можно явно разрешить Ews / Ews и WindowMean / WindowMean, не создавая Ews / WindowMean.

Объект или параметр Значение по умолчанию Назначение
Ratio.rules Обязательный Непустой список независимых правил деления.
RatioRule.numerator Обязательный Формулы и колонки, разрешённые в числителе.
RatioRule.denominator Обязательный Формулы и колонки, разрешённые в знаменателе.
RatioRule.same_column False False строит отношения разных колонок; True использует одну колонку с обеих сторон.
RatioRule.same_family True Оставляет только пары одного семейства агрегаций; несовместимые пары молча пропускаются.
RatioRule.columns None Общий список колонок при same_column=True; None разрешает все совместимые колонки.
RatioSide.formulas Sum, стандартные Ews и WindowSum Непустой список формул с параметрами, например WindowSum(days=30).
RatioSide.columns None Колонки одной стороны при same_column=False; None разрешает все совместимые колонки.

В компонентах отношения поддерживаются Sum, Count, Mean, Ews, EwsCount, EwaFraction, WindowSum, WindowCount, WindowFraction и WindowMean.

Если RatioSide.formulas не передан, сторона включает Sum(), все стандартные Ews(half_life_days=...) (1, 7, 30, 90, 365) и все стандартные WindowSum(days=...) (1, 7, 30, 90, 365, 730, 1095).

По умолчанию совместимы Sum ↔ WindowSum, Count ↔ WindowCount, Mean ↔ WindowMean, а также одинаковые формулы Ews, EwsCount, EwaFraction и WindowFraction. Например, Sum / Mean и Ews / WindowSum пропускаются. Для намеренного отношения разных семейств передайте same_family=False в соответствующий RatioRule.

Пример создаёт WindowSum / Sum для разных колонок, а также две изолированные группы отношений одной колонки на разных горизонтах:

from featminer import one_to_many_pipeline
from featminer.formulas import (
    Ews,
    Ratio,
    RatioRule,
    RatioSide,
    Sum,
    WindowMean,
    WindowSum,
)

ratios = Ratio(
    rules=[
        RatioRule(
            numerator=RatioSide(
                formulas=[WindowSum(days=7), WindowSum(days=30)],
                columns=["payments"],
            ),
            denominator=RatioSide(
                formulas=[Sum()],
                columns=["income"],
            ),
        ),
        RatioRule(
            numerator=RatioSide(formulas=[Ews(half_life_days=7)]),
            denominator=RatioSide(formulas=[Ews(half_life_days=30)]),
            columns=["balance"],
            same_column=True,
        ),
        RatioRule(
            numerator=RatioSide(formulas=[WindowMean(days=7)]),
            denominator=RatioSide(formulas=[WindowMean(days=30)]),
            columns=["balance"],
            same_column=True,
        ),
    ]
)

features = one_to_many_pipeline(
    df=events,
    target_col="target",
    aggregation_key="client_id",
    event_times=("event_date",),
    prediction_time="prediction_date",
    formulas=(ratios,),
)

В первом правиле одинаковая колонка с двух сторон исключается. Во втором и третьем правилах колонка должна входить в общий RatioRule.columns. Если нужны все подходящие колонки, соответствующий columns можно не передавать.

Параметры формул

  • q — квантиль от 0 до 1 для Quantile;
  • last_k — число последних событий для Slope; 0 означает всю доступную историю;
  • half_life_days — период полураспада веса в днях для Ewa, EwaFraction, Ews, EwsCount и EwmaTrend;
  • days — размер временного окна в днях для семейства Window*.

First и Last появляются в генерации только если в one_to_many_pipeline() передан параметр event_times. Без него pipeline не знает порядок исторических строк и использует только формулы, которым время не требуется.

Тренд к моменту прогноза

Trend и EwmaTrend используют возраст события относительно prediction_time: текущее время имеет координату 0, прошлые события — положительный возраст. Обе формулы аппроксимируют значения линией value = intercept + slope * age и возвращают intercept, то есть оценку значения непосредственно в момент прогноза. В отличие от них, Slope возвращает сам коэффициент наклона.

EwmaTrend строит ту же регрессию с весом 0.5 ** (age / half_life_days). Поэтому событие возрастом ровно один период полураспада получает вес 0.5, два периода — 0.25. События после prediction_time не участвуют в расчёте. Если у всех доступных событий одинаковое время, обе формулы возвращают среднее значение: обычное или взвешенное соответственно.

Готовый advanced-набор содержит периоды 1, 7, 30, 90 и 365 дней. Собственный положительный целочисленный период можно передать явно:

from featminer.formulas import EwmaTrend

FORMULAS = (
    EwmaTrend(half_life_days=3),
    EwmaTrend(half_life_days=14),
    EwmaTrend(half_life_days=180),
)

Интервалы между событиями

IntervalMean, IntervalMin, IntervalMax и IntervalStd сначала применяют условия формулы, затем сортируют выбранные события внутри объекта и вычисляют разности между соседними временными метками. Поэтому условие status = "overdue" описывает интервалы именно между просроченными платежами, а не между всеми платежами.

Для календарных дат интервалы измеряются в днях, включая дробную часть суток. Для RelativeTime сохраняется единица исходной временной оси. Одинаковые временные метки образуют нулевой интервал. Если у объекта осталось меньше двух событий, интервальная статистика не определена.

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