Transformacja funkcji do uczenia maszynowego, przewodnik dla początkujących

Kiedy zaczynałem uczyć się, jak optymalizować modele uczenia maszynowego, po przejściu do etapu budowy modelu często znajdowałem, że musiałbym wracać, aby ponownie odwiedzić dane, aby lepiej obsługiwać typy funkcji obecnych w zestawie danych. Z czasem odkryłem, że jednym z pierwszych kroków, które należy podjąć przed zbudowaniem modeli, jest uważne przejrzenie typów zmiennych obecnych w danych i próba ustalenia z góry najlepszego procesu transformacji, jaki należy podjąć, aby osiągnąć optymalną wydajność modelu.

W następnym poście opiszę proces, który podejmuję w celu identyfikacji i transformacji czterech typowych zmiennych. Będę korzystać z zestawu danych zaczerpniętego z konkursu rozgrzewającego „uczenie maszynowe z sercem”, który odbył się na stronie https://www.drivendata.org/. Pełny zestaw danych można pobrać tutaj https://www.drivendata.org/competitions/54/machine-learning-with-a-heart/data/. DrivenData organizuje regularne wyzwania online oparte na rozwiązywaniu problemów społecznych. Niedawno zacząłem brać udział w niektórych z tych zawodów, starając się wykorzystać niektóre moje umiejętności w słusznej sprawie, a także w celu zdobycia doświadczenia z zestawami danych i problemami, których zwykle nie spotykam w codziennej pracy.

Identyfikacja typów zmiennych

W statystyce zmienne numeryczne można scharakteryzować na cztery główne typy. Rozpoczynając projekt uczenia maszynowego, ważne jest określenie rodzaju danych zawartych w każdej z twoich funkcji, ponieważ może to mieć znaczący wpływ na działanie modeli. Próbowałem podać prosty opis czterech poniższych typów.

  • Zmienne ciągłe to zmienne, które mogą mieć nieskończoną liczbę możliwych wartości, w przeciwieństwie do zmiennych dyskretnych, które mogą mieć tylko określony zakres wartości. Przykładem zmiennej ciągłej może być liczba mil przejechanych przez samochód w ciągu jego życia.
  • Zmienne nominalne są wartościami kategorialnymi, które mają 2 lub więcej możliwych wartości, ale w których kolejność tych wartości nie ma znaczenia. Na przykład możemy użyć reprezentacji numerycznej do interpretacji typów samochodów, mówiąc, że kompakt ma wartość 1, MPV ma wartość 2, a kabriolet ma wartość 3. Jednak fakt, że kompaktowy samochód ma wartość 1 i kabriolet ma wartość 2, co nie oznacza, że ​​matematycznie grupa kabrioletów jest w jakiś sposób większa niż MPV. Jest to po prostu numeryczna reprezentacja kategorii.
  • Zmienne dychotomiczne są ponownie kategoryczne, ale mają tylko 2 możliwe wartości, zwykle 0 i 1. Na przykład możemy sklasyfikować posiadanie samochodu jako 1 (co oznacza tak) lub 0 (co oznacza nie). Kiedy przekształcamy zmienne w fikcyjne kolumny (co zrobimy później w tym poście), nowe produkowane funkcje również stają się dychotomiczne.
  • Zmienne porządkowe są podobne do nominalnych, ponieważ mają 2 lub więcej możliwych wartości, podstawowa różnica polega na tym, że wartości te mają znaczący porządek lub rangę. W naszym przykładzie samochodu może to być coś w rodzaju wielkości silnika, w której kategorie te można uporządkować pod względem mocy, 1,2, 1,6, 1,8.

Przygotowanie danych

Wykorzystam nasze uczenie maszynowe z zestawem danych serca, aby przejść przez proces identyfikowania i przekształcania typów zmiennych. Pobrałem i odczytałem pliki csv do Notatnika Jupyter. Następnie uruchamiam następującą funkcję, aby uzyskać migawkę składu danych.

importuj pandy jako pd
def szybka analiza (df):
 drukuj („Typy danych:”)
 drukuj (df.dtypes)
 print („Wiersze i kolumny:”)
 drukuj (kształt pliku)
 print („Nazwy kolumn:”)
 drukuj (df. kolumny)
 print („Wartości zerowe:”)
 print (df.apply (lambda x: sum (x.isnull ()) / len (df)))
szybka analiza (pociąg)

Daje to następujący wynik.

To mówi mi, że mam mały zestaw danych zawierający tylko 180 wierszy i że jest 15 kolumn. Jedna z funkcji jest nienumeryczna i dlatego należy ją przekształcić przed zastosowaniem większości bibliotek uczenia maszynowego. Nie ma żadnych wartości zerowych, więc nie muszę się o nie martwić. Przed przetworzeniem zestawu danych upuszczam na razie kolumnę „identyfikator_ pacjenta”, ponieważ nie jest to numeryczna i nie będzie używana na żadnym etapie szkolenia ani prognozowania.

Następnie uruchamiam funkcję opisującą pandy, aby uzyskać szybkie statystyki opisowe.

train.describe ()

Aby kategoryzować typy zmiennych w zbiorze danych, uruchamiam następujący kod, który tworzy histogramy wszystkich cech numerycznych. Na podstawie uzyskanego wyniku można łatwo zobaczyć, które funkcje są ciągłe i dychotomiczne. Funkcje ciągłe wyświetlają ciągły wzorzec dystrybucji, podczas gdy cechy dychotomiczne mają tylko dwa paski. Zmienne nominalne i porządkowe mogą czasem być trudniejsze do ustalenia i mogą wymagać dodatkowej wiedzy na temat zestawu danych lub pewnej wiedzy w dziedzinie. W przypadku takich konkursów uczenia maszynowego proponuję odnieść się do dowolnego słownika danych, który może zostać dostarczony, jeśli go nie ma (jak w tym przypadku), może być potrzebna kombinacja intuicji oraz próby i błędu.

zaimportuj matplotlib.pyplot jako plt
train [train.dtypes [(train.dtypes == "float64") | (train.dtypes == "int64")]
                        .index.values] .hist (figsize = [11,11])

Cechy scharakteryzowałem na cztery typy w poniższej tabeli. Mogę teraz podjąć decyzje dotyczące kroków transformacji, które podejmę w celu przygotowania danych do szkolenia i prognozowania.

Zmienne manekina

Jak wspomniano wcześniej w tym poście, wszelkie wartości nienumeryczne należy przekonwertować na liczby całkowite lub zmiennoprzecinkowe, aby można je było wykorzystać w większości bibliotek uczenia maszynowego. W przypadku zmiennych o niskiej liczności najlepszym rozwiązaniem jest zazwyczaj przekształcenie funkcji w jedną kolumnę na unikalną wartość, przy czym 0 oznacza, że ​​wartość nie jest obecna, i 1, gdzie ona jest. Są to tak zwane zmienne obojętne.

Ta technika jest zwykle najlepiej stosowana do dowolnych zmiennych nominalnych. Ponieważ nie mają one wewnętrznej kolejności, jeśli nie zastosujemy tego w pierwszej kolejności, algorytm uczenia maszynowego może niepoprawnie szukać relacji w kolejności tych wartości.

Panda ma fajną funkcję do tego o nazwie get_dummies (). W poniższym kodzie użyłem tego do konwersji wszystkich funkcji nominalnych i nienumerycznych na nowe kolumny. Z danych wyjściowych widać, że utworzono kilka nowych kolumn, a oryginalne kolumny zostały usunięte.

dummy_cols = ['thal', 'chest_pain_type', 'num_major_vessels',
              „workout_induced_angina”, „fasting_blood_sugar_gt_120_mg_per_dl”,
              „resting_ekg_results”, „slope_of_peak_exercise_st_segment”]
pociąg = pd.get_dummies (pociąg, kolumny = manekiny)

Skalowanie funkcji

Ciągłe zmienne w naszym zestawie danych mają różną skalę. Na przykład, jeśli odwołujesz się do histogramów powyżej, zobaczysz, że zmienna „oldpeak_eq_st_depression” wynosi od 0 do 6, podczas gdy „max_heart_rate_achieved” wynosi od 100 do 200. Stanowi to problem dla wielu popularnych algorytmów uczenia maszynowego, które często używają odległości euklidesowej między punktami danych, aby dokonać ostatecznych prognoz. Standaryzacja skali dla wszystkich zmiennych ciągłych często może skutkować wzrostem wydajności modeli uczenia maszynowego.

Istnieje wiele metod przeprowadzania skalowania funkcji w pythonie. Moją preferowaną metodą jest użycie funkcji Sci-Kit Learn MinMaxScaler. Który przekształca skalę, tak że wszystkie wartości funkcji mieszczą się w zakresie od 0 do 1. Poniżej zamieszczam kod, który to robi.

z wstępnego przetwarzania importu sklearn
n_test = train [['serum_cholesterol_mg_per_dl', 'max_heart_rate_achieved',
                „oldpeak_eq_st_depression”, „resting_blood_pressure”]]
cols_to_norm = ['serum_cholesterol_mg_per_dl', 'max_heart_rate_achieved',
                „oldpeak_eq_st_depression”, „resting_blood_pressure”]
x = n_test.values
min_max_scaler = przetwarzanie wstępne. MinMaxScaler ()
x_scaled = min_max_scaler.fit_transform (x)
n_test = pd.DataFrame (x_scaled, columns = cols_to_norm)
l_test = train.drop (['serum_cholesterol_mg_per_dl', 'max_heart_rate_achieved',
                „oldpeak_eq_st_depression”, „resting_blood_pressure”], oś = 1)
train = pd.concat ([n_test, l_test], axis = 1)
train.columns

Binning

Z powyższego kodu zauważysz, że nie uwzględniłem zmiennej ciągłej „wiek” w transformacji skalowania funkcji. Powodem tego jest fakt, że wiek jest przykładem typu cechy, który mógłby skorzystać z przekształcenia w zmienną dyskretną. W tym przykładzie możemy użyć segmentowania lub grupowania, aby przekształcić obiekt w listę znaczących kategorii.

W poniższym kodzie określiłem intuicyjne kategorie w oparciu o rozkład w danych. Wykorzystuje to funkcję cięcia pand, która pobiera listę pojemników, nazwy grup i ramkę danych. Ta funkcja zwraca oryginalną ramkę danych z nową funkcją „age_categories”. Kolumnę tę można następnie przekształcić w kilka fikcyjnych kolumn przy użyciu poprzednio opisanej metody.

pojemniki = [30, 40, 50, 60, 70, 80]
group_names = [„30–39”, „40–49”, „50–59”, „60–69”, „70–79”]
age_categories = pd.cut (train ['age'], bins, labels = nazwa_grupy)
pociąg ['wiek_kategorie'] = pd.cut (pociąg ['wiek'], pojemniki, etykiety = nazwa_grupy)
kategorie wiekowe
pd.value_counts (pociąg ['age_categories'])

Teraz mamy zestaw danych, w którym wszystkie kolumny są nienumeryczne. Stworzyliśmy kilka nowych funkcji i przekształciliśmy istniejące funkcje w formaty, które powinny pomóc poprawić wydajność wszystkich modeli uczenia maszynowego, z których możemy teraz korzystać. Transformacja funkcji jest ważnym pierwszym krokiem w procesie uczenia maszynowego, co często może mieć znaczący wpływ na wydajność modelu. Przedstawiłem tutaj pierwsze kroki, które podjąłem w procesie logicznego zastanowienia się, jak traktować różne zmienne, które mam. W fazie budowy modelu prawie zawsze będę wracał i poprawiał dane przy użyciu różnych metod, aby zwiększyć dokładność modeli. Uważam jednak, że wykonanie tych kroków na początku często skraca czas powrotu do etapów transformacji.