Po co w ogóle bawić się w feature engineering?
Silne modele, słabe dane: dlaczego surowa tabelka rzadko wystarcza
Modele drzewiaste (Gradient Boosting, XGBoost, LightGBM, CatBoost, Random Forest) potrafią wyciągnąć zaskakująco dużo informacji z surowych danych tabelarycznych. W wielu benchmarkach „z pudełka” wygrywają z rozbudowanymi sieciami neuronowymi. W praktycznych systemach produkcyjnych surowa tabelka rzadko jest jednak optymalnym wejściem. Dane biznesowe są nierówne: zawierają braki, dziury czasowe, kody wewnętrzne, ID, wartości odstające i cechy, które wprost nie mają sensu bez dodatkowej obróbki.
Na tym etapie wiadomo jedno: sam wybór algorytmu nie załatwia sprawy. Przy tej samej architekturze modelu różnica między naiwnym użyciem surowych kolumn a przemyślanym zestawem cech potrafi być większa niż zmiana algorytmu na „bardziej zaawansowany”. Co pozostaje nieoczywiste, to odpowiedź na pytanie: które cechy naprawdę pomagają, a które jedynie doklejają szum i komplikują pipeline?
Feature engineering dla tabular data jest próbą nadania surowym kolumnom struktury: wyciągnięcia z nich tych informacji, które rzeczywiście wpływają na decyzję biznesową. To nie jest sztuka dodania jak największej liczby kolumn, tylko celowe przekształcenie tabeli w zbiór sygnałów, z którymi model radzi sobie stabilnie, także po wdrożeniu.
Więcej cech vs bardziej informacyjne cechy
Łatwo wpaść w pułapkę myślenia: „im więcej cech, tym lepiej, a model sam wybierze, co jest istotne”. W krótkim horyzoncie (na zbiorze walidacyjnym) model rzeczywiście może zyskać kilka punktów metryki po dołożeniu dziesiątek nowych zmiennych. Po wdrożeniu taki system bywa jednak niestabilny: część cech będzie zależna od przypadkowych wzorców w danych historycznych, których w przyszłości już nie będzie.
Różnica jest subtelna, ale kluczowa:
- „Więcej cech” oznacza często powielanie informacji w różnych wariantach, tworzenie dziesiątek iloczynów, binningów i wskaźników bez wyraźnej hipotezy.
- „Bardziej informacyjne cechy” to takie, które mają jasne znaczenie biznesowe i wspierają konkretną decyzję: np. „czas od ostatniego zakupu”, „udział zakupów w promocji w ostatnich 30 dniach”, „odchylenie dziennej sprzedaży od własnej mediany klienta”.
Modele drzewiaste dobrze radzą sobie z redundancją, ale nie są magiczne. Nadmiar głośnych, losowych lub słabo związanych z targetem cech zwiększa ryzyko overfittingu, utrudnia debugowanie i wydłuża predykcje. W modelach liniowych i prostych sieciach wielowymiarowość i korelacje między cechami szybko zaczynają sprawiać problemy.
Jakość modelu, stabilność w czasie i koszt utrzymania
Feature engineering działa jednocześnie w trzech płaszczyznach:
- Jakość predykcji – lepsze cechy to zwykle wyższe AUC/ROC, niższy błąd MAE/MSE, lepsza kalibracja. Często wystarczy kilka dobrze dobranych agregacji, by prosty model logistic regression dorównał skomplikowanemu gradient boostingowi bez nich.
- Stabilność w czasie – pewne cechy są bardzo wrażliwe na zmianę rozkładu danych (np. agresywny target encoding konkretnych ID), inne są stabilne (np. proporcje, wskaźniki recency/tenure, cechy sezonowe). W środowisku produkcyjnym to stabilność jest często ważniejsza niż dodatkowy ułamek procenta na walidacji.
- Złożoność utrzymania – cechy trzeba policzyć zarówno na treningu, jak i w inference. Każde okno czasowe, join, agregacja czy encoder to dodatkowy element pipeline’u. Źle zaprojektowany feature engineering prowadzi do „spaghetti pipelines”: trudnych w debugowaniu, wolnych, pełnych duplikacji logiki.
Z perspektywy inżynierskiej feature engineering dla tabular data to kompromis między jakością modelu a prostotą procesu. Jeżeli dla przyrostu metryki o 0,1 punktu trzeba zbudować dziesięć dodatkowych joinów, raportów i tabel pośrednich, biznes może woleć prostsze rozwiązanie, które da się utrzymać małym zespołem.
Przykład: prosty model z dobrymi cechami vs skomplikowana sieć na surowych danych
W projektach scoringowych spotyka się sytuację, w której:
- prosty model logistyczny z kilkudziesięcioma ręcznie przygotowanymi cechami (agregacje po kliencie, wskaźniki wykorzystania limitu, relacje dochód/zobowiązania) osiąga stabilne, przewidywalne wyniki,
- a złożona sieć neuronowa karmiona surową tabelą transakcji zyskuje nieco wyższy wynik na walidacji, lecz traci go po kilku miesiącach działania w produkcji z powodu driftu i trudności w utrzymaniu pipeline’u sekwencyjnego.
W takim zestawieniu wygrywa często prostszy model z dojrzałym feature engineeringiem. Nie dlatego, że sieci są złe, tylko dlatego, że koszt przygotowania i monitoringu porządnego modelu sekwencyjnego przewyższa zysk biznesowy z kilku dodatkowych punktów na metryce. W klasycznym tabular data feature engineering jest narzędziem, które pozwala „wycisnąć” dane przy mniejszym ryzyku operacyjnym.
Zrozumienie problemu i danych – fundament przed pierwszą transformacją
Jaką decyzję wspiera model i jaki ma być poziom agregacji?
Punktem startowym nie jest algorytm, tylko pytanie: jaką decyzję biznesową ma wesprzeć model? Feature engineering dla tabular data musi być ściśle związany z granularity problemu:
- Klasyfikacja binarna (np. czy klient wypowie umowę w ciągu 90 dni): cechy muszą odzwierciedlać zachowanie klienta w oknie obserwacji przed datą decyzji.
- Regresja (np. prognoza miesięcznej sprzedaży produktu): cechy powinny uchwycić sezonowość, trend i specyfikę produktu.
- Scoring ryzyka (np. prawdopodobieństwo defaultu): kluczowe są wskaźniki stabilne i interpretowalne, odporne na manipulacje oraz regulacje.
- Rekomendacje (np. produkt do cross-sellu): warto łączyć cechy klienta z cechami produktu i ich relacją w czasie.
Granularity, czyli poziom, na którym podejmowana jest decyzja, decyduje o tym, jak tworzyć cechy. Inny zestaw cech buduje się dla modeli „na poziomie transakcji”, inny dla modeli „na poziomie klienta”. Przy tej samej tabeli surowych zdarzeń da się zbudować dwa modele: jeden przewidujący fraud na pojedynczej transakcji, drugi przewidujący ryzyko klienta – i każdy będzie wymagał innej logiki agregacji.
Typy zmiennych a możliwe transformacje
Przed pierwszym kodowaniem warto jednoznacznie oznaczyć typ każdej kolumny. Typ logiczny ma tutaj pierwszeństwo przed typem technicznym w bazie:
- Zmiennie kategoryczne nominalne – wartości bez naturalnego porządku (np. kraj, kanał sprzedaży, typ urządzenia). Tu wchodzą w grę encodingi (one-hot, target/frequency, hashing), czasem grupowanie rzadkich kategorii.
- Zmiennie kategoryczne porządkowe – mają naturalny porządek (np. poziom ryzyka: niski/średni/wysoki, rating). Przydatny może być ordinal encoding lub mapping do liczb (ale z ostrożnością, by nie narzucać sztucznego dystansu).
- Zmiennie liczbowe – kwoty, liczebności, wskaźniki. Możliwe są skalowania, transformacje log/sqrt, binning, tworzenie proporcji, różnic względem średniej, statystyki z okien czasowych.
- Zmiennie czasowe – daty, timestampy, czas trwania. Tu zaczyna się cała dziedzina cech czasowych: dzień tygodnia, sezonowość, okna rolling, recency.
- ID i klucze techniczne – identyfikatory klientów, kont, transakcji, kampanii. Zwykle nie używa się ich wprost jako cech, tylko jako elementów do agregacji lub źródło high-cardinality features.
- Tekst krótkiej formy (np. tytuł aukcji, opis kategorii) – w klasycznym tabular data często sprowadza się je do prostych sygnałów (długość, liczba słów, słowa kluczowe) lub zagregowanych embeddingów.
Takie ręczne oznaczenie typów na etapie EDA oszczędza czas na późniejsze eksperymenty. Bez tego łatwo np. użyć ID jak ciągłej liczby, co kończy się kompletnym szumem, albo potraktować datę jak zwykłą liczbę, ignorując strukturę kalendarza.
EDA pod feature engineering: rozkłady, braki, korelacje, dziury czasowe
Eksploracja danych przy nastawieniu na feature engineering różni się od klasycznego EDA pod raport. Kluczowe pytania brzmią: czy dane są wystarczająco stabilne, by zbudować na nich cechy, oraz gdzie czai się potencjalne data leakage?
- Rozkłady zmiennych – silnie skośne rozkłady (np. kwoty transakcji) sugerują transformacje log lub sqrt, a także stosowanie miar odpornych na outliery (percentyle zamiast średniej).
- Brakujące wartości – skala braków w kolumnach decyduje, czy lepiej imputować, czy w ogóle porzucić zmienną. W niektórych przypadkach sam fakt braku jest informacją, którą można zakodować jako osobną cechę.
- Kolinearność – mocno powiązane zmienne numeryczne (np. „kwota brutto” i „kwota netto”) mogą zwiększać niestabilność modeli liniowych. Dobrą praktyką bywa przejście na cechy wtórne, np. ratio brutto/netto.
- Dziury i nielogiczności czasowe – przerwy w danych, brakujące dni, zdarzenia wychodzące poza sensowny zakres (transakcja po dacie wypowiedzenia) wskazują na konieczność czyszczenia i dostosowania okien czasowych.
Taka diagnostyka prowadzi wprost do decyzji o tym, jakie transformacje mają potencjał, a które kolumny są na tyle uszkodzone lub niestabilne, że lepiej ich nie używać w ogóle.
Wczesne wykrywanie data leakage
Data leakage (a zwłaszcza target leakage) to jedna z głównych przyczyn „magicznych” wyników modelu na walidacji i rozczarowania po wdrożeniu. Źródła przecieku bywają bardzo prozaiczne:
- kolumny rejestrowane po wystąpieniu zdarzenia docelowego (np. „data windykacji” przy przewidywaniu defaultu),
- flagowe pola wynikające z decyzji biznesowych zależnych od tego samego targetu (np. „czy klient otrzymał ofertę retencyjną”).
Na etapie oględzin danych warto zaznaczyć wszystkie kolumny, których wartość mogła być obliczona lub uzupełniona później niż moment, w którym model ma „podjąć decyzję”. Jeżeli taka kolumna będzie użyta do feature engineeringu, trzeba ją zrekonstruować tak, by wykorzystywała tylko informacje dostępne do momentu decyzji – w przeciwnym razie metryka będzie zawyżona.

Podstawowe transformacje numeryczne, które prawie zawsze się przydają
Skalowanie: kiedy standard scaling, kiedy min-max, a kiedy robust
Skalowanie cech numerycznych ma różny wpływ w zależności od klasy modeli:
- Modele drzewiaste – w zasadzie odporne na skalę cech, bo decyzje w węzłach opierają się na porównaniach (czy wartość < próg), a nie na odległościach. Skalowanie może być przydatne głównie ze względów numerycznych lub gdy te same cechy będą użyte również w innych modelach.
- Modele liniowe (regresja logistyczna, regresja liniowa z regularizacją) – wymagają skalowania, by współczynniki były porównywalne, a optymalizacja stabilna. Bez tego jedna cecha o dużej skali może zdominować proces uczenia.
- Sieci neuronowe – wrażliwe na skalę wejść. Standard scaling (odjęcie średniej, podzielenie przez odchylenie) lub min-max scaling przyspieszają trening i stabilizują gradienty.
Najczęściej spotykane metody to:
- StandardScaler – przekształca cechę do rozkładu o średniej 0 i odchyleniu 1. Dobrze działa przy rozkładach zbliżonych do normalnych.
- MinMaxScaler – przeskalowuje cechę do zadanego przedziału, najczęściej [0, 1]. Przydatny, gdy model wymaga wejść w określonym zakresie (np. niektóre sieci).
- RobustScaler – korzysta z mediany i IQR (interquartile range), lepiej radzi sobie z outlierami.
Najważniejsza zasada operacyjna: skalery uczymy wyłącznie na zbiorze treningowym, a później stosujemy ten sam obiekt do transformacji walidacji, testu i danych produkcyjnych. Trenowanie skalerów „na całości” to prosty sposób na wprowadzenie lekkiego leakage, który potrafi podbić wyniki na walidacji.
Transformacje log, sqrt, rank i radzenie sobie ze skośnymi rozkładami
Duża część cech numerycznych ma rozkład silnie skośny: wiele małych wartości i pojedyncze bardzo duże. Przykładami są kwoty transakcji, przychody, liczba odwiedzin. Modele liniowe i sieci neuronowe lepiej działają, gdy rozkład jest bliższy normalnemu, a zmienność względna staje się ważniejsza niż absolutna.
Typowe transformacje to:
- log(x + c) – gdzie c to mała stała, np. 1, by uniknąć log(0). Logarytm zmniejsza wpływ dużych wartości odstających i podkreśla różnice w niższym zakresie.
Winsoryzacja, clipping i obchodzenie się z outlierami
Silnie odstające obserwacje to problem nie tylko estetyczny na wykresach. W modelach liniowych i sieciach potrafią przejąć kontrolę nad parametrami, a nawet w modelach drzewiastych zmieniają strukturę podziałów. Pytanie brzmi: które wartości są faktycznymi błędami, a które tylko rzadkimi, ale prawdziwymi przypadkami?
W praktyce stosuje się kilka prostych zabiegów:
- Clipping – przycięcie wartości do określonego przedziału, np. [1. percentyl, 99. percentyl]. Wyszczególnione outliery nie znikają, ale przestają ciągnąć rozkład. Sprawdza się przy cechach, gdzie ekstrema nie są kluczowe dla decyzji.
- Winsoryzacja – podobna do clippingu, ale skrajne wartości zastępuje się właśnie wartościami percentyli (np. 1. i 99.). Dzięki temu rozkład staje się bardziej „przycięty”, ale nie traci całkowicie informacji o położeniu skrajnych punktów.
- Log + clipping – przy skośnych rozkładach często łączy się logarytmowanie z lekkim clippingiem na skrajach. Efekt jest zwykle stabilny w treningu i mniej wrażliwy na pojedyncze anomalie.
W systemach produkcyjnych decyzja o tym, jak traktować outliery, bywa biznesowa. Jeżeli model fraudowy ma reagować właśnie na ekstremalne, dziwne transakcje, agresywne przycinanie może ukryć najciekawsze sygnały. Z kolei w prognozach sprzedaży jednorazowy „skok” spowodowany kampanią lepiej spłaszczyć lub oznaczyć osobną flagą niż pozwolić, by definiował całą krzywą popytu.
Binning, kwantyle i efekt „robust linearisation”
Nie każda zależność między cechą a targetem jest gładka i liniowa. Czasem modelowi łatwiej podjąć decyzję na podstawie kilku sensownych przedziałów niż ciągłej wartości. To podejście przypomina ręczne „odrysowanie” kształtu zależności.
Typowe techniki:
- Binning równoodległy – zakres wartości dzielony jest na równe odcinki (np. co 100 zł). Proste, ale przy mocno skośnych danych większość obserwacji ląduje w jednym, dwóch koszykach.
- Binning kwantylowy – podział według percentyli (np. decyle). W każdym koszyku jest podobna liczba obserwacji. To naturalny kandydat, gdy cecha ma duży rozrzut i wiele outlierów.
- Binning nadzorowany (target-based) – granice koszyków dobierane tak, by maksymalizować różnice w targetach między przedziałami (np. klasyczny WoE binning w scoringu). Daje bardziej informacyjne koszyki kosztem większego ryzyka przeuczenia.
Po zbinowaniu można pójść w dwie strony: użyć koszyka jako zmiennej porządkowej (1, 2, 3…) albo zakodować go one-hot, jeżeli zależność z targetem jest nieliniowa i „schodkowa”. W modelach regulowanych (np. kredytowych) binning często łączy się z ręcznym nadaniem interpretowalnych etykiet („niska kwota”, „średnia”, „wysoka”).
Proporcje, różnice i cechy relatywne zamiast „gołych” wartości
W wielu problemach liczy się nie tyle absolutna wartość, ile relacja do tła: średniej, typowego poziomu, innej wielkości. Dwie osoby zarabiające tę samą kwotę netto mogą mieć zupełnie inne ryzyko kredytowe, jeśli jedna ma dużo wyższe koszty stałe. To jest właśnie miejsce na cechy relatywne.
Kilka schematów, które często dają realny zysk:
- Ratio – stosunek dwóch kwot, np.
saldo / limit,dochód / rata,wizyty_mobilne / wszystkie_wizyty. Modele uczą się na nich szybciej niż na surowych licznikach. - Odchylenie od średniej – różnica względna lub bezwzględna względem typowego poziomu, np.
wydatki_klienta - średnie_wydatki_segmentu. Taka cecha pokazuje, kto zachowuje się „nietypowo” jak na swoją grupę. - Udziały w strukturze – np. udział kategorii „spożywcze” w koszyku klienta:
kwota_spożywcze / kwota_ogółem. W segmentacji i rekomendacjach takie udziały są często bardziej stabilne niż nominalne wartości.
Wdrożeniowo kluczowa jest spójność: jeżeli ratio wymaga średniej po segmencie, ta średnia musi być wyliczana na bieżąco (online lub w batchu) tak samo w treningu i w produkcji. Inaczej uzyskamy „pływające” cechy i niestabilny model.
Rank, percentyle i monotoniczne przekształcenia
Przy cechach, które mają mało interpretowalną skalę, ranking bywa prostym sposobem na zredukowanie wpływu outlierów i nieliniowości. Zamiast kwoty transakcji używa się jej pozycji w ułożonym rosnąco zbiorze (lub frakcji: rank/n).
Przykładowe zastosowania:
- Rank wewnątrz grupy – np. pozycja klienta pod względem wydatków w danym mieście, segmencie, roczniku. Tak zbudowana cecha działa podobnie do „lokaty” w grupie rówieśniczej.
- Percentyle globalne – klient z wydatkami w 95. percentylu ma jasne znaczenie dla modelu, nawet jeśli poziom inflacji czy cen się zmienia. Percentyle lepiej znoszą zmiany skali w czasie.
Monotoniczne przekształcenia (log, sqrt, rank, percentyle) mają jedną wspólną cechę: zachowują porządek wartości. Dlatego nadają się wszędzie tam, gdzie ważne jest, kto jest „większy”, a nie o ile większy.
Zmiennie kategoryczne: encoding, który nie psuje modelu
One-hot encoding: kiedy wystarczy prosta macierz wskaźników
One-hot encoding to najprostsza, ale wciąż bardzo użyteczna technika kodowania kategorii. Każda kategoria staje się osobną kolumną 0/1. Działa dobrze, gdy:
- liczba kategorii jest mała lub umiarkowana,
- pojawienie się konkretnej kategorii ma własne znaczenie (np. kraj, kanał sprzedaży),
- model to algorytm liniowy lub drzewiasty o umiarkowanej skali.
W produkcji kluczowe są dwa szczegóły:
- Grupowanie rzadkich kategorii – kategorie z bardzo małą liczbą obserwacji powinny być zmapowane do jednej klasy „OTHER” lub kilku większych grup. Chroni to przed przeuczeniem i problemami z wydajnością.
- Strategia dla unknown/nowych kategorii – w trakcie życia systemu pojawią się nowe wartości (np. nowy kanał sprzedaży). Potrzebna jest z góry ustalona reguła: mapowanie ich na „OTHER” lub osobny bit „UNKNOWN”.
W środowisku big data koszt one-hot rośnie szybko. Wtedy część zmiennych lepiej zakodować inną metodą, one-hot zostawiając tylko dla tych kilku najważniejszych, biznesowo zrozumiałych pól.
Target encoding, mean encoding i pułapki przecieku
Target encoding (mean encoding) polega na zastąpieniu kategorii średnią wartością targetu w tej kategorii. Przykładowo: jeżeli w danym kraju odsetek churnu wynosi 15%, a w innym 5%, model otrzymuje bezpośrednio te liczby zamiast suchych flag.
Daje to zwykle wyraźny wzrost jakości przy:
- zmiennych o średniej lub dużej liczbie kategorii,
- modelach liniowych i prostszych drzewach,
- nierównomiernych rozkładach targetu między kategoriami.
Problemem jest natomiast ryzyko przeuczenia. Kategoria, która pojawia się kilka razy, może dostać ekstremalną wartość średniej targetu i „nauczyć się” szumu. Dlatego w praktyce stosuje się kilka zabezpieczeń:
- Smoothing – mieszanie średniej dla kategorii ze średnią globalną z wagą zależną od liczebności. Im mniej rekordów w kategorii, tym bliżej do średniej globalnej.
- K-fold target encoding – wartość dla rekordów z danej foldy wylicza się na podstawie danych z pozostałych fold, nigdy na sobie samych. To minimalizuje przeciek do walidacji.
- Regularizacja przez szum – do zakodowanej wartości dodaje się mały losowy noise. Zmniejsza to szansę, że model przyczepi się do dokładnej wartości liczbowej.
W pipeline’ach produkcyjnych target encoding wymaga starannego zaimplementowania: kodowanie musi być oparte wyłącznie na historii dostępnej w momencie decyzji, a wartości dla nowych kategorii rekonstruowane z jakiejś sensownej reguły (np. średnia globalna, średnia po segmencie).
Frequency / count encoding: tania informacja o „popularności”
Frequency encoding zamienia kategorię na częstość jej występowania (lub liczność). To rodzaj kompromisu między one-hot a target encodingiem: nie używa informacji o targetcie, więc trudniej tu o przeciek, ale nadal wprowadza uporządkowanie kategorii.
Typowe zastosowania:
- pola o bardzo dużej liczbie kategorii (np. ID sprzedawcy, nazwa kampanii),
- sytuacje, w których sama popularność jest sygnałem (rzadkie kampanie mogą być testowe, masowe – standardowe),
- modele drzewiaste, które dobrze czytają takie porządki.
W praktyce zazwyczaj używa się log-count (np. log(1 + count)), aby zmniejszyć wpływ najbardziej popularnych kategorii. Częstotliwości liczy się na zbiorze treningowym, a w produkcji aktualizuje okresowo w batchu, jeśli rozkład kategorii mocno się zmienia.
Hashing trick i radzenie sobie z high-cardinality w dużych systemach
W systemach z ogromną liczbą kategorii (reklama online, logi zdarzeń) utrzymanie pełnego słownika wartości jest kosztowne. Hashing trick proponuje prostsze podejście: każdą kategorię przepuszcza się przez funkcję hashującą i obcina do ustalonego rozmiaru przestrzeni (np. 218 wymiarów).
Plusy są jasne:
- nie trzeba trzymać słownika kategorii,
- pipeline może obsłużyć dowolne nowe wartości bez zmian,
- koszt pamięci jest kontrolowany z góry.
Minus to kolizje: różne kategorie trafią do tego samego „wiadra”. W praktyce przy rozsądnym rozmiarze przestrzeni i modelach drzewiastych lub liniowych wiele zastosowań toleruje ten efekt. W części systemów łączy się hashing z dodatkowymi prostymi cechami (np. długość ciągu, rodzaj patternu), aby złagodzić skutki kolizji.
Embeddings dla kategorii: podejście inspirowane NLP
Dla bardzo bogatych, relacyjnych kategorii (ID użytkownika, ID produktu, merchant) coraz częściej stosuje się wektorowe reprezentacje – embeddings. Uczy się je zwykle w jednej z dwóch konfiguracji:
- Współuczenie z modelem głównym – warstwa embeddingu jest pierwszą warstwą sieci (np. w tabular NN), aktualizowaną podczas treningu end-to-end.
- Pre-trening na zadaniu pomocniczym – np. „produkty kupowane razem” (jak w word2vec), a potem wczytanie embeddingów jako gotowych cech do modelu tabularnego.
To podejście skaluje się lepiej niż one-hot przy setkach tysięcy kategorii i odkrywa podobieństwa, których prostsze encodery nie uchwycą (produkty kupowane razem stają się „bliskie” w przestrzeni). Wdrożeniowo wymagane jest jednak spójne mapowanie ID na wektory oraz strategia dla nowych ID (np. wektor inicjalizowany średnią lub losowo, potem aktualizowany).

Dane czasowe i sekwencyjne w tabelkach: cechy, które realnie pomagają
Rozbijanie daty i czasu na komponenty kalendarzowe
Surowy timestamp rzadko jest sensowną cechą. Zwykle interesują nas struktury kalendarzowe i cykle. Z pojedynczej daty można wyciągnąć:
- Składowe kalendarzowe – rok, miesiąc, dzień miesiąca, dzień tygodnia, tydzień roku, kwartał, czy dzień roboczy vs. weekend.
- Pozycję w cyklu – godzina dnia, część dnia (np. noc/poranek/popłudnie), pora roku.
- Święta i dni specjalne – czy dzień jest świętem, czy przypada tuż przed/po święcie, okres wakacyjny. W retailu i travelu to często jedna z najważniejszych grup cech.
W sekwencjach silnie cyklicznych (godzina, dzień tygodnia) dobrym pomysłem są cechy sinus/cosinus, np. sin(2π * godzina / 24), cos(2π * godzina / 24). Dzięki temu model widzi, że 23:00 i 1:00 są blisko siebie, czego zwykłe kodowanie liczbowej godziny nie oddaje.
Recency, frequency, monetary – klasyczne RFM w wersji produkcyjnej
RFM (Recency–Frequency–Monetary) to stare narzędzie marketingowe, ale w modelach tabularnych sprawdza się wyjątkowo dobrze. Wyciąga trzy proste wymiary zachowania klienta:
- Recency – ile czasu minęło od ostatniego zdarzenia (zakupu, logowania, kontaktu z BOK). Klient „świeży” zachowuje się inaczej niż ten, który nie był aktywny od miesięcy.
- Frequency – jak często w danym oknie czasowym pojawiają się zdarzenia (liczba wizyt, zakupów, zgłoszeń). To pierwszy miernik zaangażowania.
- Monetary – łączna wartość (przychód, marża, kwota transakcji). W churnie czy cross-sellu bardziej wartościowi klienci mogą być traktowani inaczej niż ci marginalni.
Okna czasowe i cechy „rolling” na podstawie historii zdarzeń
Sam RFM daje tylko wycinek zachowania. W systemach opartych na logach, transakcjach czy eventach kluczowa staje się dynamika w określonych oknach: ostatnie 7 dni, 30 dni, 90 dni. To proste pytanie: co wiemy o ostatnich tygodniach użytkownika i czym różnią się od jego typowego zachowania?
Najczęściej buduje się zestaw cech „rolling” dla każdego podmiotu (klienta, urządzenia, konta):
- Liczby zdarzeń w oknach – ile transakcji/logowań/klików było w ostatnich 1, 7, 30, 90 dniach.
- Suma i średnia wartości – łączna kwota, średnia kwota, mediany w tych samych oknach.
- Statystyki wariancji – odchylenie standardowe, min, max, percentyle, np. minimalna kwota transakcji w ciągu 30 dni.
- Trend – porównanie dwóch okien (np. ostatnie 7 vs 30 dni) poprzez iloraz lub różnicę.
W produkcji kluczowe są dwie kwestie. Po pierwsze, obliczenia muszą być przycięte do chwili decyzji – żadnych danych z przyszłości względem timestampu predykcji. Po drugie, trzeba podjąć decyzję, jak liczyć okna: krocząco (rolling) czy w stałych bucketach (np. kalendarzowych tygodniach). Modele reagują inaczej, a koszt obliczeniowy bywa znaczący.
W systemach online (np. real-time scoring na stronie) część statystyk rolling liczy się w systemach strumieniowych (Flink, Spark Streaming, własne agregatory) i zapisuje w cache/feature store, zamiast przeliczać je od zera przy każdym requestcie.
Lagi, różnice i tempo zmian – prosta dynamika w wersji tabelkowej
Jeżeli mamy uporządkowaną w czasie serię (np. miesięczne zużycie, dzienne odwiedziny), łatwo dodać do tabeli informację o tym, jak zmienia się wartość pomiędzy kolejnymi okresami. Zamiast modelować surowy poziom, model dostaje też „historię ostatniego ruchu”.
Najczęściej tworzone cechy to:
- Lag – wartość zmiennej w poprzednim okresie:
value_t-1, czasem teżvalue_t-2,value_t-3. - Różnice –
value_t - value_t-1lub zmiana procentowa(value_t - value_t-1) / (value_t-1). - Średnia z kilku lagów – uśrednienie ostatnich N okresów jako krótka pamięć historii.
W modelach prognozowania zużycia, popytu czy ruchu w serwisie takie cechy często dają więcej niż bardzo skomplikowane architektury sekwencyjne. Uporządkowanie jest proste: najpierw sortowanie po encji i czasie, potem przesunięcie wartości w dół, z zabezpieczeniem przed „przeskokiem” między różnymi encjami.
W implementacji produkcyjnej lagowanie wymaga ostrożności. Pipeline musi zagwarantować, że dane są czyszczone z duplikatów, spóźnionych eventów i luk w czasie (np. brak odczytów liczników przez kilka okresów). W przeciwnym razie różnice i tempo zmian będą opisywały anomalie w danych, a nie realne zachowanie.
Okna ruchome na poziomie użytkownika vs. globalne efekty kalendarza
Historia jednostkowa (user-level) to jedno, ale wiele zjawisk ma również komponent globalny: sezonowość, promocje, lockdowny, zmiany regulacyjne. Część z nich da się ująć w postaci dodatkowych cech czasowych niezależnych od konkretnego klienta.
W praktyce powstają wtedy dwie grupy zmiennych:
- Cecha per-entity – np. liczba zakupów użytkownika w ostatnich 14 dniach.
- Cecha globalna – np. liczba wszystkich zakupów w serwisie w ostatnich 14 dniach, flaga „trwa kampania -20%”, indeks natężenia ruchu.
Takie połączenie mówi modelowi: klient kupuje mniej, ale cały rynek też się skurczył – albo przeciwnie, popyt globalnie rośnie, a ten konkretny klient wyhamował. W modelach churnowych i fraudowych różnica między poziomem jednostkowym a odchyleniem od „tła” bywa kluczowa.
Czas od zdarzenia referencyjnego: dystans do istotnych punktów w czasie
W wielu zadaniach istotny nie jest sam kalendarz, lecz odległość od konkretnego zdarzenia: rejestracji konta, startu umowy, pierwszej płatności. Pytanie brzmi: jak klient zachowuje się na osi „dni od X”, a nie na osi „kalendarz 2024 vs 2025”.
Typowe przykłady cech tego typu:
- Dni od rejestracji – zupełnie inne wzorce w pierwszym tygodniu korzystania z usługi niż po roku.
- Dni do końca umowy – churn przyspiesza, gdy zbliża się data końca kontraktu.
- Czas od ostatniej zmiany planu/ceny – reakcja na zmianę warunków taryfy bywa opóźniona o kilka okresów rozliczeniowych.
Tego typu cechy są często wyliczane raz dziennie w batchu i dokładane do rekordów scoringowych jako kolumny referencyjne, co odciąża systemy online. Granice okien (np. 0–7 dni, 8–30 dni) można dodatkowo zamodelować jako kategorie lub binned features, gdy zależność jest mocno nieliniowa.
Agregacje po encjach: jak z transakcji zrobić cechy na poziomie klienta
Klasyczne agregaty po ID: średnie, sumy i liczniki
W praktyce biznesowej surowe zdarzenia (transakcje, odsłony, wiadomości) rzadko trafiają bezpośrednio do modelu tabularnego. Częściej buduje się z nich agregaty na poziomie encji: klienta, produktu, sprzedawcy, urządzenia. To prosty przepis: grupowanie po ID i liczenie funkcji agregujących.
Najczęściej używane agregaty to:
- Liczniki – liczba transakcji, liczba odwiedzin, liczba zgłoszeń.
- Sumy i średnie – łączna kwota, średnia kwota, przeciętny rabat, przeciętna liczba produktów w koszyku.
- Ekstrema – maksymalna i minimalna kwota transakcji, najdroższy kupiony produkt.
- Proporcje – udział określonego typu zachowań w całości (np. % transakcji online vs offline).
Tak zbudowane cechy wprowadzają stabilność: pojedyncza transakcja z błędną kwotą robi mniej szkody, jeśli model patrzy na medianę czy percentyle zamiast na jeden rekord. W dodatku agregaty naturalnie kompresują dane, co jest istotne przy miliardach zdarzeń.
Agregaty hierarchiczne: klient, produkt, merchant, kanał
W systemach wielowymiarowych, np. e-commerce, pojedyncza transakcja należy jednocześnie do kilku encji: klienta, produktu, sprzedawcy (merchant), kategorii, kanału. Każda z tych encji może mieć własne cechy agregowane, które później „doszywa się” do rekordu scoringowego.
Przykładowo dla systemu antyfraudowego można zbudować:
- Cecha klienta – średnia liczba transakcji dziennie.
- Cecha karty płatniczej – odsetek odrzuconych transakcji w ostatnim miesiącu.
- Cecha urządzenia – liczba unikalnych kont, które płaciły z tego device ID.
- Cecha merchant ID – udział zwrotów/chargebacków w ostatnim kwartale.
Transakcja dziedziczy komplet tych agregatów: część opisuje historię klienta, część – „reputację” sprzedawcy, a reszta – ryzykowność kanału lub urządzenia. Model ma wtedy szerszy kontekst bez budowania skomplikowanego grafu.
Agregacje na oknach czasowych: łączenie wymiaru encji i czasu
Samo zliczanie po całej historii bywa mylące. Klient mógł być aktywny trzy lata temu, potem zamilknąć. W wielu zadaniach ważne jest połączenie filtra encji z filtrem czasu: agregaty typu „klient X w ostatnich 30 dniach”.
Typowe kombinacje to:
- Liczba zdarzeń klienta w ostatnich N dniach – np. liczba logowań czy transakcji.
- Liczba unikalnych elementów – ile unikalnych SKU kupił klient w ostatnim kwartale.
- Suma wartości – przychód z klienta w wybranym oknie.
- Udziały typów zdarzeń – procent transakcji z rabatem w ostatnim miesiącu.
Operacyjnie wymaga to porządnej inżynierii danych. W hurtowni lub jeziorku danych zwykle pojawia się warstwa „snapshotów” – dziennych lub tygodniowych przekrojów z policzonymi agregatami, które można łatwo połączyć z tabelą scoringową. Obliczanie wszystkiego ad hoc przy każdym treningu lub deploymencie szybko się mści.
Agregaty kategorii i grup produktowych: od szczegółu do segmentu
Nie zawsze najważniejszy jest konkretny produkt. Często większe znaczenie mają kategorie lub rodziny produktowe: elektronika vs spożywka, bilety lotnicze vs kolejowe. Tu z pomocą przychodzą agregaty liczone po połączeniu transakcji z drzewkiem kategorii.
Przykładowe cechy dla klienta:
- Udział wydatków w danej kategorii – np. % wydatków na modę vs całość.
- Liczba unikalnych kategorii – jak bardzo zróżnicowany jest koszyk.
- Dominująca kategoria – kategoria o najwyższej sumie wydatków lub liczbie transakcji.
- Zmiana preferencji – różnica udziału wybranej kategorii między ostatnim a poprzednim okresem.
W sprzedaży krzyżowej takie cechy pozwalają odróżnić klienta „jedno-hobby” od „generalisty”, a w churnie – widzieć, czy klient stopniowo przenosi wydatki z jednej kategorii do innej (np. z własnej oferty na marketplace).
Agregaty z wagami czasowymi: recency wbudowane w wzór
Zwykłe sumy i średnie traktują wszystkie zdarzenia tak samo. W wielu scenariuszach nowsze zdarzenia powinny ważyć więcej niż stare. Zamiast trzymać osobne agregaty dla wielu okien, można wprowadzić wagi malejące w czasie, najczęściej wykładniczo.
Przykładowy schemat:
- każdej transakcji przypisuje się wagę
w = exp(-λ * age_in_days), - liczy się ważoną sumę, ważoną średnią lub ważoną liczbę zdarzeń,
- dobór parametru λ kontroluje „pamięć” systemu (jak szybko zapomina historię).
W praktyce takie cechy z wagami czasowymi często działają lepiej niż kilka osobnych agregatów okienkowych, szczególnie w danych rzadkich. Model dostaje jedną liczbę, w której stara historia naturalnie ma mniejszy wpływ.
Agregaty na poziomie populacji: „jak bardzo odstajesz od innych”
Same liczby bez kontekstu bywają trudne do interpretacji przez model. 5 transakcji tygodniowo może być bardzo dużo w jednej branży i przeciętne w innej. Tę względność da się wprowadzić przez porównanie do populacji.
Przykładowe podejście:
- dla każdej cechy agregowanej liczy się rozkład w populacji (np. per kraj, per segment),
- następnie dla konkretnego klienta wyznacza się pozycję w tym rozkładzie – percentyl, z-score, odległość od mediany,
- powstaje cecha typu: „klient jest w 90. percentylu pod względem liczby transakcji w segmencie X”.
W zastosowaniach fraudowych i riskowych takie „odstępstwa od normy” potrafią być silniejszym sygnałem niż surowe wartości. Z drugiej strony wymagają reguł aktualizacji: rozkład populacji z czasem się zmienia, więc snapshoty nie mogą być wiecznie aktualne.
Agregaty sekwencji zdarzeń: order matters
Przy procesach wieloetapowych, np. lejku sprzedażowego czy ścieżce w aplikacji, liczy się nie tylko to, ile zdarzeń zaszło, ale w jakiej kolejności. Modele sekwencyjne radzą sobie z tym naturalnie, ale w świecie tabular można wyciągnąć proste wnioski na poziomie cech.
Typowe zabiegi:
- Liczniki etapów – ile razy użytkownik doszedł do koszyka, ile razy do strony płatności.
- Najdalszy osiągnięty etap – np. zakodowany liczbowo poziom w lejku.
- Wzorce przejść – zliczanie par (poprzedni ekran → następny ekran) i budowa agregatu typu „dominująca ścieżka”.
- Flagi specyficznych sekwencji – np. czy użytkownik często wraca z płatności do koszyka, co sugeruje problem z płatnością lub wahanie.
Tego typu cechy powstają zwykle jako etap pośredni między surowymi logami a tabelą modelingową. Ograniczają wymiarowość (nie wprowadzają całej sekwencji), ale przekazują ogólny „styl” zachowania, który jest czytelny dla drzew czy modeli liniowych.
Agregacje krzyżowe: relacje między różnymi encjami
Czasem najciekawsze nie jest to, jak zachowuje się pojedynczy klient czy pojedynczy produkt, lecz relacja między nimi. Dwie identyczne transakcje mogą mieć inne ryzyko, jeśli jeden klient kupuje „jak inni”, a drugi – w kompletnie nietypowy sposób.
Przykładowe cechy krzyżowe:
Najczęściej zadawane pytania (FAQ)
Po co robić feature engineering przy tabular data, skoro modele drzewiaste „same sobie radzą”?
Modele drzewiaste rzeczywiście dobrze pracują na surowych tabelach, ale dane biznesowe są zazwyczaj chaotyczne: zawierają braki, kody techniczne, ID, luki czasowe i cechy bez jasnego znaczenia. Bez przemyślanego feature engineeringu model uczy się na takim „szumie” i częściej dopasowuje się do przypadkowych wzorców niż do realnych zależności.
Celowe przekształcenie kolumn (np. czas od ostatniego zakupu, udział transakcji w promocji, odchylenie od własnej mediany klienta) wzmacnia sygnał biznesowy w danych. W efekcie model jest prostszy, lepiej interpretowalny i zwykle stabilniejszy po wdrożeniu, mimo że sam algorytm może być mniej „wyrafinowany”.
Czy więcej cech zawsze poprawia jakość modelu?
Nie. Większa liczba cech często oznacza jedynie powielanie tej samej informacji w różnych wariantach oraz wprowadzanie dodatkowego szumu. Na walidacji może to wyglądać na lekki zysk, ale w produkcji przekłada się na wyższe ryzyko overfittingu i podatność na zmianę rozkładu danych (data drift).
Kluczowe są cechy bardziej informacyjne: powiązane z decyzją biznesową i zrozumiałe dla zespołu (np. wskaźniki recency, proporcje, relacje dochód/zobowiązania). Taki zestaw cech zwykle daje lepszy kompromis między jakością predykcji, stabilnością w czasie a kosztem utrzymania pipeline’u.
Jakie typy zmiennych w tabeli są najważniejsze z punktu widzenia feature engineeringu?
Najczęściej pracuje się z kilkoma typami zmiennych: kategorycznymi nominalnymi (np. kraj, kanał sprzedaży), kategorycznymi porządkowymi (np. rating, poziom ryzyka), liczbowymi (kwoty, liczebności, wskaźniki) oraz czasowymi (daty, timestampy, czas trwania). Oddzielną kategorią są ID i klucze techniczne, które rzadko powinny trafiać wprost do modelu.
Od poprawnego rozpoznania typu zależy dobór transformacji. Inaczej koduje się rzadkie kategorie, inaczej traktuje się daty (np. okna czasowe, dzień tygodnia), a jeszcze inaczej tworzy się proporcje i różnice z liczb. Błędne potraktowanie typu – np. użycie ID jak liczby ciągłej – często generuje czysty szum.
Jak feature engineering wpływa na stabilność modelu w czasie?
To, jakie cechy wybierzemy, decyduje, jak model zachowa się przy zmianie rozkładu danych. Agresywne operacje na ID lub mocno dostrojony target encoding mogą dać wysoki wynik na danych historycznych, ale są wrażliwe na zmiany w biznesie (nowe produkty, kampanie, inne zachowania klientów).
Bardziej stabilne w czasie są cechy oparte na relacjach i proporcjach (np. udział zakupów w promocji, wskaźnik wykorzystania limitu, recency), a także dobrze zaprojektowane cechy sezonowe. W produkcji często rezygnuje się z kilku punktów metryki na walidacji na rzecz cech, które zachowują sens po miesiącach lub latach.
Jak zdecydować, na jakim poziomie agregacji (granularity) budować cechy?
Punkt wyjścia to pytanie: jaką decyzję ma wspierać model? Jeśli celem jest przewidzenie rezygnacji klienta w 90 dni, cechy powinny podsumowywać jego zachowanie w określonym oknie obserwacji przed tą datą. Jeśli prognozujemy sprzedaż produktu, potrzebujemy cech odzwierciedlających sezonowość i trend na poziomie produktu, a nie pojedynczej transakcji.
Ta sama tabela zdarzeń może posłużyć do różnych modeli, ale każdy będzie wymagał innej logiki agregacji. Model fraudowy „na poziomie transakcji” skorzysta z cech opisujących bieżącą operację i kilka ostatnich zdarzeń, a model ryzyka klienta – z długoterminowych wskaźników zachowania klienta z wielu transakcji.
Dlaczego prosty model z dobrym feature engineeringiem bywa lepszy od złożonej sieci neuronowej na surowych danych?
W praktyce spotyka się sytuacje, w których logistic regression z kilkudziesięcioma dobrze zaprojektowanymi cechami dorównuje lub przewyższa sieć neuronową karmioną surowymi danymi. Co wiemy? Prosty model jest łatwiej interpretowalny, tańszy w utrzymaniu i bardziej przewidywalny przy zmianach w danych.
Złożone sieci wymagają bogatszych pipeline’ów, większej mocy obliczeniowej i bardziej rozbudowanego monitoringu. Jeżeli zysk na metryce jest niewielki, a koszt wdrożenia i utrzymania – wysoki, biznes częściej wybiera prostszy model z dojrzałym feature engineeringiem jako rozwiązanie bardziej opłacalne operacyjnie.
Jak pogodzić jakość modelu z prostotą i kosztem utrzymania pipeline’u cech?
Każda nowa cecha to potencjalnie dodatkowe joiny, okna czasowe, raporty i tabele pośrednie, które trzeba policzyć zarówno na etapie treningu, jak i inference. Rozbudowany zestaw cech może poprawić metryki o ułamek punktu, ale jednocześnie skomplikować pipeline do tego stopnia, że jego rozwój i debugowanie stają się bardzo kosztowne.
Praktyczne podejście zakłada selekcję transformacji, które dają wyraźny zysk i mają jasne uzasadnienie biznesowe. Zamiast tworzyć dziesiątki wariantów tych samych sygnałów, lepiej zainwestować w kilka dobrze przemyślanych agregacji i wskaźników, które zespół rozumie i potrafi monitorować w czasie.






