Które kolumny są dla nas najważniejsze?

Dzięki R i Pythonowi nie jest problemem uruchomienie funkcji modelującej. Fakt, zdobycie danych i przerobienie ich na ramkę danych może być trudne i żmudne. Jednakże jest to często tylko problem techniczny. Uruchamiamy więc nasze funkcje modelujące i z niecierpliwością czekamy na wyniki. Często tak właśnie wygląda całość naszego procesu.

Wiemy, że im więcej danych mamy tym lepiej. Najłatwiej to zobaczyć zwiększając liczbę wierszy w ramce danych. O ile komputer, na którym będziemy dokonywać obliczeń, sobie z nimi poradzi. Co natomiast z kolumnami? Czy im więcej kolumn mamy tym lepiej?

Czym w ogóle jest kolumna w ramce danych? Wiersz to obserwacja – nasz punkt, który zmierzyliśmy. Jeśli np. prowadzimy sklep internetowy, to może to być np. klient albo transakcja, która została dokonana. Łatwo tutaj sobie wyobrazić sytuację, w której uzyskujemy więcej wierszy – po prostu czekamy, aż dane same się zbiorą. Jak natomiast zabrać się za kolumny?

Kolumna to przede wszystkim cecha, która opisuje jakąś właściwość obserwacji. Jeśli naszymi obserwacjami byłyby prostokątne akwaria, to takimi cechami byłyby: długość, szerokość i wysokość, czyli wymiary akwarium. W ramce danych mielibyśmy wiele obserwacji (akwariów), natomiast zawsze mielibyśmy trzy cechy dotyczące tych obserwacji (wymiary). Będą to właśnie nasze kolumny.

Oczywiście, zawsze możemy spróbować rozbudować nasz zbiór danych o dodatkowe kolumny. Aby tego dokonać, możemy użyć jednego z dwóch sposobów. Pierwszy to dodatkowa „wyliczona” kolumna, drugi to dodatkowy „pomiar”. Czasem, jeśli kontekst na to pozwala, możemy sobie wyliczyć różne dodatkowe przydatne kolumny. W przypadku akwariów jest to objętość – wystarczy przemnożyć przez siebie trzy wymiary i bach, mamy czwartą, sensowną kolumnę. Jeśli natomiast uświadomiliśmy sobie, że nie mierzymy jakiejś konkretnej przydatnej cechy, jak np. rodzaj szkła, zawsze możemy zacząć ją mierzyć i dokładać do nowych obserwacji. Pojawia się tutaj jednak jeden zasadniczy problem – być może nie będziemy mogli dokonać takiego pomiaru dla starych obserwacji. Jeśli np. nie mamy już jakiegoś akwarium w sprzedaży, być może nie będziemy mogli sprawdzić, z jakiego rodzaju szkła zostało zbudowane.

Czy liczba kolumn jest ważna?

No okej, skoro możemy dokładać sobie kolumny praktycznie dowolnie, to dlaczego w ogóle powinniśmy się przejmować ich ilością. Powodów jest zapewne wiele. W tej chwili przychodzą mi na myśl co najmniej cztery poważne:

  • koszt uzyskania
  • koszt przechowywania
  • koszt obliczeń
  • model

Koszt uzyskania danych

Prawie zawsze dane, na których pracujemy powstały w wyniku jakiejś celowej pracy. Fakt, źródła danych takie jak logi systemowe systemów operacyjnych, są dane nam za darmo. Trzeba byłoby wręcz wykonać pracę, żeby ich w ogóle nie tworzyć. Te dane są faktycznie „za darmo”. Jednakże wszystkie pozostałe wiążą się z kosztem. Może to być stworzenie kodu w aplikacji, który będzie logował fakt, może będzie to zakup urządzenia medycznego, a może będzie to stworzenie pytania w ankiecie. O ile więc idea posiadania jak największej liczby kolumn jest kusząca, często do rozważenia będą wchodzić konkretne koszty materialne.

Koszt przechowywania danych

Jak wiemy, dane w komputerze przechowywane są na dyskach twardych. Dyski twarde mają skończoną objętość danych i koszt. Każda dodatkowa kolumna wiąże się dodatkowym miejscem potrzebnym na dane. Jeśli jesteśmy daleko od wyczerpania tego zasobu, to nie musimy się nim przejmować. Może jednak nastąpić taki moment, że przechowywanie wszystkich kolumn będzie po prostu zbyt kosztowne.

Koszt obliczeń

Wiele algorytmów uczenia maszynowego (np. drzewo decyzyjne i las losowy) jest czułe na liczbę kolumn, jeśli chodzi o czas trenowania. Każda kolumna musi zostać uwzględniona i odpowiednio obrobiona. Nawet jeśli nie zawiera żadnej przydatnej informacji. Jeśli zależy nam więc na szybkości trenowania modelu, zbyt duża liczba kolumn może nam przeszkadzać.

Wytrenowany model

Wiele bibliotek uczenia maszynowego korzysta z obiektów, które po wytrenowaniu na konkretnym zbiorze danych, mogą być używane do dokonywania predykcji na innych danych. Obiekty takie przy predykcji często wymagają danych w dokładnie takim samym formacie jak przy treningu. Dołożenie bądź zabranie jednej kolumny danych po wytrenowaniu obiektu zablokuje nam możliwość dokonywania predykcji. Trzeba więc już na etapie projektowania systemu być świadomym, z jakich kolumn będziemy korzystać w przyszłości.

Ważność kolumn w Scikit-Learn

Postraszyłem trochę hasłem „liczba kolumn”, wypadałoby więc, żebym pokazał jak oswoić ten problem i zająć się nim w praktyce. Problem ten jest dualny. Możemy dokładać kolumny i je usuwać. Tematy te są dość rozbudowane. Ja natomiast chciałbym pokazać, jak łatwo można ocenić które kolumny w ogóle mają sens dla naszego modelu.


import pandas as pd
from sklearn.datasets import load_breast_cancer
from sklearn.ensemble import RandomForestClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split

breast_cancer = load_breast_cancer()
X = pd.DataFrame(breast_cancer["data"],
                 columns = breast_cancer["feature_names"])
y = pd.Series(breast_cancer["target"])

hiperparametry = {"criterion": 'gini',
                  "max_depth": 5,
                  "min_samples_leaf": 1,
                  "min_samples_split": 2,
                  "n_estimators": 100,
                  "bootstrap": True,
                  "max_features": None,
                  "random_state": 42}

estymator_drzewo = DecisionTreeClassifier(random_state = hiperparametry["random_state"],
                                   criterion = hiperparametry["criterion"],
                                   max_depth = hiperparametry["max_depth"],
                                   min_samples_leaf = hiperparametry["min_samples_leaf"],
                                   min_samples_split = hiperparametry["min_samples_split"])

estymator_las = RandomForestClassifier(random_state = hiperparametry["random_state"],
                                   criterion = hiperparametry["criterion"],
                                   max_depth = hiperparametry["max_depth"],
                                   min_samples_leaf = hiperparametry["min_samples_leaf"],
                                   min_samples_split = hiperparametry["min_samples_split"],
                                   n_estimators = hiperparametry["n_estimators"],
                                   bootstrap = hiperparametry["bootstrap"],
                                   max_features = hiperparametry["max_features"])

X_train, X_test, y_train, y_test = train_test_split(X, y,
                                                    test_size = 0.25,
                                                    random_state = 42)
estymator_drzewo.fit(X = X_train, y = y_train)
estymator_las.fit(X = X_train, y = y_train)

ważność = pd.concat([pd.DataFrame(dict(zip(X_train.columns, estymator_drzewo.feature_importances_)), index = ["Drzewo"]),
                     pd.DataFrame(dict(zip(X_train.columns, estymator_las.feature_importances_)), index = ["Las"])])

ważność_sorted = ważność.sort_values(["Drzewo"], axis=1, ascending = False)

ważność_sorted.T

Każdy model (obiekt) w Scikit-Learn po wytrenowaniu uzyskuje listę wartości, która odpowiada ważności danej cechy po zakończeniu modelowania. Jeśli chodzi o drzewo i las, są to wartości (od 0 do 1) mówiące o tym, jak bardzo dana cecha przyczyniła się do wpływu na podział według kryterium. Im większa jest ta wartość, tym cecha była bardziej przydatna i jest ważna.

Dla przykładu wytrenowałem dwa modele, wykorzystując drzewo decyzyjne i las losowy. W tym wypadku nie interesowały mnie wyniki uzyskiwane przez modele, ale właśnie wartości z feature_importances_. Ułożyłem je według najważniejszych dla drzewa decyzyjnego.

Drzewo Las
mean concave points 0.708984 0.324494
worst texture 0.117653 0.025146
worst radius 0.060099 0.052754
worst area 0.035168 0.083314
worst perimeter 0.029283 0.139757
concave points error 0.017345 0.001658
area error 0.013011 0.012721
worst smoothness 0.010041 0.007430
texture error 0.006833 0.002816
smoothness error 0.001584 0.004192
fractal dimension error 0.000000 0.003818
mean radius 0.000000 0.003299
worst compactness 0.000000 0.003006
worst concavity 0.000000 0.015028
worst concave points 0.000000 0.254552
worst symmetry 0.000000 0.006596
symmetry error 0.000000 0.002686
compactness error 0.000000 0.001641
concavity error 0.000000 0.005592
mean texture 0.000000 0.018146
perimeter error 0.000000 0.003561
radius error 0.000000 0.006439
mean fractal dimension 0.000000 0.002603
mean symmetry 0.000000 0.002769
mean concavity 0.000000 0.001177
mean compactness 0.000000 0.000498
mean smoothness 0.000000 0.002614
mean area 0.000000 0.006274
mean perimeter 0.000000 0.002509
worst fractal dimension 0.000000 0.002910

Widzimy, że w przypadku drzewa, zostało użyte tylko 10 cech. Żadna inna poza nimi nie jest brana pod uwagę przy podejmowaniu decyzji przez model. Są rozważane w czasie modelowania, ale algorytm ich nie wykorzystuje, bo nie wnoszą niczego przydatnego. Gdybyśmy na tym etapie zdecydowali się używać modelu drzewa decyzyjnego, to moglibyśmy spokojnie zrezygnować z cech, które w powyższej tabeli wynoszą 0, moglibyśmy je też usunąć z pamięci trwałej. Nieco inaczej sprawa ma się w przypadku modelu opartego o las losowy.

W lesie losowym każda cecha ma jakąś swoją ważność. Jeśli chcielibyśmy podjąć decyzję, ile kolumn bierzemy w tym przypadku, musielibyśmy wybrać jakąś granicę i odrzucić wszystkie cechy, które są poniżej niej.

Konkluzja

Im więcej wierszy w rance danych tym lepiej. No, chyba że są to duplikaty, albo błędne obserwacje. Im więcej kolumn w ramce danych tym gorzej. Nie, nie zawsze tak jest. 😉 Byłoby to za duże uogólnienie. Warto jednak mieć na uwadze czy faktycznie korzystamy z wszystkich kolumn i czy wnoszą one odpowiednio dużo do procesu rozwiązywania naszego problemu. Jednym ze sposobów, aby to ocenić, jest użycie atrybutu feature_importances_ i na jego podstawie wybrać te cechy, które są przydatne.

Kursy Online

Jeśli jesteś zainteresowany zakupem wideo kursów online które przygotowałem, sprawdź tę stronę – może akurat opublikowałem tam kupony zniżkowe. 🙂

2 myśli na temat “Które kolumny są dla nas najważniejsze?

  1. Cześć,
    całkiem ciekawe tematy poruszasz, ale czuję niedosyt. Bo tak jak w tym artykule – zaczynasz bardzo rozbudowanie, a kończysz tak nijako.

    Bo nie było by dla mnie większej różnicy jakbyś przeszedł do konkluzji. Fajnie by było jakbyś rozbudowywał całe artykuły – np. sprawdził jak bardzo różni się czas przy 4 a 10 kolumnach przy 100 tysiącach wierszy. A tak to zaczyna się dobrze i ciekawie, a później konkluzja, że w sumie to nie wiadomo…

    p.s. Tekst nie jest zawijany i się źle czyta.

    1. Cześć!
      Dzięki za uwagę. Aktualnie staram się opisać ogólnie różne tematy i zbadać, które z nich będą najciekawsze dla czytelników. Zdecydowanie przygotuję kontynuację w postaci analizy, która Cię ciekawi. Przedstawię konkretne porównania czasów, efektywności, objętość danych na jakimś dużym zbiorze danych.

      A odnośnie do zawijania tekstu, to chodzi Ci o kawałki kodu Python? Czy jakiś inny element się zepsuł?

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *