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.
- 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)
- 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))