Přeskočit na obsah
coden

Ansámbly: náhodný les a gradient boosting

Moudrost davu a proč musí být chyby nezávislé, bagging, náhodný les a korelace stromů, odhad chyby z vynechaných vzorků, gradient boosting a rychlost učení — na datech o splácení půjček.

13 minut Matěj Žalmánek 2026-10-16

Série Základy AI Díl 54 z 83
  1. Mapa umělé inteligence: co je co a jak to do sebe zapadá
  2. Stručná historie umělé inteligence: od Turinga po jazykové modely
  3. Data, model, trénink, inference: základní pojmy na jednom příkladu
  4. Jak číst matematický zápis: symboly, indexy, sumy a kvantifikátory
  5. Množiny a relace: stavebnice, ze které se skládají definice v AI
  6. Funkce a zobrazení: proč je každý model v AI funkce
  7. Logika a důkazy: pravidla, podle kterých se v AI uvažuje
  8. Grafy a stromy: struktura, na které stojí hledání i neuronové sítě
  9. Lineární algebra pro strojové učení: vektory, matice a proč AI hlavně násobí
  10. Derivace, gradient a řetízkové pravidlo: jak model zjistí, kterým směrem se učit
  11. Gradientní sestup: jak se model učí
  12. Co je pravděpodobnost: od hodu kostkou ke Kolmogorovovým axiomům
  13. Podmíněná pravděpodobnost a Bayesova věta: jak změnit odhad, když se dozvíte něco nového
  14. Náhodná veličina a distribuční funkce: jedna funkce, která o rozdělení řekne všechno
  15. Funkce hustoty a pravděpodobnostní funkce: proč má spojitá veličina v bodě pravděpodobnost nula
  16. Střední hodnota, rozptyl a kovariance: kde rozdělení leží, jak je široké a co s čím souvisí
  17. Přehled pravděpodobnostních rozdělení: Bernoulli, binomické, Poisson, rovnoměrné, normální a exponenciální
  18. Zákon velkých čísel a centrální limitní věta: proč se průměry chovají tak předvídatelně
  19. Statistika a odhady parametrů: maximální věrohodnost, MAP a intervaly spolehlivosti
  20. Teorie informace: entropie, křížová entropie a KL divergence — odkud se berou ztrátové funkce
  21. Prohledávání stavového prostoru: BFS, DFS, UCS a A* s animacemi
  22. Hry a protivník: minimax, alfa-beta ořezávání a Monte Carlo tree search
  23. Splňování omezujících podmínek: backtracking, propagace omezení a AC-3 na sudoku a mapě krajů
  24. Logika a znalostní systémy: dopředné a zpětné řetězení, rezoluce a expertní systémy
  25. Plánování: STRIPS, svět kostek, heuristiky z relaxace a plánování v AI agentech
  26. Lokální hledání a simulované žíhání: obchodní cestující přes krajská města
  27. Genetické algoritmy: populace, křížení, mutace a výběr na batohu na výlet
  28. Evoluční strategie a genetické programování: od pravidla jedné pětiny po Keplerův zákon
  29. Optimalizace mravenčí kolonií: jak feromonová stopa najde krátkou cestu
  30. Optimalizace hejnem částic: setrvačnost, vlastní zkušenost a zkušenost hejna
  31. Neuroevoluce: evoluce vah i tvaru neuronových sítí a algoritmus NEAT
  32. Fuzzy množiny a funkce příslušnosti: jak zapsat „trochu teplo“
  33. Fuzzy logika a pravděpodobnost: proč „trochu teplo“ neznamená „pravděpodobně teplo“
  34. Fuzzy logika: t-normy, implikace a pravidla KDYŽ–PAK
  35. Fuzzy řízení: Mamdani a Sugeno od ventilátoru po kyvadlo na vozíku
  36. Fuzzy shlukování: algoritmus fuzzy c-means a body mezi shluky
  37. Neuro-fuzzy systémy (ANFIS): fuzzy pravidla, která se učí z dat
  38. Markovovy řetězce: přechodová matice, stacionární rozdělení a PageRank
  39. Skryté Markovovy modely: Viterbiho algoritmus a nepoctivé kasino
  40. Bayesovské sítě: proč je tráva mokrá a co z toho plyne pro postřikovač
  41. Kalmanův filtr: jak z nepřesných měření odhadnout, kde auto je a jak rychle jede
  42. Druhy strojového učení: s učitelem, bez učitele, s částečným učitelem a další
  43. Přeučení a regularizace: proč model, který zná data nazpaměť, selže
  44. Vyhodnocení modelu: křížová validace, F1 a křivka ROC
  45. Shlukování a snížení dimenze: k-means, PCA a t-SNE
  46. Klasifikace a regrese: dvě úlohy učení s učitelem
  47. Lineární regrese: nejmenší čtverce geometricky i maticově
  48. Polynomiální a nelineární regrese: jak přímku ohnout
  49. Logistická regrese: sigmoida, šance a křížová entropie
  50. Vícetřídní klasifikace a softmax: od dvou tříd k mnoha
  51. Naivní Bayesův klasifikátor: spamový filtr, který funguje lépe, než by měl
  52. Ztrátové funkce: co přesně model minimalizuje
  53. Rozhodovací stromy a k nejbližších sousedů: modely bez vzorců
  54. Ansámbly: náhodný les a gradient boosting
  55. SVM a jádrový trik: nejširší hranice a jak ji ohnout
  56. Signál a vzorkování: proč platí Nyquistův teorém
  57. Fourierova transformace: rozklad signálu na frekvence
  58. Filtry a konvoluce: vyhlazení, hrany a odstranění šumu
  59. Zvuk a řeč: spektrogram, melová škála a MFCC
  60. Obraz jako signál: pixely, barvy, konvoluce a hrany
  61. Perceptron a umělý neuron: nejjednodušší neuronová síť a co neumí
  62. Neuronová síť od nuly: zpětné šíření chyby krok za krokem
  63. Aktivace, inicializace a normalizace: drobnosti, na kterých hluboká síť stojí
  64. Konvoluční sítě: jak síť poznává obrázky
  65. Rekurentní sítě: paměť pro posloupnosti a mizející gradient
  66. LSTM a GRU: brány, které rozhodují, co si síť zapamatuje
  67. Autoenkodéry: síť, která se učí data stlačit a zase rozbalit
  68. Embeddingy a word2vec: jak se slovo stane vektorem
  69. Mechanismus pozornosti: jak se model naučí, kam se dívat
  70. Transformery a velké jazykové modely: architektura krok za krokem
  71. Tokenizace: jak se text rozseká na kousky pro model
  72. Předtrénování a škálování: proč větší model a víc dat funguje
  73. Doladění a RLHF: jak se z doplňovače textu stane asistent
  74. Prompty, kontext a RAG: jak modelu dát správné informace
  75. Variační autoenkodéry (VAE): nové obrázky ze spojitého latentního prostoru
  76. Generativní adversariální sítě (GAN): padělatel proti detektivovi
  77. Difúzní modely: jak se z čistého šumu stane obrázek
  78. Markovovy rozhodovací procesy: stavy, akce, odměny a Bellmanovy rovnice
  79. Q-learning a DQN: učení hodnoty akcí od tabulky po neuronovou síť
  80. Policy gradient a PPO: učení přímo strategie
  81. Jak funguje AI agent: jazykový model ve smyčce s nástroji
  82. Programování s AI agenty: zadání, testy a kontrola
  83. Vyhodnocení a bezpečnost AI systémů: jak měřit a jak hlídat

Celá osnova série 83 z 83 témat hotovo

Co si odnesete
  • Proč hlasování mnoha modelů funguje jen tehdy, když se mýlí nezávisle.
  • Jak bagging a náhodný les zkrotí přecitlivělé stromy.
  • Jak gradient boosting opravuje chyby krok za krokem a proč hlídat počet kroků.

Co se hodí znát předem: Rozhodovací stromy a k nejbližších sousedů: modely bez vzorců

Roku 1906 nechal statistik Francis Galton na dobytčím trhu 787 lidí hádat váhu vola. Jednotlivé tipy byly všelijaké, ale jejich střed (medián) se od skutečnosti lišil o necelé procento. Na stejném principu stojí jedny z nejúspěšnějších modelů strojového učení: místo jednoho chytrého modelu jich naučit sto hloupějších a nechat je hlasovat. V soutěžích na tabulková data (ceny, pojištění, podvody) takové ansámbly stromů dodnes porážejí i neuronové sítě.

Navazuje na díl Rozhodovací stromy a k nejbližších sousedů; pracujeme se stejnými daty o splácení půjček.

1. Moudrost davu — a její podmínka

Definice — ansámbl

Nechť 𝒳 je množina vstupů, B ≥ 2 a h1, …, hB jsou modely definované na 𝒳 (v klasifikaci s hodnotami v konečné množině tříd 𝒞, v regresi v ℝ). Ansámbl těchto modelů je model F na 𝒳, jehož předpověď vznikne kombinací předpovědí h1(x), …, hB(x), obvykle jedním z těchto předpisů:

  1. hlasování (klasifikace): F(x) = argmaxc ∈ 𝒞 |{b ∈ {1, …, B} : hb(x) = c}|;
  2. průměr pravděpodobností (klasifikace, dává-li každý model odhady p̂b(c | x)): F(x) = argmaxc ∈ 𝒞 1/B ∑b=1B p̂b(c | x);
  3. (vážený) průměr (regrese): F(x) = ∑b=1B wb hb(x) s vahami wb ≥ 0, ∑b wb = 1 (prostý průměr pro wb = 1/B).

Ansámbl je tedy model složený z více modelů, jejichž předpovědi se zkombinují.

Laicky řečeno

Představte si poradce, z nichž každý má pravdu v 60 % případů. Jeden je skoro k ničemu. Když se ale zeptáte jedenácti a uděláte, co řekne většina, máte pravdu v 75,3 % případů; se 101 poradci v 97,9 %. Chyby jednotlivců se navzájem vyruší — pokud jsou nezávislé. Když v 30 % případů všichni opíšou jednoho názorového vůdce, ani 1 001 poradců nepřekročí 88,0 %: dav, který si opisuje, je jen jeden hlas mnohokrát.

Věta — Condorcetova věta o porotě

Nechť n ∈ ℕ je liché, p ∈ (0, 1) a X1, …, Xn jsou nezávislé náhodné veličiny s P(Xi = 1) = p a P(Xi = 0) = 1 − p (Xi = 1 znamená, že i-tý hlasující má pravdu). Označme

Pn = P(X1 + … + Xn > n/2)

pravděpodobnost, že většina má pravdu. Pak Pn je dána vzorcem níže a platí:

  1. je-li p > 1/2, pak Pn s rostoucím lichým n roste a Pn → 1 pro n → ∞;
  2. je-li p < 1/2, pak Pn s rostoucím lichým n klesá a Pn → 0.

Proč: počet správných hlasů X1 + … + Xn má binomické rozdělení se střední hodnotou np a směrodatnou odchylkou √np(1 − p). Většina potřebuje víc než n/2; pro p > 1/2 je odstup n(p − 1/2) úměrný n, kdežto typická odchylka od střední hodnoty roste jen jako √n, takže je odstup čím dál bezpečnější. Tvrzení vyslovil markýz de Condorcet roku 1785; dnešní zápis se vzorcem je pozdější formalizace.

Pn = ∑k = n + 1/2n C(n, k) · pk (1 − p)n−k

Pn
pravděpodobnost, že většina z n nezávislých hlasujících má pravdu — zelená křivka v obrázku
k ≥ n + 1/2
sčítá se jen přes ty počty správných hlasů, které tvoří většinu; u 11 hlasujících je to 6 až 11
C(n, k)
kombinační číslo: kolika způsoby lze vybrat, kteří z hlasujících mají pravdu — na tom výsledek nezávisí, ale každý takový výběr je jiná možnost
pk (1 − p)n−k
pravděpodobnost jednoho konkrétního výběru: k hlasujících má pravdu a zbylých n − k se mýlí; násobí se, protože jsou nezávislí
Příklad — tři poradci s 60 %

všichni tři mají pravdu (k = 3):   C(3, 3) · 0,63 = 1 · 0,216 = 0,216

právě dva (k = 2):   C(3, 2) · 0,62 · 0,4 = 3 · 0,36 · 0,4 = 0,432

P3 = 0,216 + 0,432 = 0,648   (z 60 % na 64,8 %);   P11 = 0,753,   P101 = 0,979

Barvy odpovídají členům vzorce pro Pn výše.

Opisování popisuje náš jednoduchý model závislosti (vlastní zjednodušení pro tento díl): s pravděpodobností ρ všichni zopakují názor jednoho vůdce, jinak hlasují nezávisle.

Pzáv = ρ · p + (1 − ρ) · Pn

Pzáv
pravděpodobnost, že má většina pravdu, když se opisuje — jantarová křivka v obrázku
ρ · p
všichni opsali vůdce (s pravděpodobností ρ) a ten měl pravdu (p); celý dav je tu jediný hlas a víc hlasujících nepomůže
1 − ρ
pravděpodobnost, že se tentokrát neopisuje
Pn
pak platí Condorcetův vzorec pro nezávislé — tato část s rostoucím n jde k 1
Pro ρ = 0,3, p = 0,6 a velké n: Pzáv ≈ 0,3 · 0,6 + 0,7 · 1 = 0,18 + 0,70 = 0,88 — strop 88,0 %, přes který žádný počet hlasujících nepřejde.
50 %60 %70 %80 %90 %100 % 1111011001 hlasující n (počet, log. měřítko) P(většina má pravdu) (%)
Pravděpodobnost, že většina má pravdu (každý hlasující má pravdu v 60 %) nezávislí v 30 % případů všichni opíšou jednoho

Celé umění ansámblů je proto v jediné otázce: jak naučit mnoho modelů, které jsou každý slušný, a přitom se mýlí v různých případech?

2. Bagging: stejný model, jiná data

Definice — bootstrap a bagging

Nechť n ≥ 1 a D = ((x1, y1), …, (xn, yn)) jsou trénovací data. Nechť I1, …, In jsou nezávislé náhodné veličiny s rovnoměrným rozdělením na {1, …, n}, tj. P(Ij = i) = 1/n pro všechna i, j ∈ {1, …, n}. Bootstrapový výběr z D je posloupnost

D* = ((xI1, yI1), …, (xIn, yIn)),

tedy n příkladů vybraných náhodně s vracením: některé se opakují, jiné chybí.

Bagging (bootstrap aggregating; Leo Breiman, 1996) je algoritmus:

  • Vstup: trénovací data D, počet modelů B ≥ 1 a učicí algoritmus 𝒜, který z dat vyrobí model (u nás hluboký rozhodovací strom).
  • Výstup: ansámbl F.
  1. Pro b = 1, …, B: vylosuj (nezávisle na ostatních) bootstrapový výběr D*b z D a nauč model hb = 𝒜(D*b).
  2. Po B modelech skonči a vrať ansámbl: v regresi F(x) = 1/B ∑b=1B hb(x), v klasifikaci hlasování modelů h1, …, hB.
Laicky řečeno

Hluboký strom je přecitlivělý: malá změna dat ho přestaví. Normálně je to vada — tady se z ní stane výhoda. Každý strom dostane trochu jinou verzi dat, vyroste trochu jinak a přeučí se na jiném šumu. Když jich zprůměrujeme dvě stě, náhodné výkyvy se vyruší a zůstane to, na čem se shodnou.

Jeden hluboký strom na našich datech (nechaný růst, dokud nejsou listy čisté) má na 4 000 nových klientech přesnost 86,5 %. Bagging z deseti takových stromů má 88,5 %, z dvou set 89,3 %.

Algoritmus — bagging a náhodný les
def les(D, B, m):                       # m = 2: bagging, m = 1: náhodný les (u nás)
    stromy = []
    for b in range(B):
        idx = [nahodne_cele(0, n − 1) for _ in range(n)]   # s vracením
        stromy.append(postav_hluboky([D[i] for i in idx], m))
    return stromy

def postav_hluboky(D, m):               # CART bez omezení hloubky
    if D je čistá: return List(třída)
    kandidati = náhodný výběr m příznaků z p   # jen v náhodném lese m < p
    najdi nejlepší práh jen mezi kandidáty (Giniho nečistota)
    return Uzel(…, ano=postav_hluboky(L, m), ne=postav_hluboky(P, m))

def hlas(stromy, x):
    return sum(strom(x) for strom in stromy) / len(stromy)  # podíl hlasů „splatí“

Předpověď je „splatí“, když hlas ≥ 0,5. Stromy na sobě nezávisí, takže je jde stavět paralelně — na rozdíl od boostingu níže.

3. Náhodný les: ještě víc náhody

Definice — náhodný les

Nechť příklady mají p ≥ 1 příznaků, m ∈ {1, …, p} a B ≥ 1. Náhodný les (random forest; Breiman, 2001) s B stromy je bagging, ve kterém učicí algoritmus 𝒜 je CART (viz díl Rozhodovací stromy) bez omezení hloubky s touto změnou:

  1. v každém uzlu se nezávisle na ostatních uzlech vylosuje množina příznaků M ⊆ {1, …, p}, |M| = m, rovnoměrně ze všech m-prvkových podmnožin;
  2. nejlepší dělení (s nejmenší váženou Giniho nečistotou) se hledá jen mezi příznaky j ∈ M.

Typicky se volí m ≈ √p; pro m = p je náhodný les obyčejný bagging stromů.

Laicky řečeno

I na různých bootstrapových výběrech se stromy často ptají na totéž — první otázka bývá skoro vždy „příjem ≤ 40 tisíc?“. Náhodný les jim to zakáže: v každém uzlu smí strom vybírat jen z náhodné části příznaků. U nás jsou příznaky jen dva, takže v každém uzlu dostane strom náhodně buď příjem, nebo věk. Jednotlivé stromy tím trochu zhloupnou, ale přestanou si být podobné.

Měřitelně: korelace chyb dvou náhodně vybraných stromů je u baggingu 0,53, v náhodném lese 0,42. Les z 200 stromů má přesnost 90,2 % (nejvíc 90,5 % s 25 stromy). Strop daný šumem v datech je 91,5 %.

Proč na korelaci tolik záleží, ukazuje vzorec pro rozptyl průměru B stejně rozptýlených předpovědí, z nichž každé dvě mají korelaci ρ (Hastie, Tibshirani, Friedman: The Elements of Statistical Learning, 2. vyd., rovnice 15.1):

Var( 1/B ∑b hb(x) ) = ρ σ2 + (1 − ρ) σ2/B

ρ σ2
společná část chyb, kterou mají všechny stromy — průměrování ji neodstraní, ať je stromů kolik chce. Proto náhodný les snižuje ρ
(1 − ρ) σ2
vlastní, nesdílená část rozptylu každého stromu — ta, kterou se stromy mezi sebou liší
B
počet stromů; vlastní výkyvy se průměrováním vyruší, a proto se nesdílená část dělí B. Od několika desítek stromů je skoro nulová
σ2 je rozptyl předpovědi jednoho stromu. Víc stromů zmenší jen druhý člen; první zmenší jen méně podobné stromy.
Příklad — 200 stromů s našimi korelacemi

bagging, ρ = 0,53:   0,53 σ2 + 0,47 σ2/200 = 0,532 σ2

náhodný les, ρ = 0,42:   0,42 σ2 + 0,58 σ2/200 = 0,423 σ2

Barvy odpovídají členům vzorce výše.

Při 200 stromech je druhý člen zanedbatelný a o rozptylu rozhoduje skoro jen ρ. Je to jen přibližná ilustrace: vzorec platí pro průměr čísel, my jsme měřili korelaci chyb (indikátorů „strom se spletl“) a hlasování není prostý průměr. Směr ale sedí — méně korelované stromy dávají stabilnější les.

měsíční příjem (tis. Kč, 15–90) věk (roky, 20–70) jeden hluboký strom měsíční příjem (tis. Kč, 15–90) věk (roky, 20–70) bagging, 200 stromů měsíční příjem (tis. Kč, 15–90) věk (roky, 20–70) náhodný les, 200 stromů měsíční příjem (tis. Kč, 15–90) věk (roky, 20–70) gradient boosting, 50 kroků
Jeden strom proti ansámblům; sytost barvy = jistota modelu

Obrázek ukazuje i druhý dar ansámblů: místo ostrých obdélníků jednoho stromu je hranice měkká a model ví, kde si není jistý — podíl stromů, které hlasují „splatí“, funguje jako pravděpodobnost. Schody tam pořád jsou, ale jemnější a zprůměrované.

4. Testovací data zadarmo: odhad z vynechaných

Definice — chyba z vynechaných vzorků (OOB)

Nechť D = ((x1, y1), …, (xn, yn)) jsou trénovací data s yi ∈ {0, 1} a h1, …, hB : 𝒳 → {0, 1} stromy baggingu nebo náhodného lesa, kde hb je naučený na bootstrapovém výběru D*b s vylosovanými indexy Ib1, …, Ibn. Pro i ∈ {1, …, n} označme

Oi = {b ∈ {1, …, B} : Ibj ≠ i pro všechna j = 1, …, n}

množinu stromů, které příklad i při učení neviděly, a H = {i : Oi ≠ ∅}. Pro i ∈ H je předpověď z vynechaných vzorků (out-of-bag, OOB) ŷi = 1, právě když 1/|Oi| ∑b ∈ Oi hb(xi) ≥ 1/2, jinak ŷi = 0. OOB přesnost je

|{i ∈ H : ŷi = yi}|/|H|,

a chyba z vynechaných vzorků je 1 minus OOB přesnost. Každý trénovací příklad se tedy předpoví jen hlasováním stromů, které ho při učení neviděly, a výsledek se porovná se skutečností. Bootstrapový výběr přitom vynechá každý příklad s pravděpodobností (1 − 1/n)n ≈ 1/e ≈ 36,8 % (věta níže).

Laicky řečeno

Každý strom třetinu klientů nikdy neviděl, a ti pro něj fungují jako testovací data. Les si tak testovací sadu vyrobí sám, bez obětování dat. V našich lesích chybí v každém výběru průměrně 36,9 % klientů.

Věta — proč chybí zhruba třetina

Nechť n ≥ 1, D* je bootstrapový výběr z n příkladů (s indexy I1, …, In) a i ∈ {1, …, n}. Pak

P(Ij ≠ i pro všechna j) = (1 − 1/n)n   a   limn → ∞ (1 − 1/n)n = e−1 ≈ 0,368.

Důkaz. Při jednom losování se konkrétní příklad nevybere s pravděpodobností 1 − 1/n. Losování jsou nezávislá a je jich n, takže příklad chybí v celém výběru s pravděpodobností (1 − 1/n)n. Z ln(1 − 1/n) ≈ −1/n − 1/2n2 plyne n · ln(1 − 1/n) → −1, tedy (1 − 1/n)n → e−1. ∎

n = 200:   200 · ln(0,995) = 200 · (−0,0050125) = −1,0025,   e−1,0025 = 0,3670

limita:   e−1 = 0,3679;   ve výběru je tedy v průměru 1 − 0,367 = 63,3 % různých klientů

Naměřených 36,9 % je průměr přes 200 skutečných výběrů — od teoretických 36,7 % se liší náhodou losování.

Algoritmus — odhad z vynechaných vzorků
dobre = hodnoceno = 0
for i, (x_i, y_i) in enumerate(D):
    porota = [s for s in stromy if i not in s.vyber]   # stromy, které i neviděly
    if not porota: continue                            # (skoro nemožné: 0,633^200 ≈ 10^−40)
    hlas = sum(s(x_i) for s in porota) / len(porota)
    hodnoceno += 1
    dobre += ((hlas >= 0.5) == y_i)
oob_presnost = dobre / hodnoceno

Každý klient je hodnocen „porotou“ asi 0,37 · 200 ≈ 73 stromů, ne celým lesem — i proto je odhad o něco pesimističtější.

OOB odhad dal pro bagging 85,0 % a pro les 86,0 %, na 4 000 nových klientech je skutečnost 89,3 % a 90,2 %. Odhad je tu o tři až čtyři body pesimistický: každý klient je hodnocen jen třetinou lesa, a hlavně je trénovacích klientů jen 200, takže i samotný odhad kolísá zhruba o ±2 procentní body. Při tisících příkladů bývá OOB odhad velmi blízko testovací chybě — a je to oblíbený způsob, jak les ladit bez křížové validace.

5. Boosting: modely, které opravují předchůdce

Bagging staví stromy vedle sebe, nezávisle. Boosting je staví za sebou: každý další se soustředí na to, co předchozí pokazily.

Definice — gradient boosting

Nechť (x1, y1), …, (xn, yn) jsou trénovací data s xi ∈ 𝒳 a yi ∈ {0, 1}, L(y, F) ztráta skóre F ∈ ℝ diferencovatelná podle F (u nás logistická, viz věta níže), M ∈ ℕ počet kroků a η ∈ (0, 1] rychlost učení (shrinkage). Gradient boosting (Jerome Friedman, 2001) je algoritmus:

  • Vstup: trénovací data, ztráta L, M, η a maximální hloubka regresních stromů (u nás 2).
  • Výstup: skórovací funkce FM : 𝒳 → ℝ; pravděpodobnost třídy 1 je σ(FM(x)).
  1. Polož F0(x) = c0 pro všechna x, kde c0 minimalizuje ∑i L(yi, c) (u logistické ztráty c0 = ln p̄/1 − p̄, p̄ = podíl jedniček).
  2. Pro m = 1, …, M:
    1. spočítej pseudorezidua ri = −∂L(yi, F)/∂F v bodě F = Fm−1(xi), i = 1, …, n (u logistické ztráty ri = yi − pi s pi = σ(Fm−1(xi)));
    2. nauč malý regresní strom hm : 𝒳 → ℝ na dvojicích (xi, ri);
    3. polož Fm(x) = Fm−1(x) + η · hm(x).
  3. Po M krocích skonči a vrať FM.

Model je tedy součet FM = F0 + η(h1 + … + hM), kde každý strom je naučený na záporný gradient ztráty podle F.

Laicky řečeno

První strom udělá hrubý odhad. Druhý se podívá, kde se první spletl, a naučí se opravu. Třetí opravuje opravu — a tak dál. Je to gradientní sestup, jen místo vah posunujeme celou funkci a každý krok je malý strom. Stromy jsou schválně slabé (u nás hloubka 2, tedy čtyři listy) a každá oprava se započítá jen z části η, aby jeden strom nepřestřelil.

Fm(x) = Fm−1(x) + η · hm(x),   p = σ(F)

Fm(x)
skóre modelu po m krocích (logaritmus šancí); sigmoida z něj udělá pravděpodobnost splacení jako v logistické regresi
Fm−1(x)
všechno, co už umí předchozí stromy — zůstává beze změny, nový strom ho jen opravuje
η
rychlost učení: oprava se započte jen z části, aby chyba jednoho slabého stromu nepřebila ostatní; menší η chce víc kroků, ale přeučí se pomaleji
hm(x)
nový malý strom naučený na rezidua y − p: tam, kde model podceňuje (y = 1, malé p), skóre zvedne, kde přeceňuje, sníží
Na začátku je F0 = ln p̄/1 − p̄, logaritmus šancí podílu splácejících — nejlepší konstantní odhad.
Věta — rezidua jsou záporný gradient logistické ztráty

Nechť y ∈ {0, 1}, F ∈ ℝ a p = σ(F) = 1/1 + e−F ∈ (0, 1). Nechť

L(y, F) = −[y ln p + (1 − y) ln(1 − p)]

je logistická ztráta (křížová entropie) jednoho příkladu. Pak ∂L/∂F = p − y, tj. záporný gradient je reziduum y − p.

Důkaz: σ′(F) = p(1 − p), takže ∂L/∂F = −y · p(1 − p)/p + (1 − y) · p(1 − p)/1 − p = −y(1 − p) + (1 − y)p = p − y. ∎

Krok proti gradientu je tedy krok ve směru y − p. Gradientní sestup by posunul každé F(xi) zvlášť; boosting místo toho naučí strom, který tento směr přibližuje, a proto funguje i pro klienty, které nikdy neviděl. Hodnota listu je u nás Newtonův krok ∑ ri/∑ pi(1 − pi) přes klienty v listu (druhá derivace ztráty je p(1 − p)) — tak to dělá i Friedmanův algoritmus pro logistickou ztrátu.

Příklad — první krok boostingu na našich datech

start: p̄ = 140/200 = 0,7,   F0 = ln 0,7/0,3 = 0,847   pro všechny klienty

rezidua: splácí → 1 − 0,7 = +0,3,   nesplácí → 0 − 0,7 = −0,7;   p(1 − p) = 0,21

první strom hloubky 2 má stejné otázky jako strom z minulého dílu; list „příjem ≤ 39,5, věk ≤ 47,6“: 47 klientů, splácí 4

hodnota listu h1(x) = 4 · 0,3 − 43 · 0,7/47 · 0,21 = −28,9/9,87 = −2,93

η = 0,1:   F1 = 0,847 + 0,1 · (−2,928) = 0,847 − 0,293 = 0,554,   p = σ(0,554) = 63,5 %   → pořád „splatí“

η = 1:   F1 = 0,847 + 1 · (−2,928) = −2,081,   p = σ(−2,081) = 11,1 %   → „nesplatí“

Barvy v posledních třech řádcích odpovídají členům vzorce Fm = Fm−1 + η · hm výše.

S η = 0,1 zůstanou po prvním kroku všechny čtyři listy nad 50 % (63,5 až 72,9 %), model tedy řekne „splatí“ každému — a přesnost 74,7 % je přesně podíl splácejících mezi novými klienty. S η = 1 je model po prvním kroku totéž co strom hloubky 2 (88,2 %).

Algoritmus — gradient boosting pro dvě třídy
def boosting(D, kroku, eta, hloubka=2):
    F0 = log(prumer(y) / (1 − prumer(y)))
    F = [F0] * n                                   # skóre každého trénovacího klienta
    stromy = []
    for m in range(kroku):
        p = [sigmoida(F[i]) for i in range(n)]
        r = [y[i] − p[i] for i in range(n)]        # záporný gradient
        h = regresni_strom(D, r, hloubka)          # dělení podle r
        for list in h.listy:                       # Newtonův krok v každém listu
            list.hodnota = sum(r[i]) / sum(p[i] * (1 − p[i]))   # přes klienty v listu
        F = [F[i] + eta * h(x[i]) for i in range(n)]
        stromy.append(h)
    return lambda x: sigmoida(F0 + eta * sum(h(x) for h in stromy))

Každý strom závisí na předchozích (přes p), takže se stromy stavějí za sebou. Počet kroků je hlavní pojistka proti přeučení.

75 %80 %85 %90 % 11050200 počet stromů (log. měřítko) přesnost (% správně) 75 %80 %85 %90 % 1101001000 počet kroků boostingu (log. m.) přesnost (% správně)
Přesnost na nových klientech: vlevo podle počtu stromů v lese, vpravo podle počtu kroků boostingu bagging náhodný les boosting η = 0,1 boosting η = 1 strop jeden hluboký strom

S rychlostí učení 0,1 začíná boosting na 74,7 % (jediný slabý krok), po deseti krocích má 88,2 % a po padesáti 90,3 %. Pak ale pokračuje dál a začne se učit šum: po dvou stech krocích zná trénovací data nazpaměť a na nových klientech klesne na 89,2 %, po tisíci na 88,5 %. Boosting se — na rozdíl od lesa — přeučit umí, a počet kroků se proto volí na validační sadě (předčasné zastavení). S rychlostí učení 1 skočí na 88,2 % hned po prvním stromu, ale lepší než 88,5 % už nebude: velké kroky přeskakují jemné opravy. Malé η a víc kroků bývá skoro vždy lepší, jen pomalejší.

Předchůdcem gradient boostingu byl AdaBoost (Yoav Freund a Robert Schapire, 1995), který místo reziduí zvyšuje váhy špatně zařazených příkladů — a jak ukázal díl o ztrátových funkcích, minimalizuje exponenciální ztrátu. Dnešní knihovny jako XGBoost (2016), LightGBM a CatBoost jsou gradient boosting s mnoha inženýrskými triky.

6. Kdo vyhrál

Modelpřesnost na 4 000 nových klientech
jeden hluboký strom86,5 %
strom hloubky 389,5 %
bagging, 200 stromů89,3 %
náhodný les, 200 stromů90,2 %
gradient boosting, 50 kroků, η = 0,190,3 %
k nejbližších sousedů, k = 2591,3 %
strop (skutečná hranice)91,5 %

Ansámbly napravily hlavní vadu stromu — přecitlivělost — a z 86,5 % se dostaly přes 90 %, blízko ke stropu. Na našich dvou příznacích se šikmou hranicí je ale kNN stejně dobrý nebo lepší a logistická regrese by stačila taky. Síla ansámblů se ukáže až na skutečných tabulkách: desítky příznaků v různých jednotkách, chybějící hodnoty, kategorie, nelineární interakce. Tam náhodný les funguje skoro bez ladění a gradient boosting po vyladění bývá nejlepší, co existuje.

7. Shrnutí

  • Hlasování mnoha slabých modelů funguje, jen když se mýlí nezávisle: 101 nezávislých poradců s 60 % má pravdu v 97,9 %, opisující nepřekročí 88,0 %.
  • Bagging učí stejné modely na bootstrapových výběrech a průměruje je; z hlubokého stromu (86,5 %) udělal les s 89,3 %.
  • Náhodný les navíc losuje příznaky v každém uzlu; korelace chyb stromů klesla z 0,53 na 0,42 a přesnost stoupla na 90,2 %.
  • Každý strom nevidí asi 37 % dat — z nich se dá odhadnout chyba bez testovací sady (OOB).
  • Gradient boosting přidává malé stromy, které opravují předchůdce; s η = 0,1 dosáhl 90,3 % po 50 krocích, ale pak se přeučil — počet kroků se musí hlídat.

Chcete si to osahat? Nechte AI agenta naučit náhodný les a gradient boosting na veřejné tabulce — třeba o přeživších Titaniku — a vypsat, které příznaky les považuje za nejdůležitější.

Máte na to jiný názor? Napište na support@coden-app.com.

Agent na vašem počítači, ovládaný z telefonu