Przejdź do treści

Jak Przygotować Dane do Uczenia Maszynowego w 5 Krokach

Przygotowanie danych to 80% pracy w każdym projekcie ML. Sprawdź, jak krok po kroku przeprowadzić preprocessing danych, oczyścić dataset i przygotować go do trenowania modelu.

Zespół VITA7 min czytania

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:

Python
import 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:

  1. Usunięcie wierszy lub kolumn z dużym odsetkiem braków (zazwyczaj powyżej 40-50%). Używaj ostrożnie, bo tracisz dane.
  2. Imputacja prostą statystyką: mediana dla zmiennych numerycznych, moda dla kategorycznych.
  3. Imputacja zaawansowana: algorytm KNNImputer z scikit-learn lub IterativeImputer (oparty na regresji).
Python
from 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

Python
df = 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):

Python
df = pd.get_dummies(df, columns=["kraj", "kategoria"], drop_first=True)

Label Encoding (dla zmiennych porządkowych, np. rozmiar: S, M, L, XL):

Python
from 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

Python
df["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.

Python
from 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.

Python
from 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.
Python
from 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.
Python
from 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:

ZadanieBiblioteka/Narzędzie
Eksploracja i manipulacja danychpandas, NumPy
Wizualizacjamatplotlib, seaborn, Plotly
Preprocessing i encodingscikit-learn
Raport EDAydata-profiling, Sweetviz
Obsługa niezbalansowanych klasimbalanced-learn
Przetwarzanie tekstuNLTK, spaCy
Pipeline MLscikit-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:

Python
from 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.

Najczęściej zadawane pytania

Ile czasu zajmuje przygotowanie danych do uczenia maszynowego?

Przygotowanie danych zajmuje przeciętnie 60-80% całego czasu projektu machine learning. Zależy to od jakości surowych danych, liczby cech i złożoności problemu. Mały, czysty dataset można przygotować w kilka godzin. Duże, zaszumione zbiory danych z wielu źródeł wymagają dni lub tygodni pracy.

Jakie biblioteki Pythona są potrzebne do preprocessingu danych?

Podstawowe biblioteki to pandas (manipulacja danymi), NumPy (operacje numeryczne) i scikit-learn (preprocessing, encoding, podział datasetu). Do wizualizacji przyda się seaborn lub matplotlib. Przy niezbalansowanych klasach sięgnij po imbalanced-learn, a do automatycznych raportów EDA po ydata-profiling.

Co to jest data leakage i jak go uniknąć?

Data leakage to sytuacja, gdy informacje z zestawu testowego trafiają do procesu trenowania modelu, co daje sztucznie zawyżone wyniki. Najczęstszy błąd to dopasowanie scalera lub imputera na całym zbiorze przed podziałem na train i test. Żeby uniknąć leakage, zawsze najpierw podziel dane, a dopiero potem fituj preprocessor tylko na danych treningowych.

Jak radzić sobie z niezbalansowanymi klasami w danych?

Niezbalansowane klasy można obsłużyć na kilka sposobów: oversampling z metodą SMOTE (biblioteka imbalanced-learn), undersampling klasy dominującej lub użycie parametru class_weight='balanced' w modelach scikit-learn. Ważne jest też stosowanie właściwych metryk, takich jak F1-score, precision, recall i AUC-ROC, zamiast samej dokładności (accuracy).

Czy drzewa decyzyjne i XGBoost wymagają normalizacji danych?

Nie. Algorytmy oparte na drzewach decyzyjnych, takie jak Random Forest, XGBoost czy LightGBM, są odporne na skalę cech i nie wymagają normalizacji ani standaryzacji. Skalowanie jest natomiast konieczne dla regresji logistycznej, SVM, sieci neuronowych i algorytmów opartych na odległościach, takich jak KNN czy K-Means.

Jak podzielić dane na zbiór treningowy i testowy w Pythonie?

Standardowo używa się funkcji train_test_split z biblioteki scikit-learn. Typowy podział to 70-80% danych na trening i 20-30% na testy. Przy danych szeregów czasowych należy użyć TimeSeriesSplit zamiast losowego podziału, żeby uniknąć wyciekania informacji z przyszłości do zbioru treningowego. Zawsze ustawiaj parametr random_state dla odtwarzalności wyników.

Udostępnij artykuł

Polecane kursy

Powiązane artykuły