Machine Learning Academy · Lekcja

Losowe podpróbkowanie i Cluster Centroids

Uczą się Państwo losowo zmniejszać klasę większościową oraz stosować ClusterCentroids, porównując utratę informacji i uzyskaną skuteczność modelu.

Lekcja 3 z 413 kroki

Losowe podpróbkowanie i Cluster Centroids to bezpłatna lekcja Machine Learning Academy na CoddyKit. To lekcja 3 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Machine Learning Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Machine Learning Academy zawiera 4 lekcji w sumie.

Podpróbkowanie: zmniejszanie klasy większościowej

Podczas gdy nadpróbkowanie powiększa klasę mniejszościową, podpróbkowanie zmniejsza klasę większościową, aby zrównoważyć zbiór danych. Główna zaleta: trenowanie przebiega szybciej, ponieważ ogólna liczba danych jest mniejsza. Główne ryzyko: odrzucane są rzeczywiste informacje o klasie większościowej, co może powodować częstsze przewidywanie przez model fałszywych przypadków pozytywnych. Podpróbkowanie jest najbardziej przydatne, gdy klasa większościowa jest tak liczna, że nadpróbkowanie nadmiernie wydłużyłoby trenowanie.

Random Undersampling: losowe usuwanie przykładów klasy większościowej

RandomUnderSampler losowo wybiera i usuwa przykłady klasy większościowej do momentu osiągnięcia żądanej proporcji. Jest to najszybsza metoda podpróbkowania, ale odrzuca potencjalnie użyteczne informacje. W przypadku małych zbiorów danych losowe podpróbkowanie może znacznie pogorszyć model, ponieważ usuwa przykłady klasy większościowej znajdujące się w pobliżu granicy decyzyjnej.

from imblearn.under_sampling import RandomUnderSampler
from sklearn.datasets import make_classification
import numpy as np

X, y = make_classification(n_samples=1000, weights=[0.95, 0.05],
                            n_features=10, random_state=42)

print('Before undersampling:', np.bincount(y))

rus = RandomUnderSampler(sampling_strategy=1.0, random_state=42)
X_res, y_res = rus.fit_resample(X, y)

print('After undersampling:', np.bincount(y_res))
print('New total samples:', len(y_res))

Kontrolowanie strategii próbkowania

Parametr sampling_strategy określa końcowy stosunek liczebności klasy mniejszościowej do większościowej. Wartość 1.0 wyrównuje ich liczebność, a 0.5 pozostawia przewagę klasy większościowej w stosunku 2:1. W przypadku bardzo dużych zbiorów danych można ustawić 0.1, aby uzyskać stosunek 10:1 — nadal znacznie lepszy niż pierwotne 100:1, a jednocześnie zachować krótki czas trenowania. Wartość należy dobrać na podstawie kosztu biznesowego fałszywych alarmów w porównaniu z przeoczeniami.

from imblearn.under_sampling import RandomUnderSampler
from sklearn.datasets import make_classification
import numpy as np

X, y = make_classification(n_samples=10000, weights=[0.99, 0.01], random_state=42)
print('Original:', np.bincount(y))

for ratio in [1.0, 0.5, 0.2]:
    rus = RandomUnderSampler(sampling_strategy=ratio, random_state=0)
    _, y_r = rus.fit_resample(X, y)
    counts = np.bincount(y_r)
    print(f'ratio={ratio}: {counts} ({counts[1]/counts[0]:.2f} min:maj)')

Centroidy klastrów: inteligentne undersampling

ClusterCentroids stosuje klasteryzację K-Means do klasy większościowej, zastępując każdy klaster jego centroidem. Zamiast zachowywać losowe próbki klasy większościowej, metoda pozostawia skompresowany, reprezentatywny zbiór. Pozwala to lepiej zachować ogólną strukturę klasy większościowej niż losowe usuwanie próbek, ale metoda działa wolniej i wymaga dostrojenia liczby klastrów (równej docelowej liczebności klasy większościowej po resamplingu).

from imblearn.under_sampling import ClusterCentroids
from sklearn.datasets import make_classification
import numpy as np

X, y = make_classification(n_samples=1000, weights=[0.9, 0.1],
                            n_features=5, random_state=42)

print('Before:', np.bincount(y))

cc = ClusterCentroids(sampling_strategy=1.0, random_state=42)
X_cc, y_cc = cc.fit_resample(X, y)

print('After ClusterCentroids:', np.bincount(y_cc))
print('Note: synthetic centroids replace real majority samples')

Porównanie metod undersamplingu

Porównajmy random undersampling, centroidy klastrów oraz brak resamplingu na tym samym niezbalansowanym zbiorze danych, używając wyniku F1 dla klasy mniejszościowej jako metryki oceny.

from imblearn.under_sampling import RandomUnderSampler, ClusterCentroids
from imblearn.pipeline import Pipeline as ImbPipeline
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import f1_score
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
import numpy as np

X, y = make_classification(n_samples=1000, weights=[0.95, 0.05], random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=y, random_state=42)

sc = StandardScaler()
X_tr = sc.fit_transform(X_train)
X_te = sc.transform(X_test)

for name, sampler in [('None', None),
                       ('RUS', RandomUnderSampler(random_state=0)),
                       ('ClusterCentroids', ClusterCentroids(random_state=0))]:
    if sampler:
        Xr, yr = sampler.fit_resample(X_tr, y_train)
    else:
        Xr, yr = X_tr, y_train
    lr = LogisticRegression().fit(Xr, yr)
    f1 = f1_score(y_test, lr.predict(X_te))
    print(f'{name:20s}: F1={f1:.4f}  n_train={len(yr)}')

Utrata informacji podczas undersamplingu

Najpoważniejszą wadą undersamplingu jest utrata informacji. Gdy odrzucanych jest 95 na każde 100 próbek klasy większościowej, model widzi rozkład danych treningowych bardzo różny od rzeczywistego. Może to zwiększyć odsetek fałszywych alarmów w środowisku produkcyjnym. Z tego powodu undersampling często łączy się z oversamplingiem (np. przy użyciu SMOTEENN lub SMOTETomek), aby zrównoważyć zbiór danych przy jednoczesnym ograniczeniu utraty informacji.

Łączenie oversamplingu i undersamplingu

SMOTETomek łączy SMOTE (zwiększanie liczebności klasy mniejszościowej) z usuwaniem łączy Tomeka (oczyszczaniem niejednoznacznych próbek klasy większościowej znajdujących się przy granicy). W rezultacie obie klasy zostają zbalansowane, a próbki klasy większościowej leżące przy granicy, które wprowadzają klasyfikator w błąd, zostają usunięte. Takie podejście często daje lepsze wyniki niż sam oversampling lub sam undersampling.

from imblearn.combine import SMOTETomek
from sklearn.datasets import make_classification
import numpy as np

X, y = make_classification(n_samples=1000, weights=[0.95, 0.05], random_state=42)
print('Before:', np.bincount(y))

st = SMOTETomek(random_state=42)
X_res, y_res = st.fit_resample(X, y)
print('After SMOTETomek:', np.bincount(y_res))

Near Miss: undersampling oparty na odległości

NearMiss wybiera próbki klasy większościowej na podstawie ich odległości od próbek klasy mniejszościowej — wybierając albo próbki najbliższe (NearMiss-1), albo najdalsze (NearMiss-3). W przeciwieństwie do losowego undersamplingu NearMiss zachowuje próbki klasy większościowej, które mają największe znaczenie dla wyznaczenia granicy decyzyjnej. NearMiss-3 zachowuje próbki klasy większościowej najbardziej oddalone od wszystkich próbek klasy mniejszościowej, tworząc bardziej przejrzysty obszar granicy.

from imblearn.under_sampling import NearMiss
from sklearn.datasets import make_classification
import numpy as np

X, y = make_classification(n_samples=1000, weights=[0.9, 0.1], random_state=42)
print('Before:', np.bincount(y))

for version in [1, 2, 3]:
    nm = NearMiss(version=version)
    _, y_nm = nm.fit_resample(X, y)
    print(f'NearMiss-{version}:', np.bincount(y_nm))

Undersampling wewnątrz potoku imblearn

Podobnie jak oversampling, undersampling musi odbywać się wewnątrz potoku, aby zapobiec wyciekowi danych podczas walidacji krzyżowej. Należy użyć imblearn.pipeline.Pipeline, umieszczając undersampler jako krok przed klasyfikatorem. Metoda fit_resample samplera jest wywoływana dla każdego fragmentu treningowego, a fragmenty testowe nigdy nie są modyfikowane.

from imblearn.pipeline import Pipeline as ImbPipeline
from imblearn.under_sampling import RandomUnderSampler
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import cross_val_score
from sklearn.datasets import make_classification
import numpy as np

X, y = make_classification(n_samples=1000, weights=[0.95, 0.05], random_state=42)

pipe = ImbPipeline([
    ('sc', StandardScaler()),
    ('rus', RandomUnderSampler(random_state=42)),
    ('lr', LogisticRegression())
])

scores = cross_val_score(pipe, X, y, cv=5, scoring='f1')
print(f'CV F1 (RUS): {np.mean(scores):.4f} +/- {np.std(scores):.4f}')

Kiedy wybrać undersampling zamiast oversamplingu

Undersampling warto wybrać, gdy: klasa większościowa jest ogromna (miliony próbek), czas trenowania stanowi wąskie gardło lub zasoby obliczeniowe są ograniczone. Oversampling (SMOTE) warto wybrać, gdy: klasa mniejszościowa jest bardzo mała (ma mniej niż kilkaset próbek), odrzucenie danych klasy większościowej nadmiernie zmniejszyłoby zbiór treningowy lub klasa mniejszościowa ma złożoną, niewypukłą strukturę, którą SMOTE może uzupełnić. W praktyce warto wypróbować obie metody i porównać je na podstawie metryk walidacyjnych.

Ocena po undersamplingu

Po resamplingu należy zawsze przeprowadzać ocenę na oryginalnym niezbalansowanym zbiorze testowym — nigdy na zbiorze testowym po resamplingu. Resampling danych testowych dałby nierealistyczny obraz skuteczności w środowisku produkcyjnym. Celem jest poprawa zachowania modelu dla rzeczywistego rozkładu danych, a nie optymalizacja pod kątem sztucznie zbalansowanego rozkładu.

from sklearn.metrics import classification_report
from imblearn.under_sampling import RandomUnderSampler
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split

X, y = make_classification(n_samples=1000, weights=[0.95, 0.05], random_state=42)
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, stratify=y, random_state=42)

sc = StandardScaler()
X_train_s = sc.fit_transform(X_train)
X_test_s = sc.transform(X_test)

rus = RandomUnderSampler(random_state=0)
X_r, y_r = rus.fit_resample(X_train_s, y_train)

lr = LogisticRegression().fit(X_r, y_r)
# Evaluate on ORIGINAL imbalanced test set
print(classification_report(y_test, lr.predict(X_test_s)))

Szybkie sprawdzenie

Sprawdź swoją wiedzę na temat undersamplingu i Cluster Centroids z tego rozdziału.

Podsumowanie rozdziału

W tym rozdziale nauczyłeś się, że: RandomUnderSampler losowo usuwa próbki klasy większościowej — działa szybko, ale może powodować utratę ważnych informacji o granicy, ClusterCentroids zastępuje klastry klasy większościowej ich centroidami, aby wierniej zachować rozkład klas, a także że zawsze należy przeprowadzać ocenę na oryginalnym niezbalansowanym zbiorze testowym, aby zmierzyć zachowanie modelu w rzeczywistych warunkach. Następnie omówimy wagi klas i przesuwanie progu jako alternatywy dla resamplingu.

Bezpłatny start

Ucz się Python dzięki korepetycjom AI — za darmo

Pisz i uruchamiaj kod w przeglądarce, otrzymuj natychmiastową pomoc od korepetytora AI dostępnego 24/7 i kontynuuj naukę w sieci lub w aplikacji.

Kursy
30
Lekcje
120

Często zadawane pytania

Czy lekcja „Losowe podpróbkowanie i Cluster Centroids” jest bezpłatna?

Tak — pełny tekst „Losowe podpróbkowanie i Cluster Centroids” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Machine Learning Academy, przejdź na CoddyKit PRO. Kurs Machine Learning Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Losowe podpróbkowanie i Cluster Centroids”?

Uczą się Państwo losowo zmniejszać klasę większościową oraz stosować ClusterCentroids, porównując utratę informacji i uzyskaną skuteczność modelu. Ćwiczysz Machine Learning Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Machine Learning Academy?

Nie wymagamy żadnego doświadczenia. Machine Learning Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 3 z 4.

Ile czasu zajmuje lekcja „Losowe podpróbkowanie i Cluster Centroids”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Machine Learning Academy?

Tak. Każda lekcja Machine Learning Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Wykrywanie niezbalansowania: rozkład klas i pułapki modelu bazowego
  2. Losowe nadpróbkowanie i SMOTE
  3. Losowe podpróbkowanie i Cluster Centroids
  4. Wagi klas i przesuwanie progu
← Powrót do Machine Learning Academy