Gini, entropia i zysk informacyjny

Drzewa decyzyjne to jedna z najbardziej intuicyjnych i wszechstronnych technik analizy danych, stosowanych zarówno w statystyce, jak i uczeniu maszynowym. Niezwykła w swojej prostocie metoda potrafi dostarczyć potężnych wyników. W tym wpisie zajmiemy się metrykami, dzięki którym możemy dokonać najlepszego podziału. Najpierw trochę teorii…

Teoria

Współczynnik Giniego

Stosowana w statystyce miara koncentracji (nierównomierności) rozkładu zmiennej losowej. Wzór na współczynnik Giniego jest następujący:

G = 1 – \sum_{i=1}^{n} p_i^2

Gdzie:
* G: współczynnik Giniego,
* p_{i}: Prawdopodobieństwo wystąpienia i-tej klasy.
* n_{n}: Liczba klas.

Jeśli współczynnik Giniego wynosi „0”, oznacza to idealną równość (każda klasa jest równo reprezentowana). Wartość „1” oznacza całkowitą nierówność (tylko jedna klasa jest reprezentowana).

Entropia

Jest miarą stopnia nieuporządkowania układu.

H = -\sum_{i=1}^{n} p_i \log_2(p_i)

Gdzie:
* H: entropia,
* p_{i}: Prawdopodobieństwo wystąpienia i-tej klasy.
* n_{n}: Liczba klas.

Entropia jest najwyższa, gdy wszystkie klasy są równo reprezentowane (50:50), i najniższa, gdy tylko jedna klasa jest reprezentowana.

Zysk informacyjny

Zysk informacyjny to miara, która określa, jak dobrze dana cecha dzieli zbiór uczący na klasy. Jest to różnica między entropią przed podziałem a entropią po podziale, ważoną według liczby instancji w każdym podzbiorze. Zysk informacyjny można wyrazić wzorem:

IG(T, a) = H(T) – \sum_{v \in a} \frac{|T_v|}{|T|} H(T_v)

Gdzie:
* IG(T,a): Zysk informacyjny dla atrybutu a w zbiorze T.
* H(T): Entropia zbioru T przed podziałem.
* \sum_{v \in a}: Suma po wszystkich wartościach atrybutu a.
* |T_v|: Liczba elementów w podzbiorze T z wartością atrybutu v.
* |T|: Łączna liczba elementów w zbiorze T.
* H(T_v): Entropia podzbioru T z wartością atrybutu v po podziale.

Zysk informacyjny mierzy spadek entropii po podziale zbioru T według atrybutu a. Jeżeli zysk informacyjny jest wysoki, oznacza to, że atrybut aa dobrze rozdziela zbiór TT na klasy.

Przykład

Weźmy zbiór, składający się z 10 kulek. Na podstawie ich wielkości (predyktor – wpisany w kulkę), chcielibyśmy dokonać podziału, tak, żeby w zbiorze znalazły się kulki tego samego koloru (zmienna modelowana):

W którym miejscu najlepiej dokonać podziału? Policzymy to, najpierw pythonem, a później sprawdźmy jeszcze “ręcznie” dla najlepszego podziału.

Współczynnik Giniego

def gini_index(data, target_name='Color'):
    elements, counts = np.unique(data[target_name], return_counts=True)
    gini = 1 - np.sum((counts / np.sum(counts)) ** 2)
    return gini

def gini_gain(data, split_attribute_name, target_name='Color'):
    total_gini = gini_index(data)
    unique_values = sorted(np.unique(data[split_attribute_name]))
    gini_gains = {}
    for i in range(len(unique_values) - 1):
        val = (unique_values[i] + unique_values[i + 1]) / 2
        left_split = data[data[split_attribute_name] <= val]
        right_split = data[data[split_attribute_name] > val]
        left_gini = gini_index(left_split)
        right_gini = gini_index(right_split)
        left_weight = len(left_split) / len(data)
        right_weight = len(right_split) / len(data)
        split_gini = left_weight * left_gini + right_weight * right_gini
        gain = total_gini - split_gini
        gini_gains[val] = gain
    return gini_gains

gini_gains = gini_gain(data, 'Size')
print('Gini Gains for each split:\n')
for split_val, gain in gini_gains.items():
    print(f'Split at > {int(split_val)}: {gain:.4f}')
Gini Gains for each split:

Split at > 2: 0.0356
Split at > 3: 0.0050
Split at > 4: 0.0300
Split at > 5: 0.1633
Split at > 6: 0.0610
Split at > 7: 0.0050
Split at > 8: 0.0800

Przed podziałem:
G =1−(0.6)^2−(0.4)^2 = 1−0.36−0.16 = 0.48

Po podziale (pierwszy zbiór):
G_1 =1−(0.25)^2−(0.75)^2 = 1−0.0625−0.5625 = 0.375

Po podziale (drugi zbiór):
G_2 = 1−(0.83)^2−(0.17)2 = 1−0.6889−0.0289 = 0.2822

Zysk informacyjny:
IG(D, a) = Gini(D) – \sum_{v \in a} \frac{|D_v|}{|D|} Gini(D_v)
IG(D, a) = 0.48 – \left( \frac{4}{10} \cdot 0.375 + \frac{6}{10} \cdot 0.2778 \right) = 0.48 – (0.15 + 0.1667) = 0.1633


Entropia

def entropy(target_col):
    elements, counts = np.unique(target_col, return_counts=True)
    entropy = -np.sum([(counts[i] / np.sum(counts)) * np.log2(counts[i] / np.sum(counts)) for i in range(len(elements))])
    return entropy

def information_gain(data, split_attribute_name, target_name='Color'):
    total_entropy = entropy(data[target_name])
    unique_values = sorted(np.unique(data[split_attribute_name]))
    info_gains = {}
    for i in range(len(unique_values) - 1):
        val = (unique_values[i] + unique_values[i + 1]) / 2
        left_split = data[data[split_attribute_name] <= val]
        right_split = data[data[split_attribute_name] > val]
        left_entropy = entropy(left_split[target_name])
        right_entropy = entropy(right_split[target_name])
        left_weight = len(left_split) / len(data)
        right_weight = len(right_split) / len(data)
        split_entropy = left_weight * left_entropy + right_weight * right_entropy
        info_gain = total_entropy - split_entropy
        info_gains[val] = info_gain
    return info_gains

info_gains = information_gain(data, 'Size')
print('Information Gains for each split:\n')
for split_val, gain in info_gains.items():
    print(f'Split at > {int(split_val)}: {gain:.4f}')
Information Gains for each split:

Split at > 2: 0.0790
Split at > 3: 0.0074
Split at > 4: 0.0464
Split at > 5: 0.2564
Split at > 6: 0.0913
Split at > 7: 0.0074
Split at > 8: 0.1445

Przed podziałem:

p_{red} = 6/10

p_{blue} = 4/10

H = – 0.6 \log_2(0.6) – 0.4 \log_2(0.4) = 0.442 + 0.529 = 0.97

Po podziale (pierwszy zbiór):

p_{red} = 1/4

p_{blue} = 3/4

H = – 0.25 \log_2(0.25) – 0.75 \log_2(0.75) = 0.5 + 0.31 = 0.81

Po podziale (drugi zbiór):

p_{red} = 5/6

p_{blue} = 1/6

H = – 0.83 \log_2(0.83) – 0.17 \log_2(0.17) = 0.22 + 0.43 = 0.65

Zysk informacyjny:

IG(T, a) = H(T) – \sum_{v \in a} \frac{|T_v|}{|T|} H(T_v) IG(T, a) = 0.97 – [(4/10 * 0.81) + (6/10 * 0.65)] = 0.256

Zobacz także:

  • Piotr Szymański

    Kategoria:

    Hejka! Zapraszam na skrót z minionych dwóch tygodni, który przyswoić możecie przy ciepłej herbatce w te mroczne, szare dni. W opublikowanym przez Google 14 listopada ostrzeżeniu wskazano kilka najważniejszych rodzajów oszustw internetowych. Uwagę zwrócono między na niebezpieczne techniki ataków typu cloaking, które nabierają nowego wymiaru dzięki wykorzystaniu sztucznej inteligencji. Cloaking polega na ukrywaniu przed użytkownikiem […]
  • Piotr Szymański

    Kategoria:

    Hejka po dłuższej przerwie! Zaczynamy świeżym tematem. Raptem kilkanaście godzin temu do użytkowników trafiła, zapowiedziana 25 lipca, funkcja SearchGPT od OpenAI, umożliwiająca, w przeciwieństwie do tradycyjnych modeli językowych, na integrację z internetem w czasie rzeczywistym. SearchGPT ma dostęp do aktualnych informacji z sieci, co pozwala na udzielanie odpowiedzi opartych na najnowszych danych. Ponadto SearchGPT dostarcza […]
  • Piotr Szymański

    Kategoria:

    Hejson! Dzisiejsza konsumpcja mediów ma to do siebie, że odbywa się na 5-6 calowym ekranie telefonu. Ma też to do siebie, że zanim zdjęcie dotrze do Ciebie, to przejdzie przez 6 konwersacji na jedynym słusznym messengerze, zatem zostanie 6-cio krotnie skompresowane. W międzyczasie, jak będziecie mieli pecha, to jakiś wujek zrobi screena, zamiast zapisać zdjęcie […]
  • Piotr Szymański

    Kategoria:

    Hej! Robimy bardzo dużo zdjęć, a co za tym idzie – wiele z nich jest niechlujnych, z zabałagnionym tłem. Możemy jednak chcieć wykorzystać je do pochwalenia się naszym ryjkiem na jakimś publicznym profilu, gdyż np. naturalne, miękkie światło korzystnie eksponuje naszą facjatę. Podejścia mogą być dwa – albo zdecydujemy się na blur bądź zupełne usunięcie […]
  • Piotr Szymański

    Kategoria:

    Strzałeczka. Nvidia przejęła OctoAI, startup specjalizujący się w optymalizacji modeli uczenia maszynowego. To już piąta akwizycja Nvidii w 2024 roku, co czyni aktualnie nam panujący rok rekordowym pod względem liczby przejęć. OctoAI, założone w 2019 roku przez Luisa Ceze, skupiło się na tworzeniu oprogramowania zwiększającego wydajność modeli uczenia maszynowego na różnych platformach sprzętowych. Oprogramowanie OctoAI […]