Kitaplar / Yöntem ile Makine Öğrenmesi / Bölüm 2 — Topluluk yöntemleri ve destek vektör makinesi
Bölüm 2 — Topluluk yöntemleri ve destek vektör makinesi
Tek bir ağaç ya ezberler ya da çok basit kalır. Topluluk yöntemleri birçok küçük modeli birleştirir: torbalama (rastgele orman) birbirinden bağımsız ağaçların oyunu alarak dalgalanmayı azaltır; artırma (gradyan artırma, AdaBoost, XGBoost) modelleri sırayla ekler, her biri öncekilerin hatasını düzeltir. Destek vektör makinesi ise başka bir yoldan gider: sınıflar arasına olabildiğince geniş bir boşluk bırakan sınırı arar.
6. Rastgele orman
Fikir. Aynı veriden birçok farklı ağaç kurarız. Farklılığı iki rastgelelik sağlar: her ağaç verinin geri koyarak çekilmiş bir kopyasını (bootstrap) görür ve her düğümde özniteliklerin yalnızca bir kısmı denenir. Tek tek ağaçlar zayıftır ama hataları farklı yerlerdedir; oy çokluğu hataları birbirine söndürür.
program RastgeleOrman
{ Tek bir derin karar ağacı ile 25 ağaçlık rastgele ormanı karşılaştırır.
Her ağaç, verinin geri koyarak çekilmiş bir örneğiyle (bootstrap) ve her düğümde
rastgele seçilen özniteliklerle kurulur; tahmin, ağaçların oy çokluğudur. }
kullan Matematik
tip
Düğüm = sınıf
yaprak: mantıksal
sınıfı, öznitelik: tamsayı
eşik: ondalık
sol, sağ: Düğüm
bitir
değişken
X, Xt: ondalık dizisi dizisi
Y, Yt: tamsayı dizisi
orman: Düğüm dizisi
tek: Düğüm
i, t: tamsayı
{ Veri: bir çemberin içi (1) ve dışı (0); etiketlerin %10'u bilerek yanlış (gürültü) }
prosedür Üret(n: tamsayı; X: ondalık dizisi dizisi; Y: tamsayı dizisi)
değişken a, b: ondalık; k, j: tamsayı
başla
1'den n'e kadar her j için
başla
a := Rastgele * 2 - 1; b := Rastgele * 2 - 1
k := eğer a * a + b * b < 0.5 ise 1 değilse 0
eğer Rastgele < 0.1 ise k := 1 - k
X.Ekle([a, b]); Y.Ekle(k)
bitir
bitir
fonksiyon Gini(sıra: tamsayı dizisi): ondalık
değişken p: ondalık; j: tamsayı
başla
eğer Uzunluk(sıra) = 0 ise dön 0
p := 0
sıra içindeki her j için p := p + Y[j]
p := p / Uzunluk(sıra)
sonuç := 2 * p * (1 - p)
bitir
fonksiyon Çoğunluk(sıra: tamsayı dizisi): tamsayı
değişken s, j: tamsayı
başla
s := 0
sıra içindeki her j için s := s + Y[j]
sonuç := eğer 2 * s >= Uzunluk(sıra) ise 1 değilse 0
bitir
{ öznitelikSayısı = 1 ise her düğümde tek bir rastgele öznitelik denenir (ormanın "rastgele" kısmı) }
fonksiyon Ağaç(sıra: tamsayı dizisi; derinlik, öznitelikSayısı: tamsayı): Düğüm
değişken
d: Düğüm
f, k, j, enF: tamsayı
e, puan, enPuan, enE: ondalık
sol, sağ, adaylar: tamsayı dizisi
başla
d := Düğüm.Oluştur
eğer derinlik = 0 veya Gini(sıra) = 0 ise
başla
d.yaprak := doğru; d.sınıfı := Çoğunluk(sıra); dön d
bitir
adaylar := eğer öznitelikSayısı = 2 ise [0, 1] değilse [Rastgele(2)]
enPuan := 9; enF := 0; enE := 0
adaylar içindeki her f için
sıra içindeki her k için
başla
e := X[k][f]
sol := Süz(sıra, fonksiyon(j: tamsayı) => X[j][f] < e)
sağ := Süz(sıra, fonksiyon(j: tamsayı) => X[j][f] >= e)
puan := (Uzunluk(sol) * Gini(sol) + Uzunluk(sağ) * Gini(sağ)) / Uzunluk(sıra)
eğer puan < enPuan ise başla enPuan := puan; enF := f; enE := e bitir
bitir
d.öznitelik := enF; d.eşik := enE
sol := Süz(sıra, fonksiyon(j: tamsayı) => X[j][enF] < enE)
sağ := Süz(sıra, fonksiyon(j: tamsayı) => X[j][enF] >= enE)
eğer Uzunluk(sol) = 0 veya Uzunluk(sağ) = 0 ise
başla
d.yaprak := doğru; d.sınıfı := Çoğunluk(sıra); dön d
bitir
d.sol := Ağaç(sol, derinlik - 1, öznitelikSayısı)
d.sağ := Ağaç(sağ, derinlik - 1, öznitelikSayısı)
sonuç := d
bitir
fonksiyon Tahmin(d: Düğüm; x: ondalık dizisi): tamsayı
başla
eğer d.yaprak ise dön d.sınıfı
eğer x[d.öznitelik] < d.eşik ise dön Tahmin(d.sol, x)
sonuç := Tahmin(d.sağ, x)
bitir
fonksiyon OrmanTahmini(x: ondalık dizisi): tamsayı
değişken oy: tamsayı; a: Düğüm
başla
oy := 0
orman içindeki her a için oy := oy + Tahmin(a, x)
sonuç := eğer 2 * oy > Uzunluk(orman) ise 1 değilse 0
bitir
fonksiyon Doğruluk(tekMi: mantıksal): ondalık
değişken j, isabet, p: tamsayı
başla
isabet := 0
0'dan Uzunluk(Xt) - 1'e kadar her j için
başla
p := eğer tekMi ise Tahmin(tek, Xt[j]) değilse OrmanTahmini(Xt[j])
eğer p = Yt[j] ise isabet := isabet + 1
bitir
sonuç := isabet / Uzunluk(Xt)
bitir
başla
Tohum(3)
X := []; Y := []; Xt := []; Yt := []
Üret(150, X, Y)
Üret(300, Xt, Yt)
tek := Ağaç(Aralık(Uzunluk(X)), 8, 2)
yaz(Biçimle('Tek derin ağaç (derinlik 8) → test doğruluğu: {:.3}', Doğruluk(doğru)), 1)
orman := []
1'den 25'e kadar her t için
başla
{ bootstrap: n örneği geri koyarak çek }
orman.Ekle(Ağaç(Eşle(Aralık(Uzunluk(X)), fonksiyon(j: tamsayı) => Rastgele(Uzunluk(X))), 8, 1))
eğer t = 1 veya t = 5 veya t = 25 ise
yaz(Biçimle('Rastgele orman, {:2} ağaç → test doğruluğu: {:.3}', t, Doğruluk(yanlış)), 1)
bitir
bitir.Programın çıktısı şöyledir:
Tek derin ağaç (derinlik 8) → test doğruluğu: 0.803
Rastgele orman, 1 ağaç → test doğruluğu: 0.720
Rastgele orman, 5 ağaç → test doğruluğu: 0.783
Rastgele orman, 25 ağaç → test doğruluğu: 0.840Ne öğrendik. Ormanın tek ağacı (%72), tüm veriyle kurulan derin ağaçtan (%80) kötüdür; 25 ağaç bir araya gelince %84’e çıkıyor. Etiketlerin %10’u gürültü olduğu için ulaşılabilecek en iyi doğruluk %90 civarıdır. Doğruluğu her zaman eğitimde görülmemiş bir test kümesinde ölçmek gerekir: derin ağaç eğitim verisinde %100’e yakın görünür.
Alıştırma. Ağaç sayısını 100’e çıkarınız ve doğruluğun nerede durduğuna bakınız. Bootstrap’ı kaldırıp her ağacı tüm veriyle kurarsanız ne olur?
7. Gradyan artırma
Fikir. Basit bir tahminle başlarız (ortalama). Sonra sırayla küçük ağaçlar ekleriz; her yeni ağaç o ana kadarki toplamın artıklarını (gerçek − tahmin) öğrenir. Her katkı bir öğrenme oranıyla (η) küçültülür, böylece hiçbir ağaç tek başına fazla söz sahibi olmaz.
program GradyanArtırma
{ Gürültülü bir sinüs eğrisini, art arda eklenen küçük "karar kütükleri"yle öğrenir.
Her yeni kütük, o ana kadarki toplam modelin hatalarını (artıkları) tahmin etmeye çalışır:
F_m(x) = F_(m-1)(x) + η · h_m(x) η: öğrenme oranı }
kullan Matematik
tip
Kütük = kayıt eşik, sol, sağ: ondalık; bitir { x < eşik ise sol, değilse sağ değerini verir }
değişken
X, Y, F, artık: ondalık dizisi
kütükler: Kütük dizisi
i, m, n: tamsayı
eta, okh: ondalık
k: Kütük
fonksiyon Ortalama(L: ondalık dizisi): ondalık
başla
sonuç := eğer Uzunluk(L) = 0 ise 0.0 değilse Toplam(L) / Uzunluk(L)
bitir
{ Artıklara en iyi uyan tek bölmeli ağacı bulur: her olası eşiği dener, kare hatası en küçük olanı seçer }
fonksiyon KütükUydur(r: ondalık dizisi): Kütük
değişken
j, q: tamsayı
sol, sağ: ondalık dizisi
hata, enHata: ondalık
başla
enHata := 1e9
1'den n - 1'e kadar her j için
başla
sol := []; sağ := []
0'dan n - 1'e kadar her q için eğer X[q] < X[j] ise sol.Ekle(r[q]) değilse sağ.Ekle(r[q])
hata := 0
sol içindeki her e için hata := hata + (e - Ortalama(sol)) ** 2
sağ içindeki her e için hata := hata + (e - Ortalama(sağ)) ** 2
eğer hata < enHata ise
başla
enHata := hata
sonuç := Kütük.Oluştur(X[j], Ortalama(sol), Ortalama(sağ))
bitir
bitir
bitir
başla
Tohum(1)
n := 40
X := []; Y := []
0'dan n - 1'e kadar her i için
başla
X.Ekle(i * 6.28 / n)
Y.Ekle(Sin(i * 6.28 / n) + Normal(0, 0.15))
bitir
eta := 0.3
F := Eşle(Y, fonksiyon(v: ondalık) => Ortalama(Y)) { başlangıç: herkese ortalamayı tahmin et }
kütükler := []
1'den 60'a kadar her m için
başla
artık := []
0'dan n - 1'e kadar her i için artık.Ekle(Y[i] - F[i])
k := KütükUydur(artık)
kütükler.Ekle(k)
okh := 0
0'dan n - 1'e kadar her i için
başla
F[i] := F[i] + eta * (eğer X[i] < k.eşik ise k.sol değilse k.sağ)
okh := okh + (Y[i] - F[i]) ** 2 / n
bitir
eğer m <= 3 veya m mod 20 = 0 ise
yaz(Biçimle('{:2}. kütük: x < {:.2} ise {:6.3}, değilse {:6.3} → OKH = {:.4}', m, k.eşik, k.sol, k.sağ, okh), 1)
bitir
yaz(Biçimle('x = 1.57 için tahmin {:.3} (gerçek sin = 1.000)', F[10]), 1)
bitir.Programın çıktısı şöyledir:
1. kütük: x < 3.30 ise 0.599, değilse -0.662 → OKH = 0.2739
2. kütük: x < 3.61 ise 0.386, değilse -0.522 → OKH = 0.1713
3. kütük: x < 2.98 ise 0.351, değilse -0.318 → OKH = 0.1144
20. kütük: x < 5.97 ise -0.011, değilse 0.200 → OKH = 0.0229
40. kütük: x < 4.24 ise 0.019, değilse -0.039 → OKH = 0.0096
60. kütük: x < 2.04 ise 0.022, değilse -0.010 → OKH = 0.0055
x = 1.57 için tahmin 0.888 (gerçek sin = 1.000)Ne öğrendik. İlk kütük eğriyi kabaca ikiye böldü; sonrakiler giderek küçülüp ince ayar yaptı. 20. kütükte OKH, verideki gürültünün varyansına (0,15² ≈ 0,0225) ulaştı. Ondan sonraki düşüş, model artık gürültüyü ezberlediği için yanıltıcıdır. Gerçek projelerde kaç ağaç ekleneceğine ayrı bir doğrulama kümesine bakarak karar verilir.
Alıştırma. eta değerini 1,0 ve 0,05 yapınız. Aynı OKH’ye kaç kütükte ulaşılıyor?
8. Destek vektör makinesi (SVM)
Fikir. İki sınıfı ayıran pek çok doğru vardır; SVM, iki taraftaki en yakın noktalara en uzak olanı seçer. Bu en yakın noktalara destek vektörleri denir: sınır yalnızca onlara bağlıdır, diğer noktaları silseniz sonuç değişmez. Doğrusal olmayan sınırlar için “çekirdek hilesi” kullanılır.
program DestekVektörMakinesi
{ İki sınıfı ayıran ve iki sınıfa da en uzak duran doğruyu (en geniş marjı) bulur.
Kayıp (menteşe kaybı): λ/2·‖w‖² + ortalama(max(0, 1 − y·(w·x + b)))
Doğru tarafta ve marjın dışında kalan noktalar kayba hiç katkı yapmaz. }
kullan Matematik
değişken
X: ondalık dizisi dizisi
Y: tamsayı dizisi { +1 ya da −1 }
w0, w1, b, lam, eta, m, g0, g1, gb: ondalık
i, t, n: tamsayı
fonksiyon Puan(x: ondalık dizisi): ondalık
başla
sonuç := w0 * x[0] + w1 * x[1] + b
bitir
başla
X := [[1, 2], [2, 3], [2, 1], [3, 2], [1.5, 1.5], { −1 sınıfı }
[5, 5], [6, 4], [5, 6], [7, 5], [6, 6.5], [4.5, 4]] { +1 sınıfı }
Y := [-1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1]
n := Uzunluk(X)
w0 := 0; w1 := 0; b := 0; lam := 0.01
1'den 5000'e kadar her t için
başla
eta := 1 / (lam * t + 100) { zamanla küçülen adım }
g0 := lam * w0; g1 := lam * w1; gb := 0
0'dan n - 1'e kadar her i için
eğer Y[i] * Puan(X[i]) < 1 ise { marjın içinde ya da yanlış tarafta: düzelt }
başla
g0 := g0 - Y[i] * X[i][0] / n
g1 := g1 - Y[i] * X[i][1] / n
gb := gb - Y[i] / n
bitir
w0 := w0 - eta * g0; w1 := w1 - eta * g1; b := b - eta * gb
bitir
yaz(Biçimle('Karar sınırı: {:.3}·x + {:.3}·y {} {:.3} = 0', w0, w1, eğer b < 0 ise '-' değilse '+', Mutlak(b)), 1)
yaz(Biçimle('Marj genişliği: 2/‖w‖ = {:.3}', 2 / Kök(w0 * w0 + w1 * w1)), 1)
yaz('Noktalar ve y·(w·x + b) değerleri:', 1)
0'dan n - 1'e kadar her i için
başla
m := Y[i] * Puan(X[i])
yaz(Biçimle(' ({:3}, {:3}) sınıf {:2} → {:6.3}{}', X[i][0], X[i][1], Y[i], m,
eğer m < 1.05 ise ' ← destek vektörü' değilse ''), 1)
bitir
yaz(Biçimle('Yeni nokta (3.5, 3.5) → sınıf {}', eğer Puan([3.5, 3.5]) >= 0 ise '+1' değilse '-1'), 1)
bitir.Programın çıktısı şöyledir:
Karar sınırı: 0.581·x + 0.536·y - 3.780 = 0
Marj genişliği: 2/‖w‖ = 2.529
Noktalar ve y·(w·x + b) değerleri:
( 1, 2) sınıf -1 → 2.126
( 2, 3) sınıf -1 → 1.008 ← destek vektörü
( 2, 1) sınıf -1 → 2.081
( 3, 2) sınıf -1 → 0.963 ← destek vektörü
(1.5, 1.5) sınıf -1 → 2.103
( 5, 5) sınıf 1 → 1.808
( 6, 4) sınıf 1 → 1.853
( 5, 6) sınıf 1 → 2.345
( 7, 5) sınıf 1 → 2.971
( 6, 6.5) sınıf 1 → 3.194
(4.5, 4) sınıf 1 → 0.981 ← destek vektörü
Yeni nokta (3.5, 3.5) → sınıf +1Ne öğrendik. 11 noktadan yalnızca 3’ü marjın kenarındadır (değeri 1’e yakındır): sınırı onlar belirler. Diğerlerinin değeri 1’den büyüktür, yani kayba katkıları sıfırdır. Özniteliklerin ölçeği burada da önemlidir; farklı birimlerdeki öznitelikler önce standartlaştırılmalıdır.
Alıştırma. lam değerini 1 yapınız. Marj genişliği ve destek vektörü sayısı nasıl değişiyor? (Büyük λ, geniş marj için birkaç hataya göz yumar.)
14. AdaBoost
Fikir. Her tur, yalnızca tek bir eşik kullanan çok zayıf bir sınıflandırıcı (karar kütüğü) eğitir. Yanlış sınıflanan örneklerin ağırlığı büyütülür; sonraki kütük zorunlu olarak onlara odaklanır. Sonunda her kütük, isabet oranına göre belirlenen bir ağırlıkla (α) oy verir.
$$\alpha_t = \tfrac{1}{2}\ln\frac{1-\varepsilon_t}{\varepsilon_t}, \qquad F(x) = \operatorname{işaret}\Bigl(\sum_t \alpha_t h_t(x)\Bigr)$$
program AdaBoost
{ Zayıf öğrenici (tek eşikli "karar kütükleri") ağırlıklı oylamayla güçlü bir sınıflandırıcıya dönüşür.
Her turda yanlış sınıflanan örneklerin ağırlığı artar; sonraki kütük onlara odaklanır.
α_t = ½ · ln((1 − hata) / hata) F(x) = işaret(Σ α_t · h_t(x)) }
kullan Matematik
tip
Kütük = kayıt eşik: ondalık; yön: tamsayı; alfa: ondalık; bitir { h(x) = yön, x < eşik ise; −yön değilse }
değişken
X, D: ondalık dizisi
Y: tamsayı dizisi
kütükler: Kütük dizisi
i, t, n, isabet: tamsayı
k, enK: Kütük
hata, enHata, z: ondalık
fonksiyon H(k: Kütük; x: ondalık): tamsayı
başla
sonuç := eğer x < k.eşik ise k.yön değilse -k.yön
bitir
fonksiyon Güçlü(x: ondalık): tamsayı
değişken s: ondalık; j: tamsayı
başla
s := 0
0'dan Uzunluk(kütükler) - 1'e kadar her j için s := s + kütükler[j].alfa * H(kütükler[j], x)
sonuç := eğer s >= 0 ise 1 değilse -1
bitir
başla
{ Tek bir eşik bu veriyi ayıramaz: + + + − − − − + + + }
X := [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Y := [1, 1, 1, -1, -1, -1, -1, 1, 1, 1]
n := Uzunluk(X)
D := Eşle(X, fonksiyon(x: ondalık) => 1.0 / n) { başlangıçta tüm örnekler eşit ağırlıkta }
kütükler := []
1'den 4'e kadar her t için
başla
enHata := 2
{ en düşük ağırlıklı hatayı veren eşik ve yönü ara }
0'dan n'e kadar her i için
[1, -1] içindeki her yön için
başla
k := Kütük.Oluştur(i + 0.5, yön, 0)
hata := 0
0'dan n - 1'e kadar her j için eğer H(k, X[j]) <> Y[j] ise hata := hata + D[j]
eğer hata < enHata ise başla enHata := hata; enK := k bitir
bitir
k := enK
k.alfa := 0.5 * Ln((1 - enHata) / enHata)
kütükler.Ekle(k)
{ ağırlıkları güncelle: yanlışlar ×e^α, doğrular ×e^−α, sonra toplam 1 olacak şekilde ölçekle }
0'dan n - 1'e kadar her j için D[j] := D[j] * Üstel(-k.alfa * Y[j] * H(k, X[j]))
z := Toplam(D)
0'dan n - 1'e kadar her j için D[j] := D[j] / z
isabet := 0
0'dan n - 1'e kadar her j için eğer Güçlü(X[j]) = Y[j] ise isabet := isabet + 1
yaz(Biçimle('Tur {}: x < {:4} ise {:2} hata = {:.3} α = {:.3} topluluk doğruluğu: {}/{}',
t, k.eşik, k.yön, enHata, k.alfa, isabet, n), 1)
yaz(' ağırlıklar: ' + Eşle(D, fonksiyon(d: ondalık) => Yuvarla(d, 2)), 1)
bitir
bitir.Programın çıktısı şöyledir:
Tur 1: x < 3.5 ise 1 hata = 0.300 α = 0.424 topluluk doğruluğu: 7/10
ağırlıklar: [0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.17, 0.17, 0.17]
Tur 2: x < 7.5 ise -1 hata = 0.214 α = 0.650 topluluk doğruluğu: 7/10
ağırlıklar: [0.17, 0.17, 0.17, 0.05, 0.05, 0.05, 0.05, 0.11, 0.11, 0.11]
Tur 3: x < 0.5 ise -1 hata = 0.182 α = 0.752 topluluk doğruluğu: 10/10
ağırlıklar: [0.1, 0.1, 0.1, 0.12, 0.12, 0.12, 0.12, 0.06, 0.06, 0.06]
Tur 4: x < 3.5 ise 1 hata = 0.194 α = 0.711 topluluk doğruluğu: 10/10
ağırlıklar: [0.06, 0.06, 0.06, 0.08, 0.08, 0.08, 0.08, 0.17, 0.17, 0.17]Ne öğrendik. İlk kütük sağdaki üç noktayı kaçırdı; ağırlıkları 0,07’den 0,17’ye çıktı ve ikinci kütük tam onları doğru sınıflandırdı. Tek başına en fazla %70 isabet eden üç kütük, birlikte 10 noktanın hepsini doğru sınıflandırıyor. Gürültülü etiketler AdaBoost’un zayıf noktasıdır: yanlış etiketli bir örneğin ağırlığı her turda büyür.
Alıştırma. Y listesindeki bir etiketi bilerek ters çeviriniz ve 10 tur çalıştırınız. O örneğin ağırlığını izleyiniz.
15. XGBoost
Fikir. XGBoost, gradyan artırmanın hızlı ve düzenlileştirilmiş bir sürümüdür. Kaybın yalnızca eğimini (g) değil eğriselliğini de (h, ikinci türev) kullanır; böylece her yaprağın en iyi değeri tek bir formülle bulunur. λ yaprak değerlerini küçülterek aşırı uyumu engeller; γ yeterince kazanç getirmeyen bölmeleri yasaklar.
$$w^* = -\frac{G}{H + \lambda}, \qquad \text{kazanç} = \tfrac{1}{2}\Bigl[\frac{G_L^2}{H_L+\lambda} + \frac{G_R^2}{H_R+\lambda} - \frac{G^2}{H+\lambda}\Bigr] - \gamma$$
program XGBoost
{ XGBoost'un çekirdeği: kaybın birinci (g) ve ikinci (h) türevini kullanan, düzenlileştirilmiş artırma.
Lojistik kayıpta p = σ(F) için: g = p − y, h = p·(1 − p) (kodda grad ve hess dizileri)
Yaprak ağırlığı: w = −G / (H + λ) Bölmenin kazancı:
kazanç = ½ [G_L²/(H_L+λ) + G_R²/(H_R+λ) − G²/(H+λ)] − γ (kazanç ≤ 0 ise bölme yapılmaz) }
kullan Matematik
değişken
X: ondalık dizisi
Y: tamsayı dizisi
i: tamsayı
prosedür Eğit(lam, gama: ondalık)
değişken
F, grad, hess: ondalık dizisi
t, j, n, enEşik: tamsayı
GL, HL, GR, HR, G, H, kazanç, enKazanç, wL, wR, kayıp, p: ondalık
başla
n := Uzunluk(X)
F := Eşle(X, fonksiyon(x: ondalık) => 0.0)
yaz(Biçimle('λ = {}, γ = {}', lam, gama), 1)
1'den 4'e kadar her t için
başla
grad := []; hess := []
0'dan n - 1'e kadar her j için
başla
p := Sigmoid(F[j]); grad.Ekle(p - Y[j]); hess.Ekle(p * (1 - p))
bitir
G := Toplam(grad); H := Toplam(hess)
enKazanç := 0; enEşik := 0
1'den n - 1'e kadar her i için { eşik: X[i-1] ile X[i] arası }
başla
GL := 0; HL := 0
0'dan i - 1'e kadar her j için başla GL := GL + grad[j]; HL := HL + hess[j] bitir
GR := G - GL; HR := H - HL
kazanç := 0.5 * (GL * GL / (HL + lam) + GR * GR / (HR + lam) - G * G / (H + lam)) - gama
eğer kazanç > enKazanç ise başla enKazanç := kazanç; enEşik := i bitir
bitir
eğer enKazanç <= 0 ise
başla
yaz(' Tur ' + t + ': hiçbir bölme γ cezasını karşılamıyor, ağaç büyümüyor', 1)
kır
bitir
GL := 0; HL := 0
0'dan enEşik - 1'e kadar her j için başla GL := GL + grad[j]; HL := HL + hess[j] bitir
wL := -GL / (HL + lam); wR := -(G - GL) / (H - HL + lam)
kayıp := 0
0'dan n - 1'e kadar her j için
başla
F[j] := F[j] + 0.5 * (eğer j < enEşik ise wL değilse wR) { 0.5: küçültme (shrinkage) }
p := Sigmoid(F[j])
kayıp := kayıp - (Y[j] * Ln(p) + (1 - Y[j]) * Ln(1 - p)) / n
bitir
yaz(Biçimle(' Tur {}: x < {:4.1} | kazanç {:.3} | yapraklar {:6.3} / {:6.3} | kayıp {:.4}',
t, (X[enEşik - 1] + X[enEşik]) / 2, enKazanç, wL, wR, kayıp), 1)
bitir
bitir
başla
{ Müşterinin yaşı (sıralı) ve ürünü satın alıp almadığı }
X := [18, 22, 25, 28, 31, 35, 38, 42, 46, 50, 55, 60]
Y := [0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1]
Eğit(0, 0)
Eğit(5, 0)
Eğit(5, 0.8)
bitir.Programın çıktısı şöyledir:
λ = 0.0, γ = 0.0
Tur 1: x < 26.5 | kazanç 2.722 | yapraklar -2.000 / 1.111 | kayıp 0.5110
Tur 2: x < 33.0 | kazanç 1.252 | yapraklar -1.023 / 0.957 | kayıp 0.4290
Tur 3: x < 26.5 | kazanç 0.493 | yapraklar -1.221 / 0.439 | kayıp 0.3962
Tur 4: x < 52.5 | kazanç 0.318 | yapraklar -0.208 / 1.285 | kayıp 0.3755
λ = 5.0, γ = 0.0
Tur 1: x < 33.0 | kazanç 0.580 | yapraklar -0.240 / 0.370 | kayıp 0.6428
Tur 2: x < 26.5 | kazanç 0.476 | yapraklar -0.245 / 0.309 | kayıp 0.6023
Tur 3: x < 33.0 | kazanç 0.395 | yapraklar -0.214 / 0.285 | kayıp 0.5696
Tur 4: x < 26.5 | kazanç 0.324 | yapraklar -0.217 / 0.239 | kayıp 0.5431
λ = 5.0, γ = 0.8
Tur 1: hiçbir bölme γ cezasını karşılamıyor, ağaç büyümüyorNe öğrendik. λ = 0 iken yaprak değerleri ±2’ye kadar çıktı ve 4. turda model 50 yaşındaki tek “hayır” için ayrı bir bölme açtı: gürültüyü kovalamaya başladı. λ = 5 yaprakları ±0,3 civarında tuttu ve model yalnızca iki anlamlı eşiği (26,5 ve 33) kullandı. γ = 0,8 ise hiçbir bölmenin bu kadar kazanç getirmediğine karar verdi. Gerçek XGBoost bunlara ek olarak derin ağaçlar, özellik örnekleme ve paralel hesap kullanır; fikir aynıdır.
Alıştırma. Eğit(1, 0.1) ekleyiniz ve sonucu üç çalıştırmayla karşılaştırınız. Hangi ayar, verideki gerçek deseni (yaş ~30’dan sonra satın alım) en iyi yakalıyor?