Jak przygotować dane do uczenia maszynowego? Odpowiedź jest prosta: zanim Twój model zobaczy choćby jedną liczbę, musisz zebrać, oczyścić, przetransformować i podzielić dane na zestawy treningowe i testowe. Badania pokazują, że data scientists spędzają nawet 80% czasu projektu właśnie na przygotowaniu danych, a nie na budowie modelu. Ten artykuł przeprowadzi Cię przez pięć konkretnych kroków, które zmienią surowy dataset w solidną podstawę dla każdego algorytmu machine learning.
Dlaczego preprocessing danych machine learning jest kluczowy?
Model uczy się wyłącznie na tym, co mu podasz. Zasada "garbage in, garbage out" obowiązuje tu bez wyjątków. Nawet najlepszy algorytm, na przykład XGBoost czy sieć neuronowa, nie wyciągnie sensownych wniosków z danych pełnych błędów, brakujących wartości czy sprzecznych formatów.
Wyobraź sobie zbiór danych o klientach e-commerce: jedna kolumna zawiera daty w trzech różnych formatach, inna ma 30% braków, a kategoria produktów kodowana jest raz jako liczba, raz jako tekst. Żaden model nie poradzi sobie z takim chaosem bez Twojej wcześniejszej interwencji.
Dobre przygotowanie datasetu przekłada się bezpośrednio na:
- wyższą dokładność modelu (accuracy, F1-score, AUC),
- krótszy czas trenowania,
- lepszą generalizację na nowych danych,
- łatwiejsze debugowanie, gdy coś idzie nie tak.
Krok 1. Zbierz i poznaj swoje dane (Data Understanding)
Zanim zaczniesz cokolwiek zmieniać, musisz wiedzieć, z czym masz do czynienia. W Pythonie wystarczy kilka linijek z biblioteką pandas:
Pythonimport pandas as pd df = pd.read_csv("dataset.csv") print(df.shape) # liczba wierszy i kolumn print(df.dtypes) # typy danych print(df.describe()) # statystyki opisowe print(df.isnull().sum()) # braki w każdej kolumnie
Co sprawdzić na tym etapie?
- Rozmiar zbioru: ile rekordów, ile cech (features)?
- Typy kolumn: numeryczne, kategoryczne, tekstowe, daty?
- Rozkłady wartości: czy dane są symetryczne, skośne, bimodalne?
- Braki i anomalie: gdzie i ile ich jest?
- Duplikaty:
df.duplicated().sum()pokaże powtórzone wiersze.
Warto też zwizualizować dane za pomocą seaborn lub matplotlib. Histogram, wykres pudełkowy (boxplot) i macierz korelacji (heatmap) ujawnią rzeczy, których describe() nie pokaże.
Nie pomijaj eksploracji danych. Jedno spojrzenie na histogram może zaoszczędzić godzin debugowania modelu.
Narzędzia, które warto znać: pandas, ydata-profiling (dawniej pandas-profiling) generuje kompletny raport EDA jedną linią kodu, a Sweetviz porównuje dwa datasety wizualnie.
Krok 2. Oczyść dane (Data Cleaning)
Czyszczenie danych do AI to najżmudniejszy, ale absolutnie niezbędny etap. Obejmuje kilka kategorii problemów.
Brakujące wartości
Masz trzy główne strategie:
- Usunięcie wierszy lub kolumn z dużym odsetkiem braków (zazwyczaj powyżej 40-50%). Używaj ostrożnie, bo tracisz dane.
- Imputacja prostą statystyką: mediana dla zmiennych numerycznych, moda dla kategorycznych.
- Imputacja zaawansowana: algorytm KNNImputer z scikit-learn lub IterativeImputer (oparty na regresji).
Pythonfrom sklearn.impute import SimpleImputer import numpy as np imputer = SimpleImputer(strategy="median") df[["wiek", "dochod"]] = imputer.fit_transform(df[["wiek", "dochod"]])
Wartości odstające (outliers)
Outliersy potrafią poważnie skrzywić model, szczególnie regresję liniową. Metody wykrywania:
- IQR (Interquartile Range): wartości poniżej Q1 - 1,5·IQR lub powyżej Q3 + 1,5·IQR to kandydaci do usunięcia lub klipowania.
- Z-score: wartości oddalone o więcej niż 3 odchylenia standardowe.
- Isolation Forest ze scikit-learn: skuteczny dla wielowymiarowych danych.
Decyzja, co zrobić z outlierem, zawsze zależy od kontekstu. Jeśli analizujesz transakcje bankowe, ekstremalnie wysoka kwota może być właśnie tym, czego szukasz (fraud detection).
Duplikaty i błędy
Pythondf = df.drop_duplicates() df["email"] = df["email"].str.lower().str.strip()
Ustandaryzuj format tekstów, popraw literówki w kategoriach (np. "Warszawa", "warszawa", "WARSZAWA" to to samo miasto) i sprawdź spójność jednostek (km vs. mile, zł vs. EUR).
Krok 3. Przekształć i zakoduj zmienne (Feature Engineering i Encoding)
Algorytmy machine learning operują na liczbach. Zmienne kategoryczne, daty i teksty trzeba zamienić na postać numeryczną.
Kodowanie zmiennych kategorycznych
One-Hot Encoding (dla zmiennych nominalnych bez porządku, np. kolor, kraj):
Pythondf = pd.get_dummies(df, columns=["kraj", "kategoria"], drop_first=True)
Label Encoding (dla zmiennych porządkowych, np. rozmiar: S, M, L, XL):
Pythonfrom sklearn.preprocessing import LabelEncoder le = LabelEncoder() df["rozmiar"] = le.fit_transform(df["rozmiar"])
Target Encoding sprawdza się przy dużej liczbie kategorii (np. tysiące miast) i pozwala uniknąć eksplozji wymiarowości, która jest skutkiem ubocznym One-Hot Encodingu.
Przetwarzanie dat
Pythondf["data"] = pd.to_datetime(df["data"]) df["rok"] = df["data"].dt.year df["miesiac"] = df["data"].dt.month df["dzien_tygodnia"] = df["data"].dt.dayofweek
Feature Engineering
Tworzenie nowych cech na podstawie istniejących często zwiększa jakość modelu bardziej niż dobór algorytmu. Przykłady:
- Z daty urodzenia i daty zdarzenia oblicz wiek.
- Z ceny i liczby sztuk oblicz wartość zamówienia.
- Z tekstu wyciągnij długość, liczbę słów, sentymenty za pomocą NLTK lub spaCy.
Dobra cecha to taka, która niesie informację niedostępną wprost w surowych kolumnach. Myśl jak analityk, nie tylko jak programista.
Krok 4. Znormalizuj lub przeskaluj dane (Scaling)
Wiele algorytmów, w tym regresja logistyczna, SVM, sieci neuronowe i metody oparte na odległościach (KNN, K-Means), jest wrażliwych na skalę cech. Kolumna "wiek" (20-80) i kolumna "dochód" (20 000-200 000) będą miały dramatycznie różny wpływ na model, jeśli nie wykonasz skalowania.
Dwie główne metody
Min-Max Scaling (Normalizacja): sprowadza wartości do przedziału [0, 1]. Dobra, gdy rozkład nie jest normalny.
Pythonfrom sklearn.preprocessing import MinMaxScaler scaler = MinMaxScaler() df[["wiek", "dochod"]] = scaler.fit_transform(df[["wiek", "dochod"]])
Standaryzacja (StandardScaler): przekształca dane tak, żeby miały średnią 0 i odchylenie standardowe 1. Lepsza dla algorytmów zakładających rozkład normalny.
Pythonfrom sklearn.preprocessing import StandardScaler scaler = StandardScaler() df[["wiek", "dochod"]] = scaler.fit_transform(df[["wiek", "dochod"]])
Ważna zasada: scaler dopasowujesz (fit) tylko na danych treningowych, a następnie stosujesz (transform) na danych walidacyjnych i testowych. Inaczej popełniasz data leakage, czyli nieświadome "podpowiadanie" modelowi informacji z przyszłości lub z zestawu testowego.
Algorytmy oparte na drzewach decyzyjnych (Random Forest, XGBoost, LightGBM) są odporne na skalę, więc skalowanie nie jest dla nich konieczne.
Krok 5. Podziel dataset i zadbaj o równowagę klas
Podział na zbiory
Standardowy podział to:
- Zbiór treningowy (train): 70-80% danych, na nim model się uczy.
- Zbiór walidacyjny (validation): 10-15%, dobierasz hiperparametry.
- Zbiór testowy (test): 10-15%, ostateczna ocena modelu, dotykasz go tylko raz.
Pythonfrom sklearn.model_selection import train_test_split X = df.drop("target", axis=1) y = df["target"] X_train, X_temp, y_train, y_temp = train_test_split(X, y, test_size=0.3, random_state=42) X_val, X_test, y_val, y_test = train_test_split(X_temp, y_temp, test_size=0.5, random_state=42)
Parametr random_state=42 gwarantuje odtwarzalność wyników. Przy danych ze strukturą czasową (time series) używaj TimeSeriesSplit, a nie losowego podziału, żeby uniknąć wyciekania informacji z przyszłości.
Niezbalansowane klasy
Jeśli Twój problem klasyfikacyjny ma klasy mocno nierówne (np. 95% transakcji jest prawidłowych, 5% to fraudy), zwykła dokładność (accuracy) jest mylącym miernikiem. Model uczący się "nic nie jest fraudem" osiągnie 95% accuracy, nie będąc użytecznym.
Rozwiązania:
- Oversampling: SMOTE (Synthetic Minority Over-sampling Technique) z biblioteki imbalanced-learn generuje syntetyczne przykłady mniejszościowej klasy.
- Undersampling: losowe usuwanie próbek z klasy dominującej.
- Parametr class_weight="balanced" dostępny w większości modeli scikit-learn.
Pythonfrom imblearn.over_sampling import SMOTE sm = SMOTE(random_state=42) X_train_res, y_train_res = sm.fit_resample(X_train, y_train)
Walidacja krzyżowa
Przy małych zbiorach danych warto zastąpić pojedynczy podział k-fold cross-validation. Scikit-learn oferuje cross_val_score, który automatyzuje ten proces i daje bardziej wiarygodną ocenę modelu.
Narzędzia i biblioteki, które warto znać
Poniżej zestawienie najważniejszych narzędzi do przygotowania datasetu w Pythonie:
| Zadanie | Biblioteka/Narzędzie |
|---|---|
| Eksploracja i manipulacja danych | pandas, NumPy |
| Wizualizacja | matplotlib, seaborn, Plotly |
| Preprocessing i encoding | scikit-learn |
| Raport EDA | ydata-profiling, Sweetviz |
| Obsługa niezbalansowanych klas | imbalanced-learn |
| Przetwarzanie tekstu | NLTK, spaCy |
| Pipeline ML | scikit-learn Pipeline |
Pipeline ze scikit-learn pozwala połączyć wszystkie kroki preprocessingu w jeden obiekt, co eliminuje ryzyko data leakage i ułatwia deployment modelu:
Pythonfrom sklearn.pipeline import Pipeline from sklearn.preprocessing import StandardScaler from sklearn.impute import SimpleImputer from sklearn.linear_model import LogisticRegression pipe = Pipeline([ ("imputer", SimpleImputer(strategy="median")), ("scaler", StandardScaler()), ("model", LogisticRegression()) ]) pipe.fit(X_train, y_train)
Dokumentacja scikit-learn (scikit-learn.org) to jedno z najlepszych źródeł wiedzy o preprocessingu, dostępne bezpłatnie.
Jeśli chcesz pójść dalej i zrozumieć, jak modele machine learning faktycznie działają od środka, polecam kurs Sztuczna Inteligencja: Jak Działa AI od Środka dostępny na platformie VITA. Kurs tłumaczy mechanizmy stojące za algorytmami, z którymi pracujesz przy przygotowaniu danych, więc przestajesz działać na ślepo i zaczynasz podejmować świadome decyzje projektowe.
Możesz przetestować ten kurs oraz wszystkie inne materiały VITA przez 3 dni całkowicie za darmo. Wystarczy karta płatnicza do rejestracji. Jeśli zdecydujesz się zostać, abonament kosztuje 79 zł miesięcznie lub 590 zł rocznie. Anulujesz jednym kliknięciem w panelu przed końcem okresu próbnego. Zacznij teraz: vita.edu.pl/abonament.
Najczęstsze błędy przy przygotowaniu danych
Nawet doświadczeni data scientists popełniają te błędy. Sprawdź, czy żaden z nich nie czeka na Ciebie w Twoim projekcie.
1. Data leakage. Dopasowujesz scaler lub imputację na całym zbiorze danych przed podziałem. Wynik: model wygląda świetnie na testach, a na produkcji zawodzi.
2. Usuwanie outlierów bez analizy. Wartości ekstremalne to czasem najważniejszy sygnał (fraud, awaria maszyny, wybitny klient).
3. One-Hot Encoding zbyt wielu kategorii. Kolumna z 500 unikalnymi miastami daje 500 nowych kolumn binarnych. Zamiast tego użyj Target Encodingu lub embeddings.
4. Ignorowanie rozkładu zmiennej celu. Jeśli klasy są niezbalansowane, accuracy to zły miernik. Sprawdzaj F1-score, precision, recall i AUC-ROC.
5. Brak odtwarzalności. Nie ustawiasz random_state. Wyniki zmieniają się przy każdym uruchomieniu skryptu, co uniemożliwia porównywanie eksperymentów.
6. Zapomnienie o preprocessingu przy deploymencie. Scaler i encoder muszą być zapisane (np. przez joblib lub pickle) i zastosowane na nowych danych produkcyjnych dokładnie tak samo jak podczas trenowania.
Checklist przed przekazaniem danych do modelu
Przed uruchomieniem trenowania przejdź przez tę listę:
- Sprawdziłem(-am) kształt datasetu i typy kolumn.
- Obsłużyłem(-am) braki (imputacja lub usunięcie).
- Wykryłem(-am) i podjąłem(-am) decyzję o outlierach.
- Usunąłem(-am) duplikaty.
- Zakodowałem(-am) zmienne kategoryczne.
- Przetransformowałem(-am) daty i wyciągnąłem(-am) przydatne cechy.
- Zastosuję skalowanie po podziale, nie przed.
- Podzieliłem(-am) dane na train, val i test przed dopasowaniem scalera.
- Sprawdziłem(-am) balans klas i wybrałem(-am) odpowiedni miernik.
- Zapisałem(-am) pipeline do pliku, żeby użyć go przy deploymencie.
Dobrego preprocessingu nie widać w wynikach bezpośrednio, ale jego brak widać natychmiast. Zadbaj o dane tak solidnie, jak o sam model, a każdy kolejny projekt będzie szybszy i skuteczniejszy.