LightGBM
LightGBM は、小さな決定木を順番に何本も作り、前の木の誤差を補いながら予測を改善していく勾配ブースティングの手法です。各木の出力を足し合わせて最終予測とし、高速で精度が出やすいため、表形式データの分類・回帰でよく使われます。
記号と意味
| 記号 | 由来 | 意味 |
|---|---|---|
| $g_i$ | gradient | データ 1 件ごとの勾配(損失の1階微分) |
| $G$ | gradient の合計 | ノード内の $g_i$ の和 |
| $h_i$ | hessian | データ 1 件ごとの 2 階微分 |
| $H$ | hessian の合計 | ノード内の $h_i$ の和 |
| $Gain$ | gain(利得) | 分割による損失の減少量 |
| $F_i$ | function | データ $i$ の生の予測スコア(シグモイドを通す前のロジット) |
| $p_i$ | probability | 予測確率(犬である確率)。$p_i=\sigma(F_i)$ |
| $w$ | weight | リーフ値(leaf value / leaf weight、葉の重み)。リーフが持つ補正値で、$w=-\dfrac{G}{H+\lambda}$ |
| $\eta$ | eta | 学習率(learning rate、shrinkage)。LightGBM では learning_rate。$\eta w$ が $F_i$ に足される量 |
| $\lambda$ | lambda | L2 正則化の強さ(regularization)。LightGBM では reg_lambda(デフォルト 0)。$w=-\dfrac{G}{H+\lambda}$ の分母に入り、大きいほど $w$ が 0 に近づく |
データごとの量とノード・リーフごとの量
$F_i$ や $g_i$ は、データ 1 件(犬 1 匹・猫 1 匹)ごとに 1 つずつ定義されます。
10 件のデータ $x_1,\dots,x_{10}$ なら、$i=1,\dots,10$ に対して 10個 ずつあります。
| 単位 | 記号 | 例(10件のとき) |
|---|---|---|
| データ 1 件ごと | $x_i$、$y_i$、$F_i$、$p_i$、$g_i$、$h_i$ | それぞれ10個 |
| ノードごと | $G$、$H$ | そのノードに入ったデータの合計 |
| リーフごと | $w$ | リーフの数だけ(例:2個) |
$G_j$($j$ ノードの $G$)
\[G_j=\sum_{i\in\text{ノード }j}g_i\]- $x_i$ は特徴量で $x_i=(\text{体重},\ \text{耳立ち},\ \text{鼻の長さ})$ のようにベクトルです
- $F_i$ は、木を 1 本作るたびに、データごとに更新されます。同じリーフに入ったデータには、同じ値 $\eta \times w$(learning rate $\times$ leaf weight)が足されます
- 同じリーフに入ったデータは $F_i$ と $p_i$ が同じ値になりますが、$g_i=p_i-y_i$ は $y_i$ が違えば別の値になります(犬と猫で符号が逆)
$g_i$ の意味
$g_i$ は、予測確率と正解ラベルの差です。
\[g_i = p_i - y_i\]- $p_i$:データ $i$ が犬である確率の予測です。犬を $y=1$ としているので、猫のデータでも犬の確率を使います
- $y_i$:正解ラベル(犬なら 1、猫なら 0)です
勾配と呼ぶのは、損失(log loss)をロジット $F_i$ で微分した値が、計算すると $p_i-y_i$ になるためです。
\[g_i=\frac{\partial L_i}{\partial F_i}=p_i-y_i\]確率 $p_i$ で微分しているのではなく、$F_i$ で微分している点が、勾配 の正確な意味です。
2 階微分 $h_i$ は、同じ損失を $F_i$ でもう一度微分した値です。
\[h_i=\frac{\partial^2 L_i}{\partial F_i^2}=p_i(1-p_i)\]$F_i$ の意味
$F_i$ は、モデルの生の出力(スコア)で、シグモイドで確率にする前の値(ロジット)です。
初期値 $F_0$ に、各木で $x_i$ が着いたリーフ値($\eta \times w$)を足し合わせたものです。
| 部分 | 意味 |
|---|---|
| $m$ | 木の番号($m$ 本目の木) |
| $\text{leaf}_m(x_i)$ | $m$ 本目の木で、データ $x_i$ が最終的に着くリーフ |
| $w^{(m)}_{\text{leaf}_m(x_i)}$ | $m$ 本目の木の、そのリーフが持つ値 |
| $\sum_{m=1}^{M}$ | 1本目から $M$ 本目までの木の値を足し合わせる |
- $F_i$ はデータごとに 1 つあり、値の範囲に制限はありません
- $F_i$ が大きいほど犬($y=1$)らしく、小さい(負)ほど猫らしいことを表します($F_i=0$ のとき $p=0.5$)
- 木を 1 本作るたびに、$F_i \leftarrow F_i + \eta w$ と更新されます
| 記号 | 意味 | 範囲 |
|---|---|---|
| $F_i$ | データ $i$ の予測スコア(ロジット) | 実数全体 |
| $p_i=\sigma(F_i)$ | 予測確率 | 0 〜 1 |
| $F_0$ | 初期値(正例の割合のロジット) | 実数全体(正例の割合が 0.5 なら 0、0.5 より大きければ正、小さければ負) |
| $w$ | リーフ値(木1本のリーフの出力) | 実数全体(犬が多いリーフは正、猫が多いリーフは負) |
| $\eta w$ | 学習率を掛けた、$F_i$ に足される量 | 実数全体($0<\eta\le1$ なので、$w$ より 0 に近い値になる) |
大文字の $F$ は、勾配ブースティングの論文で、モデル全体を関数 $F(x)$ と書く慣習から来ています。木 1 本の出力は小文字の $f_m(x)$ で、足し合わせた全体が $F(x)$ です($F_m(x)=F_{m-1}(x)+\eta f_m(x)$)。
損失(log loss)は交差エントロピー
2 値分類の log loss は、交差エントロピー(二値交差エントロピー、binary cross-entropy)です。
1件のデータの損失は、次のとおりです。
\[L_i=-\left\{y_i\log p_i+(1-y_i)\log(1-p_i)\right\}\]正解の分布 $q=(y_i,\ 1-y_i)$ と、予測の分布 $p=(p_i,\ 1-p_i)$ の交差エントロピー $-\sum_k q_k\log p_k$ です。
| 正解 | 損失 |
|---|---|
| 犬($y_i=1$) | $-\log p_i$ |
| 猫($y_i=0$) | $-\log(1-p_i)$ |
たとえば犬で $p_i=0.75$ なら、$L_i=-\log0.75\approx0.29$(自然対数)です。
全データの log loss は、$L_i$ の平均です。
\[\frac1n\sum_{i=1}^{n}L_i\]呼び方の違い
| 呼び方 | 使われる場面 |
|---|---|
| log loss(対数損失) | scikit-learn、LightGBM、Kaggle の評価指標 |
| 交差エントロピー | 情報理論、ニューラルネットの文脈 |
| binary cross-entropy | 2 クラスの場合 |
| 負の対数尤度 | 統計学の文脈 |
2 値分類では、どれも同じ式を指します。
複数クラスの場合は、多クラス交差エントロピー(categorical cross-entropy)になります。
補足
- 対数の底は、log loss(ライブラリ)では自然対数 $\ln$ が一般的です。決定木のエントロピーでは底 2 を使うことが多いです。底が違っても値は定数倍になるだけで、大小関係は変わりません
- 微分するときは $\ln$ を使うと、そのまま $g_i=p_i-y_i$ になります。
- LightGBM の 2 値分類のデフォルトの損失(
objective='binary')は、この log loss です。
分割ゲイン(split gain)
分割ゲインは、そのノードを分割したことで、損失がどれだけ減るかを表す値です。
具体的には、分割した場合の左右のリーフの改善量の合計から、分割しなかった場合の改善量を引いたもので、大きいほど良い分岐です。
| 記号 | 意味 |
|---|---|
| $G_L, G_R$ | 左右のノードに入ったデータの $g_i$ の合計 |
| $H_L, H_R$ | 左右のノードに入ったデータの $h_i$ の合計 |
| $\lambda$ | 正則化の強さ(reg_lambda、デフォルト 0) |
| $\gamma$ | 分割のペナルティ(LightGBM では min_gain_to_split が同様の働きをする) |
- 前の 2 項:分岐後の左右のリーフが、それぞれ損失を下げられる量
- 最後の項:分岐しなかった場合(親のまま)に下げられる量
- ゲインが大きいほど良い分岐で、最大のものを選ぶ
LightGBM の学習の流れ
全体の流れ
次の手順を、木の本数(n_estimators)だけ繰り返します。
- 初期値を置く:全データに同じ初期値 $F_0$(正例の割合のロジット)を与えます。
- $g_i, h_i$ を計算する:各データの $p_i=\sigma(F_i)$ から、$g_i=p_i-y_i$、$h_i=p_i(1-p_i)$ を求めます。
- 木の形を決める:特徴量と閾値の候補ごとに分割ゲインを計算し、最大のものを分岐条件として選びます。
- リーフ値を決める:形が決まった後、各リーフで $w=-\dfrac{G}{H+\lambda}$ を計算します。
- $F_i$ を更新する:データが入ったリーフの値を足します。$F_i \leftarrow F_i + \eta w$
- 次の木へ:更新後の $F_i$ から、2に戻って $g_i, h_i$ を計算し直します。
最終的な予測は、全部の木の出力を足し合わせて確率に変換し、0.5 で分類します。
\[F(x)=F_0+\eta\sum_{m}w^{(m)}_{\text{leaf}_m(x)},\qquad p=\sigma(F(x))\]押さえておくポイント
- 1本の木を作っている間、$g_i, h_i$ は固定されます。根でも、その下のノードでも、同じ値を使います。変わるのは、データが入るノードと、ノードの $G, H$ だけです。
- $g_i, h_i$ が変わるのは、木を作り終えて $F_i$ を更新した後です。
- 前の木は変更しません。 次の木は、更新後の $g_i, h_i$ から、新しく分岐を探して作ります。前の木と同じ分岐になるとは限りません。
- 分岐を選ぶ基準は分割ゲインで、リーフ値 $w$ は形が決まった後に計算します。どちらも $G, H$ から求めます。
- 同じリーフに入ったデータには、同じ値が足されます。 犬でも猫でも変わりません。
- 左右の件数が偏ってもかまいません。 5:5 でなく、3:7 になることもあります。最小件数は
min_child_samplesなどで制限できます。 - 特徴量と閾値で分けます。 $F_i$ や $p_i$ そのもので分けるわけではありません。狙いは、$g_i$ の向きがそろったデータを同じ側に集めることです。
決定木1本との違い
| 決定木1本 | LightGBM | |
|---|---|---|
| 木の数 | 1本 | 多数(n_estimators) |
| 分岐の基準 | 不純度の低下(ジニ不純度・エントロピー) | 分割ゲイン($G, H$ から計算) |
| リーフの値 | 多数派クラス(回帰なら平均値) | 補正値 $w$(数値) |
| 予測 | リーフで確定する | 全部の木の値を足して確率に変換する |
| 前の木との関係 | なし | 前の木までの誤差($g_i$)を材料に、次の木を新しく作る |
以下、犬猫の例で実際に計算します。
1本目の木
犬を $y=1$、猫を $y=0$ として、1本目の木を数値で追います。
設定
- 訓練データは犬 5・猫 5 の 10 件です。
- 木は
耳が立っている?で分け、左は犬 4・猫 1、右は犬 1・猫 4 です。 - $F_0=0$(正例の割合0.5のロジット)、$\lambda=0$、$\gamma=0$、
learning_rateは $\eta=0.1$ とします。
各データの $g_i, h_i$(全員 $p=0.5$)
| データ | $y$ | $g=p-y$ | $h=p(1-p)$ |
|---|---|---|---|
| 犬 | 1 | $-0.5$ | $0.25$ |
| 猫 | 0 | $+0.5$ | $0.25$ |
根の $G, H$
| 根(犬 5・猫 5) | |
|---|---|
| $G$ | $5(-0.5)+5(0.5)=0$ |
| $H$ | $10\times0.25=2.5$ |
分割後の $G, H$ とリーフ値
| 左(犬 4・猫 1) | 右(犬 1・猫 4) | |
|---|---|---|
| $G$ | $4(-0.5)+1(0.5)=-1.5$ | $1(-0.5)+4(0.5)=+1.5$ |
| $H$ | $5\times0.25=1.25$ | $1.25$ |
| $w=-G/H$ | $+1.2$ | $-1.2$ |
| $\eta w$ | $+0.12$ | $-0.12$ |
分割ゲイン
\[\frac12\left[\frac{(-1.5)^2}{1.25}+\frac{1.5^2}{1.25}-\frac{0^2}{2.5}\right]=\frac12(1.8+1.8)=1.8\]$F$ と予測確率の更新
| $F$ | $p=\sigma(F)$ | |
|---|---|---|
| 左の5件 | $0+0.12=0.12$ | 0.530 |
| 右の5件 | $0-0.12=-0.12$ | 0.470 |
$0.12$ の出どころ
$0.12$ は、1本目のリーフ値 $w$ に learning_rate($\eta=0.1$)を掛けた値です。
- 左リーフの $G=-1.5$、$H=1.25$ から、リーフ値は $w=-G/H=1.5/1.25=1.2$ です。
- $\eta=0.1$ を掛けて、$\eta w=0.1\times1.2=0.12$ です。
- これを $F$ に足します。$F=F_0+\eta w=0+0.12=0.12$ です。
- シグモイドで確率にします。$p=\sigma(0.12)\approx0.530$ です。
右のリーフも、$w=-1.5/1.25=-1.2$ なので、$\eta w=-0.12$、$F=-0.12$、$p=0.470$ となります。
1 本目の木の後の各データ(10件)
| $i$ | データ | $y_i$ | $F_i$ | $p_i$ | $g_i$ |
|---|---|---|---|---|---|
| 1 〜 4 | 左に入った犬 | 1 | 0.12 | 0.530 | $-0.470$ |
| 5 | 左に入った猫 | 0 | 0.12 | 0.530 | $+0.530$ |
| 6 | 右に入った犬 | 1 | $-0.12$ | 0.470 | $-0.530$ |
| 7 〜 10 | 右に入った猫 | 0 | $-0.12$ | 0.470 | $+0.470$ |
($i$ の番号の振り方は、説明のための例です。)
次の木で $g_i$ が変わる
変わるのは犬の $g_i$ だけではなく、猫の $g_i$ も変わります。
次の木のとき、左のリーフにいる5件の予測は $p=0.530$ です。
| データ | $y_i$ | $p_i=0.530$ のとき | 1本目 | 2本目($g=p-y$) |
|---|---|---|---|---|
| 犬 | 1 | $g=0.530-1=-0.470$ | $0.5-1=-0.5$ | $0.530-1=-0.470$ |
| 猫 | 0 | $g=0.530-0=+0.530$ | $0.5-0=+0.5$ | $0.530-0=+0.530$ |
仮に次の木でも左のリーフに同じ5件が入るなら、
\[G_{\text{左}}=4(-0.47)+1(+0.53)=-1.88+0.53=-1.35\]| となり、$-1.5$ から $-1.35$ に変わります($ | G | $ が小さくなります)。右のリーフも同様に、$G_{\text{右}}=1(-0.53)+4(+0.47)=+1.35$ です。 |
なぜこうなるか
- 犬は予測が $0.5$ から $0.530$ に近づいたので、誤差が小さくなりました。
- 猫は、同じリーフに犬が多いため $F$ が上がり、予測が正解の0から離れて、誤差が大きくなりました。
| 全体としては、犬4件の改善が猫1件の悪化を上回るので、$ | G | $ は小さくなります。この「$ | G | $ が小さくなる」というのが、損失が下がっていることの表れです。 |
まとめ
- $0.12$ は、$\eta\times w$ で、リーフ値に学習率を掛けたものです。
- $F$ が更新されると $p$ が変わり、$g_i=p_i-y_i$ も変わります。
- 犬の $g_i$ は $-0.5\to-0.47$ に変わり、猫は $+0.5\to+0.53$ と、逆向きに変わります。