3.5/5 - (6 votes)

Nawigacja:

Gdy dane płatają figle: krótka scena z praktyki

Masz miesięczny deadline. Zespół sprzedaży czeka na model, który oceni szansę zakupu podczas rozmowy. Surowy CSV ląduje w repo: tysiące rozmów, kilkadziesiąt pól, w tym data rozmowy, region, segment klienta, kwota koszyka i wynik „czy kupił”. Po dwóch dniach pierwsze wyniki wyglądają świetnie – AUC ponad 0,9. Po tygodniu wdrożenia skuteczność spada do poziomu rzutu monetą. Co poszło nie tak? Uciekły duplikaty, pojawił się przeciek czasowy, a klasy były mocno niezrównoważone. Da się tego uniknąć, jeśli konsekwentnie przejdziesz przez trzy filary: czyszczenie, balansowanie i poprawny podział.

Najczęstsze pytania, które padają na starcie

  • Jak szybko wykryć i usunąć duplikaty oraz niespójne typy danych?
  • Kiedy brakujące wartości uzupełniać, a kiedy wyrzucać wiersze lub kolumny?
  • Jak kodować zmienne kategoryczne, aby nie wprowadzić przecieku do walidacji?
  • Czy i jak balansować klasy: oversampling, undersampling, SMOTE, wagi klas czy zmiana progu?
  • Jak podzielić dane, by uniknąć data leakage, zwłaszcza przy seriach czasowych lub klientów powtarzających się?
  • Jak ustawić pipeline, by każdy krok był powtarzalny i liczony tylko na zbiorze treningowym?

Fundament: doprecyzuj cel i granice danych

Jednostka analizy i etykieta

Zanim zaczniesz cokolwiek „naprawiać”, odpowiedz sobie: co jest pojedynczym rekordem i co przewiduję? Jeden klient, jedno zamówienie, jedna sesja, jedno zdarzenie? Błędnie zdefiniowana jednostka generuje kaskadę błędów: duplikaty „bliźniacze”, sprzeczne agregacje czy mylenie poziomów (np. cechy sesji przypięte do klienta). Ustal także jasne okno czasowe dla etykiety (np. „czy klient kupi w 30 dni od kontaktu?”). Wiele danych „z przyszłości” nie powinno znaleźć się w cechach dostępnych w momencie prognozy.

Kontekst czasu i ryzyko przecieku

Jeśli data lub sekwencja zdarzeń mają znaczenie, każda transformacja musi respektować porządek czasu. Agregacje wsteczne są okej, agregacje w przód – to przeciek. Metadane „data wykonania raportu” albo „data dostawy” często nieświadomie zdradzają wynik – usuń lub logicznie przesuwaj je w czasie, by model „wiedział” tylko to, co człowiek wiedziałby w punkcie prognozy.

Mapa danych: typy i ograniczenia

Szybko skategoryzuj kolumny: liczbowe, kategoryczne (nominalne lub porządkowe), daty/czas, tekst, identyfikatory. Dołóż ograniczenia biznesowe: zakresy (np. wiek 0–120), listy dozwolonych wartości (np. ISO krajów), unikalność (np. ID zamówienia). To twoja „mapa porządków” – posłuży do walidacji i czyszczenia.

Czyszczenie: audyt jakości przed modelowaniem

Duplikaty i rekordy bliźniacze

Duplikat to nie tylko identyczny wiersz. W praktyce częściej trafiają się „bliźniaki”: te same ID klienta i ta sama data, ale drobne różnice w polach (np. zaokrąglona kwota). Zdefiniuj klucz porównawczy (np. ID + timestamp z dokładnością do minuty) i wykryj kandydatów do deduplikacji. Zdecyduj: scalić (agregacja pól), zostawić najnowszy, czy odrzucić oba, jeśli sprzeczne? Kryterium: co jest wiarygodnym źródłem prawdy i jaka decyzja minimalizuje błąd w etykiecie.

Niespójne typy i zakresy

Połączone źródła często „mieszają” typy: liczby w stringach („1 200,50”), wartości „brak” jako „-1” lub „N/A”. Ustandaryzuj separatory, waluty i strefy czasowe. Ustal politykę wartości specjalnych: -1 bywa znaczącą kategorią lub brakującą daną – rozdziel te przypadki. Sprawdź rozkłady: nagłe wartości skrajne w nowym imporcie to często problem ETL, nie „prawdziwy” outlier.

Braki danych – diagnoza przyczyn

Zlicz braki kolumnami i wierszami, ale patrz też na współwystępowanie braków: puste pole „miasto” wraz z „kod_pocztowy” sugeruje brak segmentu adresowego – imputuj logicznie lub usuń pakietowo. Zbadaj mechanizm braków: całkowicie losowe (MCAR), zależne od obserwowalnych cech (MAR) czy nielosowe (MNAR). Dla MAR/MNAR rozważ flagę „było puste” jako cechę – często niesie sygnał (np. brak numeru telefonu koreluje z rezygnacją).

Braki danych: usuwać czy uzupełniać?

Kryteria decyzji: kolumna czy wiersz

Prosty próg „usuń kolumnę, gdy >40% braków” bywa mylący. Lepiej użyj kryteriów:

  • Znaczenie biznesowe cechy: jeśli krytyczna, spróbuj zaawansowanej imputacji.
  • Zależność braków od targetu: jeśli flaga „brak” silnie koreluje z Y, zachowaj ją jako cechę.
  • Gęstość informacji: kolumna prawie stała po imputacji nie wnosi wartości – usuń.
  • Wiersze: usuń jedynie, gdy braki są wielowymiarowe i nieodtwarzalne; nie kasuj wierszy z rzadką klasą przy klasyfikacji nierównoważnej.

Imputacja liczbowa i kategoryczna bez przecieku

Dla liczb: mediana jest bezpieczna przy rozkładach skośnych; średnia bywa wrażliwa na outliery; KNN-imputer lepiej odtwarza strukturę, ale może rozmywać granice klas; regresyjne/multiplierowe metody (np. MICE) są silne, lecz cięższe obliczeniowo. Dla kategorii: najczęstsza kategoria sprawdza się, ale bywa uprzedzona; specjalna kategoria „Missing” bywa najlepsza, gdy „pustość” niesie informację.

Klucz: ucz imputery tylko na zbiorze treningowym, a następnie transformuj walidację i test. Używaj pipeline’ów, aby uniknąć sytuacji, w której średnia z całego zbioru trafia do treningu – to cichy przeciek i zawyżone wyniki.

Imputacja w danych czasowych i sekwencjach

W szeregach czasowych unikaj „podglądania przyszłości”. Forward-fill (uzupełnianie poprzednią wartością) jest z natury kauzalne; rolling-mean z oknem wyłącznie wstecz także. Spline czy globalne średnie z całego szeregu mogą wprowadzić przyszłą informację do przeszłości – stosuj jedynie w eksperymentach offline, nigdy w prognozie czasu rzeczywistego.

Kodowanie zmiennych kategorycznych bez bólu głowy

Zacznij od prostego pytania: czy kategoria ma naturalny porządek? Jeśli tak (np. „niski”, „średni”, „wysoki”), użyj kodowania porządkowego z jawnie zdefiniowaną kolejnością. Jeśli nie, jedyną bezpieczną liczbą dla „koloru” czy „regionu” jest wektor cech – tu sprawdza się one-hot. Drzewa i ich pochodne (RandomForest, XGBoost, LightGBM) radzą sobie z one-hot bez skalowania; modele liniowe czy sieci lubią też rzadkie macierze, ale przy bardzo wysokiej krotności potrafią puchnąć.

Gdy liczność kategorii rośnie (np. tysiące identyfikatorów kampanii), rozważ trzy ścieżki. Hashing trick kontroluje wymiar cech, ale wprowadza kolizje – akceptowalne, jeżeli nie budujesz interpretowalnych reguł. Target/mean encoding kondensuje informację do jednej kolumny, lecz wymaga rygorystycznej ochrony przed przeciekiem: średnia musi być liczona wyłącznie na treningu i najlepiej w schemacie K-fold, z losowym szumem i wygładzaniem dla rzadkich kategorii. Ostatnia droga to grupowanie rzadkich wartości do koszyka „other” według progu częstości – proste, skuteczne i odporne na dryf nowych kategorii.

Krótki przykład z praktyki: „region” (5 wartości) – one-hot; „typ_abonamentu” (Basic < Standard < Premium) – kodowanie porządkowe; „kampania_id” (dziesiątki tysięcy) – target encoding z K-fold i wygładzaniem albo hashing, jeśli priorytetem są zasoby i prostota.

Procedura, która nie przecieka do walidacji

Kodery dopasowuj wyłącznie na zbiorze treningowym (i w obrębie każdej pętli walidacyjnej). Dla one-hot ustaw „handle_unknown=’ignore’”, by nowe kategorie w walidacji/test nie psuły przetwarzania. W target encodingu zastosuj schemat: w każdym foldzie obliczanie średnich bez użycia walidacji tego foldu; dodaj wygładzanie (np. mieszanka globalnej średniej i średniej kategorii zależna od liczności) oraz drobny szum, by zbić przeuczenie.

W danych czasowych kodowanie oparte na celu wprowadzaj wyłącznie z użyciem informacji z przeszłości: oblicz średnie do danej daty, a nie z całego zakresu. To detal, który często decyduje, czy AUC w realu ma sens.

Nierównowaga klas: jak dobrać narzędzie do problemu

Zanim uruchomisz SMOTE, policz, ile naprawdę masz przykładów klasy rzadkiej w treningu, walidacji i teście. Model ma nauczyć się wzorca, ale też sprawdzić się na uczciwym przekroju – jeśli w teście zostanie garstka pozytywów, każdy błąd zmieni metryki dramatycznie. Druga rzecz: koszt biznesowy pomyłek. Czasem lepiej podnieść recall kosztem precyzji i pracować progiem decyzji, niż tworzyć setki syntetycznych punktów.

Opcje, które zwykle działają po kolei. Wagi klas (class_weight) są dobrym startem w modelach liniowych i drzewach – nie zmieniają rozkładu danych, a modyfikują funkcję straty. Undersampling większości bywa skuteczny, gdy masz dużo przykładów i chcesz przyspieszyć trening; pilnuj, by zachować różnorodność (stratyfikacja, ewentualnie metody z priorytetem do granic decyzyjnych). Oversampling prosty (duplikacja) naraża na przeuczenie, więc raczej wybieraj warianty syntetyczne: SMOTE/ADASYN dla zmiennych ciągłych; dla mieszanych rozważ SMOTENC lub hybrydy (SMOTE + TomekLinks/ENN), które czyszczą trudne punkty. Po treningu i tak warto korygować próg – szczególnie, gdy metryką prowadzącą jest F-beta lub zbalansowany koszt błędów.

Przykład z działu retencji (churn ~5%): start od XGBoost z „scale_pos_weight” zgodnym z proporcją klas, walidacja na AUC-PR i recall przy akceptowalnej precyzji. Jeśli recall nie domaga – pipeline z normalizacją cech ciągłych, SMOTENC dla mieszanych i ponowny trening, a na końcu ustawienie progu z krzywej precyzja–czułość na zbiorze walidacyjnym.

Walidacja, która nie „połyka” próbek syntetycznych

Resampling wykonuj wyłącznie na foldach treningowych, po podziale i po dopasowaniu transformacji z treningu. Kolejność w pipeline jest kluczowa: najpierw imputacja i skalowanie dopasowane na treningu, potem oversampling (SMOTE korzysta z odległości – musi widzieć już przeskalowaną przestrzeń), na końcu model. W kroswalidacji nigdy nie „doklejaj” wygenerowanych próbek do walidacji. Przy danych sekwencyjnych stosuj splits blokowe w czasie, a resampling – jeśli już – wyłącznie w obrębie okien treningowych z przeszłości.

Podział danych bez pułapek i skrótów

Scenariusz i.i.d.? Użyj stratyfikowanego podziału train/val/test, zwłaszcza przy klasach rzadkich, aby każda część miała ich wystarczająco dużo do oceny metryk. Gdy w danych pojawia się czas, trzymaj chronologię: trenowanie na przeszłości, walidacja na nowszym oknie, test na jeszcze nowszym. Rolling-origin (seria okien uczących i przesuwający się horyzont) często daje bardziej stabilny obraz generalizacji niż pojedynczy „cut”.

Jeśli te same byty powtarzają się w danych (klient, urządzenie, firma), użyj podziałów grupowych (GroupKFold/GroupShuffleSplit), aby nie mieszać zdarzeń jednego bytu między trening i walidację. To najczęstsza, cicha wersja wycieku: model „rozpoznaje” klienta po idiosynkratycznych cechach, a wynik w walidacji jest nierealnie wysoki.

Najpierw deduplikuj, potem dziel. Bliźniacze rekordy po dwóch stronach granicy podziału to prosty sposób na przeszacowane metryki. Gdy do gry wchodzą agregacje po bycie (np. historia klienta), licz je wyłącznie w obrębie treningu lub „przeszłości” – nigdy z użyciem informacji z walidacji czy testu.

Ile na trening, ile na test i jak to utrwalić

Gdy danych jest sporo, test 10–20% zwykle wystarcza; przy bardzo rzadkiej klasie rozważ większy test lub akumulację testów w czasie. Ważniejsze od „idealnego procentu” jest to, by w teście mieć dziesiątki–setki przypadków rzadkiej klasy, a nie trzy. Ustal stałe ziarna losowości, zapisuj identyfikatory obserwacji w podziałach i przechowuj migawkę schematu danych wraz z podstawowymi statystykami – replikowalność eksperymentu oszczędza tygodnie.

Pipeline i porządek kroków, które robią różnicę

Ułóż przetwarzanie w spójny łańcuch: selekcja/filtry → imputacja → transformacje/skalowanie → kodowanie → balansowanie (jeśli stosujesz) → model → ewentualna kalibracja → wybór progu. Przy modelach drzewiastych skalowanie zazwyczaj pomijasz; przy SMOTE najpierw dopasuj skalowanie na treningu i przekształć, a dopiero potem generuj próbki syntetyczne. Używaj narzędzi typu Pipeline/ColumnTransformer (i odpowiedników z bibliotek do resamplingu), by każdy „fit” widział wyłącznie trening.

Dla tekstu lub cech o bardzo wysokiej krotności wybierz reprezentację opartą na hashowaniu lub worku słów z ograniczeniem słownika; trzymaj spójny seed, by kolejne iteracje nie mieszały kolumn. Jeśli planujesz strojenie hiperparametrów, rozważ walidację zagnieżdżoną: wewnątrz – tuning; na zewnątrz – ocena. Mało efektowne, ale ratuje przed zbyt optymistycznymi wnioskami.

Krótka lista kontroli przed startem treningu

  • Brak wspólnych bytów (klientów/urządzeń) między treningiem a walidacją/testem.
  • Imputery, skalery i kodery dopasowane wyłącznie na treningu; one-hot ignoruje nieznane kategorie.
  • Balansowanie klas wykonywane po podziale i wyłącznie na częściach treningowych/foldach.
  • Bezpieczne cechy z historii i z wielu tabel

    Agregacje „z historii” kuszą, bo zwykle dodają sporo mocy. Klucz jest prosty: zamrażasz kalendarz w chwili predykcji i patrzysz wyłącznie wstecz. Jeśli przewidujesz ryzyko chargebacku dla transakcji T, to „liczba sporów w ostatnich 30 dniach” liczy się po dacie T−30 do T−1, a nie „w ciągu 30 dni od T”. Brzmi banalnie, ale to dokładnie ten drobny błąd, który winduje AUC na walidacji i rozsypuje się w produkcji.

    Przy łączeniu wielu źródeł trzymaj się perspektywy „co wiemy w momencie decyzji”. Tabela decyzji (predykcji) powinna być lewą stroną złączenia, a każda tabelka pomocnicza musi mieć filtr czasowy nieprzekraczający daty zdarzenia. Przykład: ocena churnu w D+0 na podstawie „aktywności w ostatnich 90 dniach” – tak; „aktywności w kolejnych 7 dniach po ocenie” – to czysty przeciek. Gdy budujesz liczniki po bytach (klient, urządzenie), utrzymuj okna i horyzonty jawnie w kodzie (prefiksuj nazwy: cnt_tx_30d_past), a przy danych strumieniowych dopilnuj, by pipeline operował na stanach inkrementalnych, nie na agregacjach z całego zbioru.

    Łączenia i selekcje, które przewracają rozkład

    Inner join na tabeli celu potrafi wymazać „brakujące” negatywy – dostajesz czystszy, ale nierealny świat. Do predykcji, która ma działać na wszystkich rekordach wejściowych, buduj zestaw startowy jako lewy join do celu: każdy rekord predykcji pozostaje, a etykieta może być pusta (np. jeszcze nie nadszedł horyzont). Podobnie z duplikacją przy wielu-do-wielu: jedno zamówienie po joinie z tabelą produktów nagle staje się pięcioma wierszami i zaczyna dominować trening. Rozwiązanie? Agreguj do poziomu predykcji przed joinem (np. „liczba pozycji”, „suma wartości”, „czy zawiera kategorię X”), a dopiero potem łącz.

    Odrębny klasyk to filtry „po fakcie”. Skoro celem jest przewidzieć, kto nie zapłaci faktury, to odrzucenie rekordów „bez danych płatności” może usunąć właśnie tych najtrudniejszych. Zamiast ucinać, oznaczaj flagi kompletności i dopuść brakujące wartości (imputacja lub osobna kategoria). Dzięki temu model widzi realny rozkład, a nie wypolerowaną próbkę.

    Regresja: inne akcenty w przygotowaniu

    Przy regresji ciężkie ogony i skrajne wartości rządzą metrykami. Jeśli kilka obserwacji dominuje RMSE, rozważ transformację celu: log1p przy rozkładach prawoskośnych albo Yeo–Johnson, gdy pojawiają się zera i wartości ujemne. Modele liniowe zwykle zyskują na skalowaniu cech (Standard/RobustScaler), drzewa – rzadziej. Odstające obserwacje? Zamiast ślepo je wycinać, porównaj dwa tory: winsoryzacja (ucięcie do percentyli) kontra metryka odporniejsza (MAE, pinball loss przy quantile regression). Kryterium jest proste: które podejście lepiej służy decyzji biznesowej – trafność przeciętna czy stabilność na ogonie?

    Transformacja celu bez zaskoczeń

    Transformuj y wyłącznie tam, gdzie daje to przewidywalną korzyść: stabilizację wariancji, liniowość relacji, mniejszą wrażliwość na outliery. Przy log1p pamiętaj o odwracaniu predykcji przed oceną i o tym, że błąd w przestrzeni log nie jest intuicyjny w złotówkach czy godzinach. Yeo–Johnson działa dla wartości ujemnych i bywa bezpieczniejszy niż Box–Cox. W drzewach transformacja celu rzadko pomaga, ale bywa sensowna przy heteroscedastyczności. I drobiazg: jeśli stosujesz standaryzację y (np. w sieciach), parametry dopasuj tylko na treningu i noś je w pipeline, by odwrócić skalę spójnie w walidacji i teście.

    Sanity-checki po przygotowaniu danych

    Dwa krótkie testy odsiewają większość „magicznych” wyników. Po pierwsze, modele bazowe: DummyClassifier/Regressor (stratyfikacja, średnia) powinny dać przewidywalnie słabe metryki; jeśli już je przebijasz, ale po permutacji etykiet nadal „coś działa”, masz przeciek. Po drugie, walidacja krzyżowa z permutacją cech: zniknięcie wydajności po potasowaniu kolumn, które podejrzewasz o wyciek (np. identyfikator dokumentu lub timestamp z przyszłości), to szybki sygnał ostrzegawczy. Równolegle porównaj rozkłady podstawowych cech między train/val/test (prosty KS/psi albo chociaż wykresy kwantyl–kwantyl). Gdy foldy różnią się jak dzień i noc, najpewniej nie masz problemu modelu, tylko problem próbkowania.

    Jak przygotować dane do machine learningu: czyszczenie, balansowanie, podział
    Źródło: Pexels | Autor: Jakub Zerdzicki

    Krótki szkic „od surowych danych do pierwszego fitu”

    Detekcja nadużyć płatniczych w transakcjach kartowych. Start od lewego joinu zdarzeń transakcyjnych z metadanymi sklepu i posiadacza. Usuwasz duplikaty po (card_id, timestamp, amount, merchant_id). Budujesz cechy okienkowe wstecz: liczba transakcji/kwota w 1h, 24h, 7d; liczba unikalnych merchantów w 7d; odległość geograficzna od ostatniej legalnej transakcji; kody MCC – one-hot lub hashing. Cechy skalujesz (RobustScaler), a dopiero potem – na foldach treningowych – stosujesz SMOTE dla zmiennych ciągłych lub zostajesz przy class_weight, jeśli mieszanych cech jest dużo. Walidacja: blokowa w czasie (rolling-origin), by nie mieszać przyszłości do treningu. Po trenowaniu ustawiasz próg na walidacji pod zadaną fałszywą dodatniość (np. maks. liczba alertów na zespół). Całość zamykasz w Pipeline, który liczniki i skaler dopasowuje wyłącznie na treningu każdego okna.

    Po przejściu takiego toru masz dane, które „oddychają” jak produkcja: bez spojrzeń w przyszłość, z sensownymi oknami i z walidacją, która mówi prawdę. Następny krok? Zapisać pipeline, seedy i podziały, a potem spokojnie iterować – zmieniając pojedyncze elementy i mierząc ich realny wpływ zamiast zaczynać wszystko od zera.

    Braki danych bez mitów: decyzje zależne od mechanizmu

    Najpierw odpowiedz na krótkie „dlaczego”: braki całkiem losowe (MCAR) są rzadkie, częściej brak zależy od innej cechy (MAR) albo od samej wartości (MNAR). Jeśli pole „dochód” znika głównie u klientów z krótką historią w systemie, to imputacja medianą bez flagi braków spłaszczy różnice. Zacznij od prostych testów: korelacje flag braków z innymi kolumnami i z celem, rozkład braków w czasie lub po segmentach (region, kanał). Gdy flaga „is_null_x” sama w sobie przewiduje etykietę, zostaw ją – bywa cenniejsza niż sama imputowana liczba.

    Usuwanie? Wiersze – tylko gdy braki rozlewają się po większości kluczowych kolumn i nie tworzą osobnej populacji (inaczej wycinasz najtrudniejszych). Kolumny – gdy brakuje w nich prawie wszystkiego, a flaga „is_null” nie niesie sygnału. W każdym innym przypadku imputuj na treningu i przenoś parametry w pipeline. Dla liczb – mediana przy rozkładach skośnych, średnia tylko przy stabilnych, w miarę normalnych; dla kategorycznych – „Unknown/Other” jako osobna kategoria. Czasowe szeregi imputuj w obrębie bytu i chronologii (forward/backward fill), nigdy mieszając przyszłość do przeszłości. KNNImputer działa sensownie przy kilku cechach ciągłych o podobnej skali; wielowymiarowa imputacja (MICE) ma sens przy małych/średnich zbiorach z wyraźnymi zależnościami – ale licz ją wyłącznie na foldach treningowych, inaczej zrobisz elegancki przeciek.

    Krótka ściąga decyzyjna bez listy: braków do 5% – prosta imputacja + flaga; 5–30% – imputacja dopasowana do typu i rozkładu + flaga, rozważ MICE, jeśli cech mało a zależności silne; powyżej 30% – zadaj pytanie, czy ta cecha w ogóle ma sens w predykcji, często flaga + wycięcie kolumny da więcej porządku niż „bohaterskie” imputowanie.

    Kodowanie zmiennych kategorycznych bez przecieków

    One-hot to dobry domyślny wybór, gdy liczba kategorii jest mała lub umiarkowana, a zestaw jest stabilny w czasie. W modelach liniowych możesz zrzucić jedną kolumnę referencyjną, w drzewach nie ma takiej potrzeby. Zadbaj o obsługę nieznanych kategorii („ignore”, „infrequent as one”) i dopasuj słownik wyłącznie na treningu; walidacja i produkcja nie mogą rozszerzać mapowania w locie.

    Porządkowe kodowanie ma sens tylko wtedy, gdy naprawdę istnieje naturalny porządek (np. „mały/średni/duży”). Gdy porządku nie ma, a użyjesz IntegerEncoder, model liniowy „uwierzy” w odległości między etykietami i dorobi sobie nieistniejące relacje. Drzewa zwykle lepiej to znoszą, ale i tak potrafią nadmiernie przyklejać się do przypadkowego porządku.

    Target/mean encoding ratuje sytuację przy wysokiej krotności (tysiące wartości „job_title”, „merchant_id”), ale tylko z uszczelnieniem: w klasyku stosuj K-fold target encoding wewnątrz treningu (dla każdego wiersza średnia z foldów, do których nie należy), dodaj wygładzanie do globalnej średniej i lekki szum. Dla danych czasowych lepsza jest strategia „expanding mean” z oknami wstecz. Bez tych barier wycieknie informacja o celu i wynik w walidacji odleci.

    Hashing trick daje stały wymiar i prywatność, a kolizje są akceptowalne przy szerokich modelach liniowych i drzewach z regularyzacją. Gdy łączysz kilka kategorii w interakcje („miasto×urządzenie”), haszuj od razu parę, zamiast rozwijać milion kolumn. A co z rzadkimi wartością? Scal je w „Other” po progu częstości z treningu – konserwujesz stabilność i zmniejszasz ryzyko dopasowania do szumu.

    Co z nieznanymi kategoriami w produkcji?

    Włącz tryb „handle_unknown=ignore” lub mapuj do „Other”, a następnie monitoruj udział tej kategorii w czasie. Gdy zaczyna dominować, masz sygnał o dryfie – zaplanuj przebudowę słownika i ponowny trening. Mapowania zamrażaj wersjami tak samo jak model; to drobiazg, który oszczędza godziny polowania na rozjazdy.

    Balansowanie klas w praktyce

    Zanim cokolwiek „wyrównasz”, zdecyduj, co ma być optymalizowane: ranking potencjalnych przypadków (AUC-PR, recall@precision), czy dobrze skalibrowane prawdopodobieństwa (Brier, log loss)? Oversampling i SMOTE poprawiają czułość i ranking, ale potrafią popsuć kalibrację. Class_weight przesuwa granicę decyzyjną bez zmiany rozkładu treningu; próg na wyjściu modelu bywa najtańszą, a skuteczną dźwignią.

    Undersampling bywa świetny na start, gdy dominujący negatywów jest morzem (np. 1:1000) i chcesz szybko przetestować cechy. Wadą jest utrata informacji. Oversampling (kopiowanie mniejszości) zwiększa wariancję, a SMOTE tworzy syntetyki w przestrzeni cech ciągłych – sensownie działa przy niezbyt wysokim wymiarze i bez misz-maszu kategorycznych. Dla mieszanek cech rozważ SMOTE-NC lub po prostu class_weight + tuning progu.

    Drzewa/boostingi: zacznij od wag klas (np. w XGBoost/LightGBM odpowiednio scale_pos_weight ≈ liczba_negatywnych/liczba_pozytywnych) i dopiero, gdy ranking dalej kuleje, testuj umiarkowany oversampling w obrębie foldów treningowych. Modele liniowe: class_weight + regularyzacja, a na końcu dostrojenie progu pod koszt błędów. KNN/SVM/miary odległości: bez skalowania i ostrożnie z syntetykami – często lepiej działają wagi klas i porządny skaler. Głębokie sieci: zbalansowane batch samplery lub focal loss, walidacja zawsze na surowym rozkładzie.

    Kalibracja prawdopodobieństw rób na niezbalansowanej walidacji (Platt lub izotoniczna), szczególnie gdy raportujesz ryzyko do systemów downstream. SMOTE, jeśli w ogóle, licz wyłącznie na foldach treningowych i nie mieszaj bytów ani czasu – syntetyki w przyszłości to elegancki przeciek.

    Szybka mapa decyzji dla klas niezbalansowanych

  • Mało danych + ekstremalna nierównowaga: lekki undersampling negatywów + class_weight.
  • Średnia skala + cechy głównie ciągłe: test SMOTE/SMOTE-NC na foldach vs. samo class_weight.
  • Boostingi drzewiaste: najpierw wagi (w tym scale_pos_weight), potem tuning progu pod budżet alertów.
  • Potrzeba dobrych probabilistyk: unikaj agresywnego oversamplingu, kalibruj na oryginalnej walidacji.
  • System online: nie zmieniaj rozkładu treningu co iterację; trzymaj stałe reguły wag/próbkowania.

Przykład z codzienności: w czurnie kontaktowym masz limit 500 połączeń dziennie. Trenujesz LightGBM z scale_pos_weight, a próg ustawiasz tak, by na walidacji liczba predykcji „do kontaktu” mieściła się w limicie. Jeśli koszty są asymetryczne (fałszywy negatyw boli bardziej), wprowadź wagi przypadków odzwierciedlające koszt – decyzje od razu stają się bardziej biznesowe niż akademickie.

Podział danych: wariant dopasowany do problemu

Klasyczne losowe rozcięcie z estratyfikacją wystarcza, gdy obserwacje są niezależne i nie ma czasu w tle. Gdy kilka wierszy należy do jednego bytu (klient, urządzenie, dokument), włącz GroupKFold/GroupShuffleSplit – inaczej model nauczy się „charakteru” bytu, który potem trafia do walidacji. W szeregach czasowych stosuj blokowe rozcięcia (TimeSeriesSplit, rolling-origin), najlepiej z przerwą (embargo), by cechy okienkowe nie dotykały walidacji przez „ogon”.”

Geograficzne lub kampanijne dane? Zrób rozcięcie po regionie/kampanii i dopiero wtedy pytaj, czy model uogólnia. W regresji z bardzo skośnym celem sensowne jest estratyfikowanie po kwantylach celu, aby foldy nie różniły się dramatycznie rozkładem.

Duplikaty i „bliźniaki” usuń przed podziałem albo grupuj po kluczach podobieństwa (np. ten sam plik/obraz po innym przetworzeniu). W przeciwnym razie ten sam przypadek wyląduje w treningu i walidacji, a wyniki wystrzelą bez pokrycia. Transformacje, imputery, kodery – dopasowuj wyłącznie na części treningowej danego foldu i przenoś stan w pipeline; walidacja ma widzieć wyłącznie „zamrożone” mapowania.

Pięć krótkich zasad podziału

  • Najpierw usuń duplikaty, potem dziel.
  • Zawsze estratyfikuj klasy; w regresji – binuj cel do kwantyli na potrzeby splitu.
  • W danych czasowych – rozcinaj w czasie, dodaj embargo, licz cechy wyłącznie wstecz.
  • Gdy istnieją powiązania (klient, sesja, dokument) – użyj splitu grupowego.
  • Test trzymasz nienaruszony do końca; wszystkie decyzje podejmuj na walidacji/krzyżowej.

Krótki obraz z praktyki: scoring kredytowy z miesięcznymi snapshotami. Tworzysz rolling split: do czerwca trenujesz, na lipcu walidujesz, sierpień to test. Wszelkie agregacje (np. „ile opóźnień w 3 miesiącach”) liczysz dla każdej daty odniesienia wyłącznie z przeszłości. Klienta traktujesz jako grupę – nie może pojawić się jednocześnie w treningu i w teście.

Skalowanie i stabilizacja cech numerycznych

Standaryzacja pomaga modelom opartym o odległości i iloczyny (regresja/logistyczna z regularyzacją, SVM, k-NN, sieci). Drzewa i ich boosting są niemal niewrażliwe – skaler często zbędny. Przy ciężkich ogonach i odstających wartościach użyj RobustScaler lub zrób transformacje log1p na dodatnich cechach. Danych rzadkich z one-hot nie skaluj – zniszczysz interpretację wag i tylko zwiększysz szum.

Porządek operacji trzymaj żelazny: najpierw imputacja liczb (na treningu), potem skaler (dopasowany na tych samych wierszach), a wszystko w ColumnTransformer/Pipeline. W szeregach czasowych dopasowuj parametry skalera w każdym oknie treningowym oddzielnie; walidacja widzi wyłącznie „zamrożone” wartości średniej i odchylenia z przeszłości.

Najważniejsza myśl jest prosta: nie walcz z modelem, jeśli dane uciekają bokiem. Uszczelnij podział, powiąż przygotowanie w jednym pipeline i dopiero wtedy ruszaj w eksperymenty – zaczynając od wag klas lub progu, a SMOTE i bardziej zamaszyste ruchy zostaw na moment, gdy baza jest naprawdę stabilna.

Najczęściej zadawane pytania (FAQ)

Jak szybko wykryć duplikaty i „bliźniacze” rekordy w danych?

Najpierw ustal klucz porównawczy: identyfikator + znacznik czasu (np. zaokrąglony do minuty) lub inny zestaw pól, które definiują jedno zdarzenie. Klasyczne duplikaty wyłapiesz po pełnej zgodności pól, ale „bliźniaki” wymagają grupowania po kluczu i sprawdzenia rozbieżności w pozostałych kolumnach (np. dwie płatności o tym samym ID i czasie, lecz z różną kwotą zaokrąglenia).

Potem zdecyduj, co jest źródłem prawdy: zachować najnowszy rekord, scalić pola (np. średnia/mediana dla kwot, maksymalna dla statusu), czy odrzucić sprzeczne wpisy. Jeśli predykcja opiera się na czasie, trzymaj się zasady „nic z przyszłości”: nie łącz danych, które nie byłyby znane w momencie zdarzenia.

Braki danych: kiedy imputować, a kiedy usuwać kolumny lub wiersze?

Nie ma jednego progu procentowego. Kieruj się trzema pytaniami: jak ważna jest cecha biznesowo, czy mechanizm braków niesie informację (flaga „było puste” bywa silnym sygnałem), oraz czy po uzupełnieniu cecha nadal ma zróżnicowanie. Wiersze usuwaj tylko wtedy, gdy braki są liczne i nieodtwarzalne — szczególnie uważaj, by nie wycinać rzadkiej klasy.

Dla liczb bezpieczna bywa mediana; gdy zależności są bogatsze, użyj KNN/MICE. Dla kategorii sprawdza się najczęstsza wartość lub osobna kategoria „Missing”. Klucz operacyjny: każdy imputer dopasuj wyłącznie na treningu (w ramach foldów), a następnie transformuj walidację i test, by nie wprowadzić cichego przecieku.

Jak kodować zmienne kategoryczne bez ryzyka przecieku?

Najpierw rozpoznaj porządek. Gdy istnieje (np. „Basic < Standard < Premium”), użyj kodowania porządkowego z jawnie ustawioną kolejnością. Dla nominalnych kategorii o małej liczbie wartości wybierz one‑hot i ustaw „handle_unknown=’ignore’”, aby nowe kategorie w walidacji/test nie wywoływały błędów.