Implementação e Análise do Algoritmo AdaBoost

O AdaBoost é um algoritmo de aprendizado de máquina que combina vários classificadores fracos para formar um classificador forte. O processo envolve a atribuição de pesos aos dados, onde os pesos dos dados mal classificados são aumentados e os dos bem classificados são diminuídos. Isso resulta em uma ênfase maior nos dados mais difíceis de classificar nas iterações subsequentes.

Observação: O AdaBoost é principalmente usado para problemas de classiifcação binária. Para problemas de classificação multiclasce, o AdaBoost pode ser menos eficiente em comparação com outros algoritmos como Random Forest e Árvores de Decisão.

1.1 Exemplo de Análise

Vamos analisar o AdaBoost comparando-o com Decision Tree e Random Forest usando o conjunto de dados de câncer de mama.

  1. Comparação entre Decision Tree, Random Forest e AdaBoost

2.1 Carregamento dos Dados

from sklearn.model_selection import train_test_split
from sklearn.datasets import load_breast_cancer

X, y = load_breast_cancer(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

2.2 Uso da Decision Tree

from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score

score = 0
for _ in range(100):
    model = DecisionTreeClassifier()
    model.fit(X_train, y_train)
    y_pred = model.predict(X_test)
    score += accuracy_score(y_test, y_pred) / 100
print("Acurácia média da Decision Tree:", score)

2.3 Uso da Random Forest

from sklearn.ensemble import RandomForestClassifier

score = 0
for _ in range(100):
    model = RandomForestClassifier()
    model.fit(X_train, y_train)
    y_pred = model.predict(X_test)
    score += accuracy_score(y_test, y_pred) / 100
print("Acurácia média da Random Forest:", score)

2.4 Uso do AdaBoost

from sklearn.ensemble import AdaBoostClassifier

score = 0
for _ in range(100):
    model = AdaBoostClassifier()
    model.fit(X_train, y_train)
    y_pred = model.predict(X_test)
    score += accuracy_score(y_test, y_pred) / 100
print("Acurácia média do AdaBoost:", score)
  1. Implementação Manual do Algoritmo AdaBoost

3.1 Cálculo de Três Rodadas

import numpy as np
from sklearn.ensemble import AdaBoostClassifier
from sklearn.tree import DecisionTreeClassifier
import graphviz

X = np.arange(10).reshape(-1, 1)
y = np.array([1, 1, 1, -1, -1, -1, 1, 1, 1, -1])

model = AdaBoostClassifier(n_estimators=3, algorithm='SAMME')
model.fit(X, y)
y_pred = model.predict(X)

# Visualização das árvores
dot_data = tree.export_graphviz(model.estimators_[0], filled=True, rounded=True)
graphviz.Source(dot_data)

dot_data = tree.export_graphviz(model.estimators_[1], filled=True, rounded=True)
graphviz.Source(dot_data)

dot_data = tree.export_graphviz(model.estimators_[2], filled=True, rounded=True)
graphviz.Source(dot_data)

3.1.1 Cálculo do Gini Index

w1 = np.full(10, 0.1)
cond = y == 1
p1 = w1[cond].sum()
p2 = 1 - p1
gini = p1 * (1 - p1) + p2 * (1 - p2)

3.1.2 Cálculo do Melhor Split

gini_result = []
best_split = {}
lower_gini = 1
for i in range(len(X) - 1):
    split = X[i:i+2].mean()
    cond = (X <= split).ravel()
    left = y[cond]
    right = y[~cond]

    gini_left = 0
    gini_right = 0
    for j in np.unique(y):
        p_left = (left == j).sum() / left.size
        gini_left += p_left * (1 - p_left)
        p_right = (right == j).sum() / right.size
        gini_right += p_right * (1 - p_right)

    left_p = cond.sum() / cond.size
    right_p = 1 - left_p
    gini = gini_left * left_p + gini_right * right_p
    gini_result.append(gini)
    if gini < lower_gini:
        lower_gini = gini
        best_split.clear()
        best_split['X[0]<='] = split
print(gini_result)
print(best_split)

3.1.3 Cálculo do Erro

y1_ = model.estimators_[0].predict(X)
error1 = (y != y1_).mean()

3.1.4 Cálculo do Peso do Classificador Fraco

alpha_1 = 0.5 * np.log((1 - error1) / error1)

3.1.5 Atualização dos Pesos das Amostras

w2 = w1 * np.exp(-y * y1_ * alpha_1)
w2 = w2 / w2.sum()

3.2 Segunda Rodada de Cálculos

cond = y == -1
np.round(w2[cond].sum(), 3)

cond = y == 1
np.round(w2[cond].sum(), 3)

cond = y == 1
p1 = w2[cond].sum()
p2 = 1 - p1
gini = p1 * (1 - p1) + p2 * (1 - p2)

gini_result = []
best_split = {}
lower_gini = 1
for i in range(len(X) - 1):
    split = X[i:i+2].mean()
    cond = (X <= split).ravel()
    left = y[cond]
    right = y[~cond]

    left_p = w2[cond] / w2[cond].sum()
    right_p = w2[~cond] / w2[~cond].sum()

    gini_left = 0
    gini_right = 0
    for j in np.unique(y):
        cond_left = left == j
        p_left = left_p[cond_left].sum()
        gini_left += p_left * (1 - p_left)

        cond_right = right == j
        p_right = right_p[cond_right].sum()
        gini_right += p_right * (1 - p_right)

    p1 = cond.sum() / cond.size
    p2 = 1 - p1
    gini = gini_left * p1 + gini_right * p2
    gini_result.append(gini)
    if gini < lower_gini:
        lower_gini = gini
        best_split.clear()
        best_split['X[0]<='] = split
print(gini_result)
print(best_split)

3.2.3 Cálculo do Erro

y2_ = model.estimators_[1].predict(X)
error2 = ((y != y2_) * w2).sum()

3.2.4 Cálculo do Peso do Segundo Classificador Fraco

alpha_2 = 0.5 * np.log((1 - error2) / error2)

3.2.5 Atualização dos Pesos das Amostras

w3 = w2 * np.exp(-y * y2_ * alpha_2)
w3 = w3 / w3.sum()

3.3 Terceira Rodada de Cálculos

cond = y == 1
p1 = w3[cond].sum()
p2 = 1 - p1
gini = p1 * (1 - p1) + p2 * (1 - p2)

gini_result = []
best_split = {}
lower_gini = 1
for i in range(len(X) - 1):
    split = X[i:i+2].mean()
    cond = (X <= split).ravel()
    left = y[cond]
    right = y[~cond]

    left_p = w3[cond] / w3[cond].sum()
    right_p = w3[~cond] / w3[~cond].sum()

    gini_left = 0
    gini_right = 0
    for j in np.unique(y):
        cond_left = left == j
        p_left = left_p[cond_left].sum()
        gini_left += p_left * (1 - p_left)

        cond_right = right == j
        p_right = right_p[cond_right].sum()
        gini_right += p_right * (1 - p_right)

    p1 = cond.sum() / cond.size
    p2 = 1 - p1
    gini = gini_left * p1 + gini_right * p2
    gini_result.append(gini)
    if gini < lower_gini:
        lower_gini = gini
        best_split.clear()
        best_split['X[0]<='] = split
print(gini_result)
print(best_split)

3.3.3 Cálculo do Erro

y3_ = model.estimators_[2].predict(X)
error3 = ((y != y3_) * w3).sum()

3.3.4 Cálculo do Peso do Terceiro Classificador Fraco

alpha_3 = 0.5 * np.log((1 - error3) / error3)

3.3.5 Atualização dos Pesos das Amostras

w4 = w3 * np.exp(-y * y3_ * alpha_3)
w4 = w4 / w4.sum()

3.4 Agregação dos Classificadores Fracos

print("Resultados dos classificadores fracos:")
display(y1_, y2_, y3_)
F = alpha_1 * y1_ + alpha_2 * y2_ + alpha_3 * y3_
print("Resultado agregado do classificador forte:\n", F)
print("Resultado final do classificador forte:\n", np.array([1 if i > 0 else -1 for i in F]))
print("Previsões do modelo:\n", model.predict(X))

Tags: AdaBoost DecisionTree RandomForest scikit-learn Python

Publicado em 8-27 02:06