Ćwiczenie 9: Projekt końcowy¶
Po co to ćwiczenie?¶
Przez osiem ćwiczeń poznawaliśmy elementy układanki osobno: podział danych, analizę eksploracyjną, przygotowanie cech (ang. features), regresję, klasyfikację, walidację krzyżową, drzewa, grupowanie. Za każdym razem ktoś prowadził Cię za rękę - był przykład prowadzony, a zadanie sprowadzało się do powtórzenia schematu na innym parametrze.
W prawdziwej pracy nikt nie daje przykładu prowadzonego. Dostajesz plik z danymi, pytanie od zleceniodawcy i termin.
To ćwiczenie jest właśnie takie. Nie ma tu przykładu prowadzonego ani gotowego schematu do skopiowania. Jest opis zadania i rusztowanie z sekcjami do wypełnienia. Cały kod i wszystkie decyzje należą do Ciebie.
Gdy utkniesz, wracaj do ćwiczeń 01-08 - masz tam wszystkie potrzebne elementy, tyle że pokazane osobno. Cała trudność tego projektu polega na złożeniu ich w całość we właściwej kolejności.
Pracujesz też na zbiorze danych, którego wcześniej nie było w kursie. To celowe. Chodzi nie o „znajomość zbioru diabetes.csv", tylko o zdolność zastosowania metody do nowego problemu.
Czego się nauczysz¶
- Jak samodzielnie przejść pełną ścieżkę: dane → zrozumienie → przygotowanie → modele → dobór → uczciwa ocena → wnioski.
- Jak zaplanować pracę tak, żeby na końcu dało się komuś wytłumaczyć, dlaczego wybór padł na ten, a nie inny model.
- Jak nie popełnić czterech błędów, które unieważniają wynik - nawet jeśli liczba na końcu wygląda świetnie.
- Jak napisać wniosek, który jest odpowiedzią na pytanie, a nie wykazem uruchomionych funkcji.
Ten notatnik jest Twoim szkieletem pracy. Wypełniaj go w miejscach oznaczonych
# TWÓJ KOD TUTAJoraz (tutaj Twój komentarz). Możesz dodawać własne komórki; sekcji lepiej nie usuwać, bo każda odpowiada za inny etap pracy.
Zbiór danych: rozpoznawanie odmiany wina¶
Pracujesz na zbiorze wine wbudowanym w scikit-learn. Nie wymaga pobierania z internetu - wczytuje się jedną funkcją.
Dane pochodzą z analizy chemicznej win pochodzących z jednego regionu Włoch, wyprodukowanych przez trzech różnych producentów. Dla każdej butelki zmierzono 13 wielkości chemicznych (zawartość alkoholu, kwasu jabłkowego, magnezu, flawonoidów, intensywność barwy, zawartość proliny i inne).
Zadanie: na podstawie wyników analizy chemicznej rozpoznać, od którego z trzech producentów pochodzi wino.
To jest klasyfikacja wieloklasowa (ang. multiclass classification) - i to pierwsza rzecz, która odróżnia ten projekt od wszystkiego, co było wcześniej w kursie. Klas nie ma dwóch, tylko trzy. Część rzeczy przenosi się wprost, część wymaga uwagi:
| Element | Klasyfikacja binarna (ćwiczenia 01-07) | Klasyfikacja wieloklasowa (ten projekt) |
|---|---|---|
| Macierz pomyłek | 2×2 | 3×3 - błędy dzielą się na więcej rodzajów |
| Skuteczność (ang. accuracy) | działa tak samo | działa tak samo |
| Precyzja, czułość, F1 | jedna liczba | osobno dla każdej klasy; do jednej liczby trzeba je uśrednić (average='macro' albo 'weighted') |
| Model odniesienia | „zawsze klasa większościowa" | to samo, ale poprzeczka jest niżej - klas jest więcej |
| Krzywa ROC | naturalna | wymaga podejścia „jedna klasa przeciw reszcie" - w tym projekcie możesz ją pominąć |
Druga istotna różnica: zbiór jest mały. To niecałe dwieście butelek - dwa rzędy wielkości mniej niż 10 000 kart pacjentów. Konsekwencje są poważne i trzeba będzie się z nimi zmierzyć:
- zbiór testowy liczy kilkadziesiąt próbek, więc jedna pomyłka więcej lub mniej zmienia wynik o punkty procentowe,
- pojedynczy podział danych jest bardzo niestabilny - walidacja krzyżowa przestaje być dobrą praktyką, a staje się koniecznością,
- stratyfikacja przestaje być kosmetyką (pamiętasz zadanie 7 z ćwiczenia 01? tam przy 10 000 wierszy nie robiła różnicy - tutaj zrobi).
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.dummy import DummyClassifier
from sklearn.metrics import ConfusionMatrixDisplay
# Jedno ziarno losowosci na caly projekt. Kazde miejsce, w ktorym sklearn
# losuje (podzial danych, inicjalizacja modelu), dostaje te sama wartosc -
# dzieki temu wynik da sie powtorzyc co do cyfry, takze na innym komputerze.
ZIARNO = 42
wino = load_wine(as_frame=True)
X = wino.data # 13 cech chemicznych
y = wino.target # 0, 1, 2 - trzech producentow
print("Liczba probek i cech:", X.shape)
print("Nazwy klas:", list(wino.target_names))
print()
print("Liczebnosc klas:")
print(y.value_counts().sort_index().to_string())
print()
print("Cechy:")
for nazwa in X.columns:
print(" -", nazwa)
Chcesz trudniej? Zamiast
load_winemożesz użyćload_digits- 1797 obrazków odręcznych cyfr, każdy jako 64 piksele (8×8), dziesięć klas. Wszystkie wymagania projektu pozostają te same. Zbiór jest większy i ma dziesięć klas zamiast trzech, więc macierz pomyłek robi się znacznie ciekawsza (które cyfry mylą się ze sobą?), a modele liczą się dłużej. Jeśli wybierasz ten wariant, napisz o tym wprost we wnioskach.
Uwaga o
PatientID: w tym zbiorze nie ma identyfikatora - wszystkie 13 kolumn to wyniki pomiarów. Nie znaczy to jednak, że temat znika. Nadal warto sprawdzić i zapisać, że każda użyta kolumna jest faktyczną cechą, a nie artefaktem procesu zbierania danych. Odruch „sprawdzam, czym są moje kolumny, zanim je wrzucę do modelu" jest ważniejszy niż konkretny zbiór.
Zasady gry¶
Wolno:
- korzystać z
numpy,pandas,matplotlib,scikit-learn- i tylko z nich, - wracać do ćwiczeń 01-08 i przepisywać stamtąd kod (to wręcz wskazane),
- czytać dokumentację scikit-learn,
- dodawać własne komórki, wykresy i analizy ponad wymagane minimum.
Nie wolno:
- używać
seaborn,plotly,graphvizaani innych bibliotek spoza listy (drzewa rysujemy wyłącznie przezsklearn.tree.plot_tree), - pobierać czegokolwiek z internetu - zbiór jest wbudowany,
- pominąć którejkolwiek z sekcji rusztowania,
- uznać za skończony notatnika, który nie wykonuje się od początku do końca po Kernel → Restart Kernel and Run All Cells.
Obowiązkowo w każdym kawałku kodu z elementem losowym: random_state=42.
Rusztowanie projektu¶
Poniżej znajduje się siedem etapów. Każdy ma opis tego, co masz zrobić, oraz pustą komórkę na kod i - gdzie trzeba - na komentarz.
Komentarze liczą się tak samo jak kod. Projekt bez wniosków jest projektem nieukończonym, choćby kod był bezbłędny - bo nikt, łącznie z Tobą za miesiąc, nie odtworzy z samego kodu, dlaczego podjąłeś takie, a nie inne decyzje.
Etap 1: Poznaj dane¶
Zanim zbudujesz cokolwiek, dowiedz się, z czym pracujesz. Minimum:
- Rozmiar zbioru, typy kolumn, braki danych (
isna().sum()). - Statystyki opisowe cech (
describe()) - ze szczególną uwagą na zakresy. Zwróć uwagę, czy cechy są w porównywalnych skalach. - Rozkład klas - czy zbiór jest zrównoważony (ang. balanced), czy nie.
- Co najmniej dwa wykresy: na przykład histogramy wybranych cech w rozbiciu na klasy oraz macierz korelacji między cechami (
X.corr()iax.imshow).
Na koniec napisz trzy do pięciu zdań o tym, czego udało się dowiedzieć. Nie „zbiór ma 13 kolumn" - to widać w kodzie. Raczej: które cechy wyglądają na przydatne, czy coś jest podejrzane, czy konieczne będzie skalowanie i dlaczego.
# TWÓJ KOD TUTAJ - analiza eksploracyjna
Wnioski z etapu 1:
(tutaj wpisz swoje obserwacje - kliknij dwukrotnie, żeby edytować)
Etap 2: Podział danych¶
Odłóż zbiór testowy (ang. test set) i nie dotykaj go aż do etapu 6.
- Podziel dane na uczące i testowe:
test_size=0.25,stratify=y,random_state=42. - Wypisz liczebności obu części oraz rozkład klas w każdej z nich.
- Napisz jedno zdanie: dlaczego
stratify=yprzy tak małym zbiorze nie jest opcjonalne.
To jest najważniejsza komórka w całym projekcie. Od tego momentu
X_testiy_testsą dla Ciebie zamknięte. Nie patrzysz na nie, nie liczysz na nich statystyk, nie dopasowujesz na nich skalera, nie wybierasz według nich hiperparametrów. Wszystko - absolutnie wszystko - robisz na zbiorze uczącym, korzystając z walidacji krzyżowej.
# TWÓJ KOD TUTAJ - podział na zbiór uczący i testowy
Etap 3: Przygotowanie danych i model odniesienia¶
- Zbuduj model odniesienia (ang. baseline) -
DummyClassifier(strategy="most_frequent"). Zmierz go walidacją krzyżową na zbiorze uczącym. To Twoja poprzeczka: model, który jej nie przeskoczy, nie ma prawa bytu. - Zdecyduj, jak przygotujesz dane. Przy tym zbiorze najważniejsze pytanie brzmi: czy skalować cechy? Odpowiedź nie jest jedna dla wszystkich modeli - patrz tabela niżej.
- Zbuduj przygotowanie jako
Pipeline, nie jako osobne wywołania.
| Rodzina modeli | Skalowanie | Dlaczego |
|---|---|---|
| regresja logistyczna, SVM, k najbliższych sąsiadów | konieczne | liczą odległości albo sumy waga × cecha w poprzek cech |
| drzewo, las losowy, boosting | zbędne | porównują wartość cechy z progiem wewnątrz tej samej cechy |
Dlaczego
Pipeline, a nie „przeskaluję sobie wcześniej"? Bo skaler uczy się z danych - zapamiętuje średnią i odchylenie standardowe. Jeśli dopasujesz go na całości przed podziałem, informacja ze zbioru testowego wycieknie do procesu uczenia.Pipelinezałatwia to automatycznie: w walidacji krzyżowej skaler jest dopasowywany osobno w każdej składce, wyłącznie na jej części uczącej. To nie jest szczegół stylistyczny - to różnica między oceną uczciwą a zawyżoną.
# TWÓJ KOD TUTAJ - model odniesienia i potoki przygotowania danych
Etap 4: Co najmniej trzy różne modele¶
Zbuduj i porównaj minimum trzy modele należące do różnych rodzin. Chodzi o różnorodność podejść, nie o trzy warianty tego samego pomysłu.
Przykładowy zestaw (nie musisz trzymać się dokładnie tego):
| Model | Rodzina | Skalowanie |
|---|---|---|
LogisticRegression |
liniowy | tak |
KNeighborsClassifier |
oparty na odległościach | tak |
DecisionTreeClassifier |
drzewo | nie |
RandomForestClassifier |
zespół drzew (ang. ensemble) | nie |
SVC |
margines / jądra | tak |
Wymagania:
- Każdy model oceniasz walidacją krzyżową na zbiorze uczącym (
cross_val_score,cv=5,StratifiedKFoldzshuffle=True, random_state=42). - Podajesz średnią i odchylenie standardowe wyników ze składek - nie samą średnią. Przy tak małym zbiorze rozrzut między składkami bywa duży i sam w sobie jest informacją.
- Zestawiasz wyniki w jednej tabeli (
pd.DataFrame) razem z modelem odniesienia.
Trzy modele to minimum, nie cel. Jeśli dorzucisz czwarty i piąty, a przy tym potrafisz powiedzieć, czym się od siebie różnią - tym lepiej.
# TWÓJ KOD TUTAJ - porównanie modeli walidacją krzyżową
Wnioski z etapu 4:
(który model prowadzi? czy różnice między modelami są większe niż rozrzut między składkami? co to oznacza?)
Etap 5: Dobór hiperparametrów¶
Wybierz co najmniej dwa modele z etapu 4 i dobierz im hiperparametry (ang. hyperparameters) - czyli ustawienia, których model nie uczy się z danych, tylko dostaje od Ciebie z góry.
- Użyj
GridSearchCValboRandomizedSearchCVz tą samą strategią walidacji co w etapie 4. - Przeszukiwanie prowadzisz wyłącznie na zbiorze uczącym.
- Wypisz najlepsze znalezione ustawienia (
best_params_) i odpowiadający im wynik walidacyjny (best_score_). - Napisz, co dany hiperparametr właściwie robi. „Najlepsze
C=10" nie jest wynikiem - wynikiem jest „mniejszeCoznacza silniejszą regularyzację, a przy tak małym zbiorze spodziewałem(-am) się, że pomoże; okazało się, że...".
Punkty startowe (rozszerz je według uznania):
| Model | Hiperparametr | Co kontroluje |
|---|---|---|
LogisticRegression |
C |
siłę regularyzacji - mniejsze C to mocniejsze karanie dużych współczynników |
KNeighborsClassifier |
n_neighbors, weights |
ilu sąsiadów głosuje i czy bliżsi ważą więcej |
DecisionTreeClassifier |
max_depth, min_samples_leaf |
jak bardzo drzewo może się rozrosnąć |
RandomForestClassifier |
n_estimators, max_features, max_depth |
liczbę drzew i ich zróżnicowanie |
SVC |
C, gamma, kernel |
kształt i sztywność granicy decyzyjnej |
Uwaga na
Pipeline: parametry modelu w potoku adresuje się z przedrostkiem, na przykład{'logisticregression__C': [0.01, 0.1, 1, 10]}przymake_pipelinealbo{'model__C': ...}, jeśli krok wPipelinenosi nazwęmodel. Sprawdźpotok.get_params().keys(), jeśli nie masz pewności, jak nazywa się Twój krok.
# TWÓJ KOD TUTAJ - dobór hiperparametrów
Wnioski z etapu 5:
(co dał dobór hiperparametrów? czy poprawa jest realna, czy mieści się w rozrzucie między składkami?)
Etap 6: Uczciwa ocena na zbiorze testowym¶
Dopiero teraz sięgasz po X_test i y_test. Raz.
- Wybierz jeden model - ten, który wypadł najlepiej w walidacji krzyżowej. Wybór ma być uzasadniony wynikami z etapów 4-5, a nie wynikiem testowym (którego jeszcze nie znasz).
- Naucz go na całym zbiorze uczącym (jeśli w grę wchodzi
GridSearchCV, obiektbest_estimator_jest już nauczony na całości - sprawdź w dokumentacji, co robirefit=True). - Zmierz na zbiorze testowym:
- skuteczność,
classification_report- precyzję, czułość i F1 dla każdej klasy osobno,- macierz pomyłek (
ConfusionMatrixDisplay).
- Porównaj wynik testowy z wynikiem walidacji krzyżowej z etapu 5. Skomentuj różnicę.
Dlaczego „raz"? Bo gdy zmierzysz wynik testowy, zobaczysz go, a potem wrócisz do modelu i coś poprawisz - zbiór testowy przestanie być zbiorem, którego model nie widział. Zacznie brać udział w wyborze modelu za Twoim pośrednictwem. To najsubtelniejsza odmiana przecieku danych (ang. data leakage): nie ma wycieku w kodzie, wyciek przechodzi przez Twoją głowę. Efekt jest ten sam - zawyżony, nieuczciwy wynik.
# TWÓJ KOD TUTAJ - ocena końcowa na odłożonym zbiorze testowym
Wnioski z etapu 6:
(jaki wynik osiągnął model? które klasy myli ze sobą? czy wynik testowy jest zbliżony do walidacyjnego, wyższy czy niższy - i co z tego wynika?)
Etap 7: Wnioski i uzasadnienie wyboru¶
To jest część, którą przeczytałby zleceniodawca - i jedyna, która zostaje, gdy zamkniesz notatnik. Napisz kilkanaście zdań (nie kod) odpowiadające na poniższe pytania:
- Który model został wybrany i dlaczego? Odwołaj się do liczb z etapów 4-5, nie do ogólnych opinii o algorytmach.
- Czy model jest użyteczny? Porównaj z modelem odniesienia. O ile jest lepszy i czy ta różnica jest warta zachodu.
- Jakie błędy popełnia? Które klasy myli i czy te pomyłki mają jakieś wyjaśnienie.
- Jak bardzo ufasz temu wynikowi? Zbiór testowy liczy kilkadziesiąt próbek - ile z nich to jeden punkt procentowy? Co to mówi o precyzji Twojego pomiaru?
- Co zrobiłbyś(-abyś) dalej, mając jeszcze tydzień? Wymień dwie, trzy konkretne rzeczy.
- Czego ten wynik nie mówi? Jedno ograniczenie, którego z samych liczb nie widać.
Punkt 4 jest w tym projekcie ważniejszy niż gdzie indziej i nie da się go obejść. Przy
test_size=0.25zbiór testowy liczy 45 butelek, więc jedna pomyłka to ponad dwa punkty procentowe. Różnica „model A ma 97,8%, model B ma 95,6%" oznacza jedną butelkę. Student, który na tej podstawie ogłasza zwycięzcę, nie zrozumiał, czym jest niepewność pomiaru - i to jest jedna z najważniejszych rzeczy, jakie ten projekt ma sprawdzić.
Wnioski końcowe:
(tutaj wpisz swoje podsumowanie - kliknij dwukrotnie, żeby edytować)
- Wybrany model i uzasadnienie:
- Użyteczność względem modelu odniesienia:
- Rodzaje popełnianych błędów:
- Zaufanie do wyniku i niepewność pomiaru:
- Co dalej:
- Czego wynik nie mówi:
Co powinien zawierać dobry projekt¶
Poniższa tabela to lista samokontrolna. Kolumna „minimum" opisuje to, bez czego projekt nie odpowiada na postawione pytanie. Kolumna „poziom, do którego warto dążyć" pokazuje, czym różni się praca porządna od pracy dobrej.
Przejdź przez nią, gdy uznasz projekt za skończony. Jeśli któryś wiersz budzi wątpliwość - wróć do tego etapu.
| Obszar | Minimum | Poziom, do którego warto dążyć |
|---|---|---|
| 1. Analiza danych | Rozmiar zbioru, braki danych, statystyki opisowe, rozkład klas, dwa wykresy, kilka zdań wniosków | Świadoma analiza korelacji między cechami i wnioski z niej dla wyboru modelu; wykresy z opisanymi osiami, tytułem i komentarzem, co z nich wynika |
| 2. Podział i przygotowanie danych | Poprawny podział ze stratyfikacją i random_state=42; skalowanie zastosowane tam, gdzie jest potrzebne; zbiór testowy nietknięty do etapu 6 |
Całe przygotowanie zamknięte w Pipeline; wyjaśnione, dlaczego części modeli skalowanie jest zbędne |
| 3. Modele | Co najmniej trzy modele z różnych rodzin, ocenione walidacją krzyżową, zestawione w tabeli razem z modelem odniesienia | Więcej modeli albo świadomie dobrany zestaw; podane odchylenie standardowe ze składek i użyte w interpretacji |
| 4. Dobór hiperparametrów | GridSearchCV (lub odpowiednik) dla co najmniej dwóch modeli, wyłącznie na zbiorze uczącym; wypisane best_params_ |
Wyjaśnione, co robi każdy strojony hiperparametr i dlaczego dobrany zakres ma sens; sprawdzone, czy poprawa mieści się w rozrzucie między składkami |
| 5. Ocena końcowa | Jednokrotny pomiar na zbiorze testowym: skuteczność, classification_report, macierz pomyłek |
Analiza macierzy pomyłek klasa po klasie z próbą wyjaśnienia pomyłek; porównanie wyniku testowego z walidacyjnym i komentarz do różnicy |
| 6. Wnioski | Odpowiedzi na wszystkie sześć pytań z etapu 7, oparte na liczbach z projektu | Wnioski, które ktoś nieznający kodu zrozumie bez pytań dodatkowych; uczciwie nazwane ograniczenia; sensowny plan dalszych kroków |
Czego na tej liście świadomie nie ma: wysokości wyniku liczbowego. Projekt z uczciwie zmierzoną skutecznością 92% jest wart więcej niż projekt z 99% uzyskanym przez podglądanie zbioru testowego. W pracy zawodowej jest dokładnie tak samo - z tą różnicą, że tam nikt nie zagląda do Twojego notatnika, a błąd wychodzi dopiero na produkcji.
Cztery błędy, które unieważniają wynik¶
Przejdź przez tę listę, zanim uznasz projekt za skończony. Każdy z tych czterech błędów sprawia, że liczba, którą podajesz na końcu, jest nieprawdziwa - i żadna jakość reszty pracy tego nie naprawia.
To nie jest lista zakazów wymyślona na potrzeby ćwiczenia. Każdy z tych błędów zdarza się w prawdziwych projektach i każdy kończy się tak samo: model, który świetnie wypadł w notatniku, zawodzi na pierwszych prawdziwych danych.
1. Ocena na zbiorze uczącym¶
Objaw: w projekcie pojawia się model.score(X_ucz, y_ucz) podane jako wynik modelu.
Dlaczego to błąd: model widział te dane podczas uczenia. Mierzysz, jak dobrze je zapamiętał, a nie jak dobrze radzi sobie z nowymi butelkami. Drzewo bez ograniczeń osiągnie tu 100% i nie będzie to znaczyło nic (ćwiczenie 01, zadanie 3).
Jak sprawdzić: przeszukaj notatnik pod kątem score(X_ucz i score(X_train. Wynik na zbiorze uczącym wolno pokazać wyłącznie jako ilustrację przeuczenia, wyraźnie jako taki opisaną.
2. Dobór hiperparametrów na zbiorze testowym¶
Objaw: pętla po wartościach hiperparametru, w której za każdym razem liczony jest wynik na X_test, a potem wybór najlepszego.
Dlaczego to błąd: zbiór testowy przestaje być bezstronny, bo brał udział w wyborze modelu. Raportowany wynik jest zawyżony i nie przewiduje zachowania na prawdziwie nowych danych. To ten sam błąd, który celowo popełniliśmy w ćwiczeniu 01 (zadanie 4) i naprawiliśmy w ćwiczeniu 06.
Jak zrobić poprawnie: hiperparametry dobiera się walidacją krzyżową na zbiorze uczącym. Zbiór testowy dotykasz raz, na samym końcu, jednym pomiarem.
Odmiana subtelna, równie groźna: wynik testowy zostaje zmierzony, nie podoba się, więc wracasz i poprawiasz model. Wtedy zbiór testowy uczestniczy w doborze modelu przez Ciebie - i przestaje być testowy, nawet jeśli w kodzie nie widać niczego złego.
3. Skalowanie (albo cokolwiek innego) przed podziałem danych¶
Objaw: StandardScaler().fit_transform(X) przed train_test_split.
Dlaczego to błąd: skaler wylicza średnią i odchylenie standardowe. Jeśli liczy je na całym zbiorze, do przekształcenia danych uczących trafia informacja ze zbioru testowego. To przeciek danych (ang. data leakage) - subtelny, bo nic się nie wysypie, a wynik wyjdzie odrobinę lepszy niż prawdziwy.
Jak zrobić poprawnie: najpierw podział, potem Pipeline(StandardScaler(), model). Wewnątrz walidacji krzyżowej skaler jest dopasowywany osobno w każdej składce - Pipeline pilnuje tego za Ciebie i to jest jego główny powód istnienia.
Dotyczy nie tylko skalowania: tak samo jest z uzupełnianiem braków danych, selekcją cech, PCA i każdym innym krokiem, który uczy się czegoś z danych.
4. Identyfikator jako cecha¶
Objaw: w X znajduje się kolumna będąca numerem porządkowym, identyfikatorem, datą rejestracji albo indeksem wiersza.
Dlaczego to błąd: identyfikator jest unikalny, więc model może zapamiętać po nim każdą próbkę z osobna. Na danych uczących wygląda to znakomicie, na nowych - katastrofalnie, bo ich identyfikatorów model nigdy nie widział.
W tym konkretnym zbiorze kolumny identyfikatora nie ma - wszystkie 13 cech to wyniki pomiarów chemicznych. Sprawdzenie i tak należy wykonać i opisać. Odruch „patrzę, czym są moje kolumny, zanim je wrzucę do modelu" jest tym, co sprawdzamy; brak identyfikatora w tym zbiorze to szczęśliwy zbieg okoliczności, a nie reguła.
Szerzej: usunąć trzeba wszystko, co nie będzie dostępne w momencie predykcji albo co niesie informację o odpowiedzi pochodzącą z przyszłości. W danych medycznych to na przykład kolumna „zalecone leczenie" - wypełniana po postawieniu diagnozy.
Lista kontrolna na koniec¶
Odhacz wszystko, zanim uznasz projekt za skończony:
- Kernel → Restart Kernel and Run All Cells wykonuje się bez błędu od początku do końca
- Wszystkie komórki
# TWÓJ KOD TUTAJsą wypełnione - Wszystkie komórki z komentarzem są wypełnione (żadnego pozostawionego (tutaj wpisz...))
random_state=42wszędzie, gdzie występuje losowość- Zbiór testowy użyty dokładnie raz, w etapie 6
- Żaden wynik na zbiorze uczącym nie jest podany jako wynik modelu
- Skalowanie odbywa się wewnątrz
Pipeline, nie przed podziałem - Każdy wykres ma tytuł i opisane osie
- Wnioski odwołują się do konkretnych liczb z projektu
- Żadnych bibliotek spoza
numpy,pandas,matplotlib,scikit-learn
Pytania do przemyślenia¶
Na te pytania odpowiadasz słowami, nie kodem. Warto wrócić do nich po skończeniu projektu.
- Twój model osiągnął pewien wynik na zbiorze testowym. Gdyby powtórzyć cały projekt z
random_state=7zamiast42, jak bardzo zmieniłby się ten wynik? Od czego to zależy? - Walidacja krzyżowa dała jeden ranking modeli, zbiór testowy potwierdził go albo nie. Jeśli nie - który z pomiarów jest bliższy prawdy i dlaczego?
- Dlaczego nie wolno wybrać modelu na podstawie wyniku testowego, skoro to właśnie ten wynik najbardziej nas interesuje?
- Zbiór wine ma 178 próbek. Które z wniosków Twojego projektu byłyby inne, gdyby miał 178 000 próbek? A które zostałyby takie same?
- Model odniesienia w tym zadaniu ma niższą poprzeczkę niż w zbiorze diabetes (trzy klasy zamiast dwóch). Czy to znaczy, że zadanie jest łatwiejsze, czy trudniejsze?
- Twój najlepszy model osiąga wynik bliski ideałowi. Czy to powód do radości, czy do podejrzliwości? Co sprawdzić, zanim ogłosisz sukces?
- Zleceniodawca pyta: „czy mogę na tym polegać przy nowych butelkach z tego regionu?". Co dokładnie mu odpowiesz i czego nie możesz obiecać?
Chcesz wiedzieć więcej¶
- Opis zbioru wine w dokumentacji scikit-learn - pochodzenie danych i znaczenie cech.
GridSearchCVi strojenie hiperparametrów - zwróć uwagę na sekcję o zagnieżdżonej walidacji krzyżowej (ang. nested cross-validation); to poprawne rozwiązanie problemu, który w tym projekcie obchodzimy odłożonym zbiorem testowym.- Metryki klasyfikacji wieloklasowej - czym różni się uśrednianie
macroodweightedi kiedy które ma sens. - Typowe pułapki i zalecane praktyki - oficjalna lista błędów scikit-learn, w tym przeciek danych i niewłaściwe użycie
random_state. Warto przeczytać w całości. PipelineiColumnTransformer- powrót do ćwiczenia 03, ale teraz już wiesz, po co to jest.
W kolejnych ćwiczeniach (10 - Od notatnika do skryptu i 11 - Jakość kodu w ML) zajmiemy się tym, co zrobić z modelem po projekcie: jak wyjąć go z notatnika, zapisać na dysk, uruchamiać z wiersza poleceń i przetestować. Jeśli podczas tego projektu choć raz zginął wynik przez uruchomienie komórek w złej kolejności - właśnie widać, po co te dwa ćwiczenia istnieją.