10 · Praktyka · 3 min czytania · aktualizacja
Jak zapewnić powtarzalność wyników w uczeniu maszynowym?
W skrócie
Powtarzalność to możliwość odtworzenia wyniku: te same dane, kod, wersje bibliotek i ziarna losowości, a także raport rozrzutu wyniku między ziarnami.
Co to jest
Powtarzalność (reproducibility) eksperymentu ML oznacza, że ktoś inny — albo ty za pół roku — uruchamiając ten sam kod na tych samych danych dostanie ten sam wynik. W szerszym sensie oznacza też, że wniosek („model B jest lepszy od A”) przetrwa zmianę rzeczy, które nie powinny mieć znaczenia: ziarna losowości, kolejności danych, sprzętu.
Te dwa poziomy warto odróżniać. Pierwszy to inżynieria: ustalone ziarna, zamrożone wersje, zapisane dane. Drugi to statystyka: nawet idealnie odtwarzalny wynik może być przypadkiem jednego szczęśliwego ziarna. Wynik, który znika przy innym random_state, był odtwarzalny, ale nieprawdziwy.
Mechanizm — dlaczego tak działa
Losowość jest w ML wszędzie: podział na zbiory i foldy, tasowanie mini-batchy, inicjalizacja wag, losowanie cech i próbek w lasach, dropout, augmentacja. Każde z tych źródeł zmienia wynik o trochę, a „trochę” bywa tej samej wielkości co różnica, którą chcemy zgłosić. Ustalenie ziarna zamraża jedną konkretną realizację tej losowości — nie usuwa jej wpływu, tylko go ukrywa.
Do tego dochodzą źródła mniej oczywiste. Wersja biblioteki może zmienić domyślny hiperparametr albo algorytm. Obliczenia równoległe na GPU sumują liczby zmiennoprzecinkowe w różnej kolejności, a dodawanie zmiennoprzecinkowe nie jest łączne, więc wyniki różnią się na ostatnich bitach — w długim treningu sieci te różnice potrafią urosnąć. Dane „z bazy” zmieniają się między uruchomieniami, jeśli nie zostały zapisane w konkretnej wersji.
Stąd dwie strategie. Inżynierska: zapisz wszystko, co wpływa na wynik — ziarna, wersje pakietów (plik z zamrożonymi wersjami, kontener), skrót lub wersję danych, konfigurację, commit kodu. Statystyczna: powtórz eksperyment dla kilku ziaren i kilku podziałów, a zgłaszaj średnią i rozrzut. Różnica między modelami jest wiarygodna dopiero wtedy, gdy jest wyraźnie większa niż rozrzut każdego z nich.
Uwaga na pułapkę: wybieranie najlepszego ziarna to też strojenie hiperparametru, tylko bezwartościowego. Taki wynik jest obciążony w górę dokładnie tak samo jak wybór najlepszego z wielu modeli na jednym zbiorze walidacyjnym.
Na przykładzie
Titanic, las losowy ze 100 drzewami, 5-krotna walidacja krzyżowa. Przy ustalonym podziale na foldy i 10 różnych ziarnach modelu wynik waha się od 80,7% do 81,6% (odchylenie standardowe 0,3 punktu procentowego). Przy ustalonym ziarnie modelu i 10 różnych ziarnach podziału na foldy: od 80,1% do 82,6% (odchylenie 0,7 punktu). Losowość podziału danych waży tu więcej niż losowość samego modelu.
Jeszcze wyraźniej widać to przy pojedynczym podziale 80/20. Ta sama regresja logistyczna, oceniana na 179 pasażerach odłożonych z 10 różnymi ziarnami, osiąga od 78,8% do 84,4% — rozpiętość 5,6 punktu. Ktoś, kto porównuje dwa modele na jednym takim podziale, może z powodzeniem „udowodnić” dowolną kolejność.
Dane: Titanic
W praktyce
- Ustaw
random_statew każdym losowym obiekcie scikit-learn (train_test_split,KFold(shuffle=True), modele), a w PyTorchtorch.manual_seed,numpy.random.seed,random.seed. - Dla pełnego determinizmu w PyTorch:
torch.use_deterministic_algorithms(True)itorch.backends.cudnn.benchmark = False— kosztem szybkości. - Zapisuj wersje:
pip freeze > requirements.txtlub plik lock, najlepiej kontener; dane wersjonuj (skrót pliku, DVC, snapshot). - Raportuj średnią ± odchylenie z co najmniej 3–5 ziaren lub z
RepeatedStratifiedKFold, nie pojedynczy przebieg. - Porównując modele, używaj tych samych foldów dla obu — różnice parami są mniej zaszumione niż wyniki osobno.
- Typowy błąd: ustawione jedno ziarno globalne i przekonanie, że wynik jest „pewny”.
Najczęstsze pytania
- Ustawiłem ziarno, a wyniki na GPU i tak się różnią. Dlaczego?
- Część operacji na GPU (np. niektóre sploty i sumowania atomowe) jest niedeterministyczna, bo kolejność dodawania liczb zmiennoprzecinkowych zależy od harmonogramu wątków. PyTorch pozwala wymusić wersje deterministyczne, ale nie dla każdej operacji i zwykle wolniej.
- Ile ziaren wystarczy?
- Do szybkiej orientacji 3–5, do publikacji lub ważnej decyzji więcej, zależnie od rozrzutu. Ważniejsze od liczby jest porównanie: jeśli rozrzut między ziarnami jest tej samej wielkości co różnica między modelami, potrzeba więcej powtórzeń albo więcej danych, a nie lepszego ziarna.
- Czy powtarzalność to to samo co replikowalność?
- Terminologia nie jest jednolita. Często „odtwarzalność” oznacza ten sam wynik z tym samym kodem i danymi, a „replikację” — ten sam wniosek przy niezależnej implementacji lub nowych danych. Druga jest mocniejszym testem prawdziwości wyniku.
Źródła
- Pineau J. i in. „Improving Reproducibility in Machine Learning Research (A Report from the NeurIPS 2019 Reproducibility Program)”, Journal of Machine Learning Research 22, 2021.
- Henderson P. i in. „Deep Reinforcement Learning that Matters”, AAAI 2018.
- Bouthillier X., Laurent C., Vincent P. „Unreproducible Research is Reproducible”, ICML 2019.
- Dokumentacja PyTorch: „Reproducibility”, https://pytorch.org/docs/stable/notes/randomness.html
- Dokumentacja scikit-learn: „Controlling randomness”, https://scikit-learn.org/stable/common_pitfalls.html