Faza 02 · lecția 11
Metode de ansamblu
Scopul lecției: Un grup de modele slabe, combinat corect, devine un model puternic. Aceasta nu este o metaforă, ci un rezultat matematic în condiții precise.
Versiunea curentă AlexBred.com: primele 100 de lecții ale programului în limba română.
Cuprinsul lecției
- Obiective de învățare
- Problema
- Conceptul
- De ce funcționează ansamblurile
- Bagging (agregare bootstrap)
- Boosting (corectarea secvențială a erorilor)
- AdaBoost
- Gradient boosting
- XGBoost: de ce este puternic pe date tabelare
- Stacking (metaînvățare)
- Votarea
- Construiți
- Pasul 1: ciot de decizie (model de bază)
- Pasul 2: AdaBoost de la zero
- Pasul 3: gradient boosting de la zero
- Pasul 4: comparați cu scikit-learn
- Folosiți
- Când să folosiți fiecare metodă
- Un flux practic pentru date tabelare
- Livrați
- Exerciții
- Termeni-cheie
- Lecturi suplimentare
Un grup de modele slabe, combinat corect, devine un model puternic. Aceasta nu este o metaforă, ci un rezultat matematic în condiții precise.
Tip: Construire Limbaj: Python Cerințe preliminare: Faza 2, lecția 10 (Compromisul deplasare–varianță) Durată: ~120 de minute
Obiective de învățare
- Implementarea de la zero a AdaBoost și gradient boosting și explicarea modului în care boosting-ul secvențial poate reduce deplasarea
- Construirea unui ansamblu bagging și demonstrarea modului în care medierea modelelor slab corelate reduce varianța, de regulă fără o creștere mare a părtinirii
- Compararea bagging-ului, boosting-ului și stacking-ului din perspectiva componentelor erorii pe care le vizează în principal
- Evaluarea diversității ansamblului și explicarea condițiilor în care acuratețea votului majoritar crește odată cu numărul de modele slabe
Problema
Un singur arbore de decizie se antrenează rapid și este ușor de interpretat, dar poate supraînvăța. Un singur model liniar poate subînvăța frontiere complexe. Ați putea petrece zile întregi proiectând arhitectura perfectă. Sau ați putea combina mai multe modele imperfecte și obține ceva mai bun decât fiecare dintre ele luat separat.
Metodele de ansamblu fac exact acest lucru. Ele sunt instrumente foarte eficiente în competițiile pe date tabelare și în numeroase sisteme de producție și ilustrează practic compromisul deplasare–varianță. Bagging-ul urmărește în principal reducerea varianței. Boosting-ul poate reduce deplasarea prin corecții succesive. Stacking-ul învață cum să combine predicțiile mai multor familii de modele.
Notă tehnică a traducerii: aceste asocieri sunt intuiții utile, nu separări absolute. Bagging-ul poate modifica și deplasarea, boosting-ul poate afecta și varianța, iar stacking-ul nu garantează o îmbunătățire. Rezultatul depinde de modelele de bază, diversitate, regularizare și protocolul de validare.
Conceptul
De ce funcționează ansamblurile
Să presupunem că aveți N clasificatoare independente, fiecare cu acuratețea p > 0,5. Acuratețea votului majoritar este:
P(majoritatea este corectă) = suma pentru k > N/2 din C(N,k) * p^k * (1-p)^(N-k)
Pentru 21 de clasificatoare independente, fiecare cu o acuratețe de 60%, acuratețea votului majoritar este de aproximativ 82,56%. Pentru 101 clasificatoare, ea crește la aproximativ 97,91%. Erorile se compensează numai în măsura în care modelele nu fac aceleași greșeli.
Notă tehnică a traducerii: valorile de 74% și 84% din original nu corespund formulei binomiale afișate. Calculul exact pentru N impar folosește suma de la
floor(N/2)+1la N și produce aproximativ 0,825622 pentru N=21 și 0,979103 pentru N=101. Creșterea către 1 este concluzia modelului idealizat cu votanți independenți, identic distribuiți și p > 0,5; corelația erorilor poate reduce drastic avantajul.
Cerința esențială este diversitatea. Dacă toate modelele fac aceleași erori, combinarea lor nu ajută. Ansamblurile încearcă să producă modele diverse prin:
- submulțimi diferite de antrenare, în bagging;
- submulțimi diferite de caracteristici, în pădurile aleatoare;
- corectarea secvențială a erorilor, în boosting;
- familii diferite de modele, în stacking.
Bagging (agregare bootstrap)
Bagging-ul creează diversitate antrenând fiecare model pe alt eșantion bootstrap extras din datele de antrenare.
Un eșantion bootstrap este extras cu înlocuire din datele originale și are aceeași dimensiune ca acestea. În medie, aproximativ 63,2% dintre exemplele originale apar cel puțin o dată într-un asemenea eșantion. Cele aproximativ 36,8% rămase sunt exemple out-of-bag (OOB).
Pentru modele instabile, precum arborii necurățați, bagging-ul reduce adesea varianța. Fiecare arbore se ajustează la alt eșantion bootstrap, iar medierea poate atenua fluctuațiile care nu sunt comune arborilor.
Notă tehnică a traducerii: exemplele OOB nu formează un singur set de validare identic pentru toți arborii. O predicție OOB pentru un exemplu se agregă numai din arborii ale căror eșantioane bootstrap nu au inclus acel exemplu. Estimarea OOB este utilă, dar nu înlocuiește automat un set de testare independent și poate avea proprietăți diferite în funcție de problemă. Bagging-ul ajută în special modele instabile; pentru un model foarte stabil, câștigul poate fi mic.
Pădurile aleatoare sunt o formă de bagging cu un element suplimentar: la fiecare separare este luată în considerare numai o submulțime aleatoare de caracteristici. Aceasta forțează și mai multă diversitate între arbori. O alegere frecventă pentru clasificare este sqrt(n_features); pentru regresie, alegerea depinde de implementare și trebuie reglată în context.
Notă tehnică a traducerii: regula istorică
n_features / 3pentru regresie nu este valoarea implicită actuală înRandomForestRegressordin scikit-learn, undemax_features=1.0folosește toate caracteristicile candidate la fiecare separare. Reducereamax_featurespoate crește diversitatea, dar poate mări și deplasarea arborilor individuali.
Boosting (corectarea secvențială a erorilor)
Boosting-ul antrenează modelele secvențial. Fiecare model nou se concentrează asupra exemplelor sau direcțiilor de eroare pe care ansamblul curent nu le tratează bine.
Boosting-ul poate reduce deplasarea prin corectarea erorilor sistematice ale ansamblului curent. Predicția finală este o sumă ponderată a modelelor, iar ponderile depind de algoritm și de performanța fiecărui model de bază.
Compromisul este că boosting-ul poate deveni sensibil la zgomot și valori aberante, mai ales fără regularizare, adâncime controlată, rată de învățare și oprire timpurie adecvate.
Notă tehnică a traducerii: afirmația că prea multe runde produc în mod necesar supraînvățare este prea puternică. Comportamentul depinde de algoritm, funcția de pierdere, capacitatea modelelor de bază și zgomot; AdaBoost poate continua uneori să îmbunătățească marjele chiar după atingerea erorii zero pe antrenare. Numărul de runde trebuie ales prin validare.
AdaBoost
AdaBoost, adică Adaptive Boosting, a fost primul algoritm de boosting cu utilizare practică largă. Este folosit de obicei cu modele de bază care acceptă ponderi pe eșantioane, adesea cioturi de decizie — arbori de adâncime 1.
Algoritmul:
1. Inițializați ponderile eșantioanelor: w_i = 1/N pentru orice i
2. Pentru t = 1 până la T:
a. Antrenați modelul slab h_t pe datele ponderate
b. Calculați eroarea ponderată:
err_t = sum(w_i * I(h_t(x_i) != y_i)) / sum(w_i)
c. Calculați ponderea modelului:
alpha_t = 0.5 * ln((1 - err_t) / err_t)
d. Actualizați ponderile eșantioanelor:
w_i = w_i * exp(-alpha_t * y_i * h_t(x_i))
e. Normalizați ponderile astfel încât suma lor să fie 1
3. Predicția finală: H(x) = sign(sum(alpha_t * h_t(x)))
Modelele cu eroare mai mică primesc un alpha mai mare. Eșantioanele clasificate greșit primesc ponderi mai mari, astfel încât modelul următor să le acorde mai multă atenție.
Notă tehnică a traducerii: formula binară presupune etichete și predicții în {-1,+1} și un model slab cu eroare sub 0,5. Pentru eroare exact zero, algoritmul practic trebuie să oprească sau să limiteze numeric alpha; pentru eroare de cel puțin 0,5, modelul trebuie respins, inversat când este posibil ori procesul oprit, în funcție de implementare.
Gradient boosting
Gradient boosting generalizează ideea de boosting la funcții de pierdere diferențiabile. În loc să repondereze direct eșantioanele, ajustează fiecare model nou la pseudo-reziduurile — gradientul negativ al pierderii — ansamblului curent.
1. Inițializați: F_0(x) = argmin_c sum(L(y_i, c))
2. Pentru t = 1 până la T:
a. Calculați pseudo-reziduurile:
r_i = -dL(y_i, F_{t-1}(x_i)) / dF_{t-1}(x_i)
b. Ajustați un arbore h_t la reziduurile r_i
c. Găsiți mărimea optimă a pasului:
gamma_t = argmin_gamma sum(L(y_i, F_{t-1}(x_i) + gamma * h_t(x_i)))
d. Actualizați:
F_t(x) = F_{t-1}(x) + rata_de_învățare * gamma_t * h_t(x)
3. Predicția finală: F_T(x)
Pentru pierderea pătratică, pseudo-reziduurile sunt chiar reziduurile obișnuite: r_i = y_i - F_{t-1}(x_i). Fiecare arbore ajustează erorile ansamblului precedent.
Rata de învățare, numită și contracție, controlează contribuția fiecărui arbore. Ratele mai mici necesită de regulă mai mulți arbori și pot oferi o regularizare mai puternică. Valori inițiale frecvente se află între 0,01 și 0,3, dar alegerea trebuie validată împreună cu numărul și complexitatea arborilor.
Notă tehnică a traducerii: o rată de învățare mai mică nu garantează singură o generalizare mai bună. Ea interacționează cu numărul de iterații, adâncimea arborilor, eșantionarea și funcția de pierdere; o rată prea mică și prea puțini arbori pot conduce la subînvățare.
XGBoost: de ce este puternic pe date tabelare
XGBoost, adică eXtreme Gradient Boosting, combină gradient boosting cu regularizare și optimizări de sistem care îl fac rapid și precis în multe sarcini:
- Obiectiv regularizat: penalizările asupra ponderilor frunzelor limitează complexitatea arborilor individuali.
- Aproximare de ordinul al doilea: folosește atât derivatele de ordinul întâi, cât și pe cele de ordinul al doilea ale pierderii pentru evaluarea actualizărilor și separărilor.
- Separări conștiente de raritate: tratează valorile lipsă învățând direcția implicită pentru fiecare separare.
- Subeșantionarea coloanelor: selectează caracteristici pentru a regulariza și diversifica arborii.
- Schiță ponderată de cuantile: găsește eficient puncte candidate de separare pentru caracteristici continue în modurile aproximative și distribuite descrise de lucrare.
- Structură de blocuri atentă la cache: organizează accesul la memorie pentru eficiență pe CPU.
Pentru multe seturi de date tabelare de dimensiune medie, XGBoost, LightGBM și alte implementări de arbori amplificați reprezintă puncte de plecare foarte puternice. Comparați-le însă cu referințe adecvate și validați alegerea pe problema concretă.
Notă tehnică a traducerii: LightGBM nu este pur și simplu „succesorul” XGBoost, ci o implementare separată de gradient boosting bazat pe arbori, cu alte alegeri algoritmice și de sistem. Afirmația că modelele bazate pe arbori depășesc consecvent toate rețelele neuronale și că situația nu se va schimba este o generalizare nejustificată. Studiile comparative arată un avantaj frecvent pe anumite benchmark-uri tabelare, nu o dominație universală sau permanentă.
Stacking (metaînvățare)
Stacking-ul folosește predicțiile mai multor modele de bază drept caracteristici pentru un metamodel.
Metamodelul învață cum să combine ieșirile modelelor de bază. Dacă acestea au puncte forte complementare, predicțiile lor pot conține suficientă informație pentru ca metamodelul să le pondereze util.
Pentru a evita scurgerea de informație, metacaracteristicile de antrenare trebuie generate prin predicții out-of-fold: fiecare rând este prezis de un model de bază care nu a fost antrenat pe acel rând. După antrenarea metamodelului, modelele de bază sunt de regulă reajustate pe întregul set de antrenare pentru predicțiile finale.
Notă tehnică a traducerii: dacă metamodelul primește numai predicțiile de bază, el nu „rutează” explicit fiecare regiune a spațiului de intrare decât în măsura în care acea informație este codificată în predicții. Pentru o dependență directă de intrare, unele implementări transmit și caracteristicile originale. Orice preprocesare și reglare a modelelor de bază trebuie să rămână în interiorul fold-urilor pentru a evita scurgerea.
Votarea
Este cel mai simplu ansamblu: combinați direct predicțiile.
- Votare dură: vot majoritar asupra etichetelor de clasă.
- Votare probabilistică: media probabilităților prezise, urmată de alegerea clasei cu media cea mai mare. Poate folosi mai multă informație decât votarea dură atunci când probabilitățile modelelor sunt comparabile și bine calibrate.
Notă tehnică a traducerii: votarea probabilistică nu este întotdeauna mai bună. Un model foarte sigur, dar prost calibrat, poate domina media; calibrați probabilitățile și alegeți ponderile exclusiv pe date de validare.
Construiți
Pasul 1: ciot de decizie (model de bază)
Codul din code/ensembles.py implementează totul de la zero. Începem cu un ciot de decizie: un arbore cu o singură separare.
class DecisionStump:
def __init__(self):
self.feature_idx = None
self.threshold = None
self.polarity = 1
self.alpha = None
def fit(self, X, y, weights):
n_samples, n_features = X.shape
best_error = float("inf")
for f in range(n_features):
thresholds = np.unique(X[:, f])
for thresh in thresholds:
for polarity in [1, -1]:
pred = np.ones(n_samples)
pred[polarity * X[:, f] < polarity * thresh] = -1
error = np.sum(weights[pred != y])
if error < best_error:
best_error = error
self.feature_idx = f
self.threshold = thresh
self.polarity = polarity
def predict(self, X):
n = X.shape[0]
pred = np.ones(n)
idx = self.polarity * X[:, self.feature_idx] < self.polarity * self.threshold
pred[idx] = -1
return pred
Pasul 2: AdaBoost de la zero
class AdaBoostScratch:
def __init__(self, n_estimators=50):
self.n_estimators = n_estimators
self.stumps = []
self.alphas = []
def fit(self, X, y):
n = X.shape[0]
weights = np.full(n, 1 / n)
for _ in range(self.n_estimators):
stump = DecisionStump()
stump.fit(X, y, weights)
pred = stump.predict(X)
err = np.sum(weights[pred != y])
err = np.clip(err, 1e-10, 1 - 1e-10)
alpha = 0.5 * np.log((1 - err) / err)
weights *= np.exp(-alpha * y * pred)
weights /= weights.sum()
stump.alpha = alpha
self.stumps.append(stump)
self.alphas.append(alpha)
def predict(self, X):
total = sum(a * s.predict(X) for a, s in zip(self.alphas, self.stumps))
return np.sign(total)
Pasul 3: gradient boosting de la zero
class GradientBoostingScratch:
def __init__(self, n_estimators=100, learning_rate=0.1, max_depth=3):
self.n_estimators = n_estimators
self.lr = learning_rate
self.max_depth = max_depth
self.trees = []
self.initial_pred = None
def fit(self, X, y):
self.initial_pred = np.mean(y)
current_pred = np.full(len(y), self.initial_pred)
for _ in range(self.n_estimators):
residuals = y - current_pred
tree = SimpleRegressionTree(max_depth=self.max_depth)
tree.fit(X, residuals)
update = tree.predict(X)
current_pred += self.lr * update
self.trees.append(tree)
def predict(self, X):
pred = np.full(X.shape[0], self.initial_pred)
for tree in self.trees:
pred += self.lr * tree.predict(X)
return pred
Pasul 4: comparați cu scikit-learn
Codul compară implementările construite de la zero cu estimatorii corespunzători din scikit-learn și prezintă metodele alăturat.
Notă tehnică a traducerii: fragmentele nu sunt autonome: folosesc
npfără a afișaimport numpy as np, iarSimpleRegressionTreenu este definit în pagină.AdaBoostScratchnu tratează explicit eroarea cel puțin egală cu 0,5, nu se oprește la eroare zero, iarnp.sign(total)poate întoarce eticheta 0 la egalitate. Ambele metodefitadaugă estimatori la listele existente la apeluri repetate. În plus,GradientBoostingScratchimplementează regresie cu pierdere pătratică și produce valori continue; nu poate fi comparat direct ca acuratețe cuGradientBoostingClassifierfără o formulare și un prag de clasificare adecvate.
Folosiți
Când să folosiți fiecare metodă
| Metodă | Efect principal frecvent | Potrivită pentru | Atenție la |
|---|---|---|---|
| Bagging / pădure aleatoare | Reducerea varianței | Date zgomotoase, multe caracteristici, modele de bază instabile | Nu elimină automat deplasarea |
| AdaBoost | Reducerea erorii prin reponderare | Date relativ curate, modele de bază simple | Sensibilitate la valori aberante și zgomot |
| Gradient boosting | Reducerea erorii secvențiale | Date tabelare și pierderi diferențiabile | Antrenare secvențială și risc de supraînvățare fără reglare |
| XGBoost / LightGBM | Regularizare și optimizare de ordinul al doilea sau pe histograme | Multe sarcini tabelare de producție | Numeroși hiperparametri și alegeri dependente de bibliotecă |
| Stacking | Combinarea erorilor complementare | Obținerea unui câștig suplimentar din modele diverse | Complexitate și risc de scurgere ori supraînvățare a metamodelului |
| Votare | Stabilizarea predicțiilor | Combinarea rapidă a unor modele diverse | Ajută numai dacă modelele aduc informație complementară |
Un flux practic pentru date tabelare
Pentru multe probleme de predicție tabelară, puteți începe astfel:
- Evaluați LightGBM, XGBoost sau un estimator de gradient boosting pe histograme, împreună cu referințe simple.
- Reglați numărul de estimatori, rata de învățare, complexitatea arborilor și regularizarea prin validare încrucișată adecvată datelor.
- Dacă un câștig suplimentar justifică complexitatea, evaluați un ansamblu stacking cu câteva modele diverse.
- Păstrați preprocesarea și selecția în interiorul validării încrucișate și folosiți un set de testare independent pentru raportarea finală.
Rețelele neuronale pot fi mai slabe decât gradient boosting pe multe benchmark-uri tabelare de dimensiune medie, dar rezultatul nu este universal. Comparați empiric metodele sub același protocol, buget de reglare și metrică.
Livrați
Această lecție produce outputs/prompt-ensemble-selector.md — un prompt care vă ajută să alegeți metoda de ansamblu potrivită pentru un set de date. Descrieți datele — dimensiune, tipuri de caracteristici, nivel de zgomot și echilibrul claselor — și problema pe care o rezolvați. Promptul parcurge o listă de decizii, recomandă o metodă, sugerează hiperparametri inițiali și avertizează asupra greșelilor frecvente ale acelei metode. Lecția produce și outputs/skill-ensemble-builder.md, cu ghidul complet de selecție.
Exerciții
-
Modificați implementarea AdaBoost pentru a urmări acuratețea de antrenare după fiecare rundă. Reprezentați acuratețea în funcție de numărul de estimatori. Când se stabilizează?
-
Implementați de la zero o pădure aleatoare adăugând unui arbore de regresie subeșantionarea aleatoare a caracteristicilor. Antrenați 100 de arbori cu
max_features=sqrt(n_features)și calculați media predicțiilor. Comparați varianța cu aceea a unui singur arbore pe mai multe eșantioane sau împărțiri, nu doar printr-o singură valoare observată. -
Adăugați oprire timpurie implementării gradient boosting: urmăriți pierderea de validare după fiecare rundă și opriți-vă când nu s-a îmbunătățit timp de 10 runde consecutive. Câți arbori sunt necesari în acea rulare?
-
Construiți un ansamblu stacking cu trei modele de bază — regresie logistică, arbore de decizie și k cei mai apropiați vecini — și un metamodel de regresie logistică. Folosiți validare încrucișată cu 5 fold-uri pentru a genera metacaracteristici out-of-fold. Comparați ansamblul cu fiecare model de bază separat pe date reținute.
-
Rulați XGBoost pe același set de date cu o configurație inițială documentată. Comparați acuratețea cu gradient boosting-ul construit de la zero și măsurați timpul ambelor metode în aceleași condiții. Cât de mare este diferența și cât de stabilă este între repetări?
Termeni-cheie
| Termen | Cum i se spune | Ce înseamnă de fapt |
|---|---|---|
| Bagging | „Antrenare pe submulțimi aleatoare” | Agregare bootstrap: antrenați modele pe eșantioane bootstrap și mediați predicțiile pentru a reduce varianța |
| Boosting | „Concentrare pe exemplele dificile” | Antrenarea secvențială a modelelor, fiecare corectând erorile ansamblului curent conform algoritmului |
| AdaBoost | „Reponderarea datelor” | Boosting prin actualizarea ponderilor eșantioanelor; punctele clasificate greșit primesc o pondere mai mare pentru următorul model |
| Gradient boosting | „Ajustarea reziduurilor” | Boosting prin ajustarea fiecărui model nou la gradientul negativ al funcției de pierdere |
| XGBoost | „Instrumentul competițiilor Kaggle” | Gradient boosting cu obiectiv regularizat, informație de ordinul al doilea și optimizări de sistem |
| Stacking | „Modele peste modele” | Folosirea predicțiilor out-of-fold ale modelelor de bază drept intrări pentru un metamodel |
| Pădure aleatoare | „Mulți arbori randomizați” | Bagging cu arbori de decizie și subeșantionare aleatoare a caracteristicilor la fiecare separare |
| Diversitatea ansamblului | „Să facă greșeli diferite” | Modelele trebuie să aducă erori suficient de necorelate sau informație complementară pentru ca ansamblul să se îmbunătățească |
| Eroare out-of-bag | „Validare fără un holdout separat” | Estimarea pe fiecare eșantion folosind numai arborii ale căror eșantioane bootstrap nu l-au inclus |
Lecturi suplimentare
- Schapire și Freund: Boosting: Foundations and Algorithms — cartea autorilor AdaBoost
- Friedman: Greedy Function Approximation: A Gradient Boosting Machine (2001) — lucrarea originală despre gradient boosting
- Chen și Guestrin: XGBoost (2016) — lucrarea despre XGBoost
- Wolpert: Stacked Generalization (1992) — lucrarea originală despre stacking
- Metode de ansamblu în scikit-learn — referință practică
Sursă: Ensemble Methods — original
Navigare: înapoi: 02.10 — Compromisul deplasare–varianță · Faza 2 — Bazele învățării automate · Catalog complet.