LightGBM(ライトジービーエム)は、Microsoftが開発した勾配ブースティング決定木(GBDT)のオープンソース実装です。浅い決定木を1本ずつ足し、前の木が外した分を次の木で埋めていく学習を、表形式データ向けに高速化しています。最新版は2026年7月18日にPyPIで公開された4.7.0で、Python 3.10以上が必要です。
この記事では、勾配ブースティングの手順を3件の数値例で追ったうえで、4.7.0で変わったfitの書き方、n_estimatorsとlearning_rateの決め方、leaf-wise成長で木が実際どこまで深くなるかを、手元で実行した結果つきで説明します。
まとめ:LightGBMの要点と4.7.0で変わったこと
- 正体:勾配ブースティング決定木の実装。MIT Licenseで商用利用も無料です。リポジトリは4.7.0で
microsoftからlightgbm-orgへ移りました。 - 速さの理由:特徴量をビン(既定255個)にまとめて分岐を探し、損失が最も減る葉から伸ばすleaf-wise成長を採ります。論文ではGOSSとEFBで従来のGBDTより最大20倍超速いと報告されています。
- 4.7.0の変更:scikit-learn APIの
eval_setは非推奨になり、eval_Xとeval_yで検証データを渡します。fit(early_stopping_rounds=...)はTypeErrorで、早期終了はcallbacksで指定します。 - n_estimators:既定の100本では足りないことが多く、上限を大きく置いて早期終了に本数を決めさせます。実測では
learning_rate=0.1で616本、0.01で6,047本が最適でした。 - 選ばない場面:学習データの範囲外を予測する用途(外挿)では、予測値が範囲の端で止まります。行数が少ないこと自体は避ける理由になりませんでした。
勾配ブースティングの仕組み:残差を少しずつ埋める手順
勾配ブースティングは、Friedmanが2001年にAnnals of Statisticsで定式化した手法です。予測モデルを「最初の予測値+木1の出力×学習率+木2の出力×学習率+…」という足し算で作ります。各木は、その時点の予測がどれだけ外れているかを学習します。
3件の数値例で見る1ラウンドの更新
家賃を予測する例で、正解が8万円・10万円・12万円の3件とします。
- 最初の予測は全件の平均の10万円です。外れ(残差)は−2万円・0円・+2万円になります。
- 1本目の木は、この残差−2・0・+2を当てるように分岐を作ります。ここでは完全に当てたとします。
- 木の出力に学習率0.1を掛けて足します。予測は9.8万円・10万円・10.2万円になり、残差は−1.8・0・+1.8に縮みます。
- 2本目の木は新しい残差−1.8・0・+1.8を学習し、同じ手順を繰り返します。
学習率を掛けるのは、各木が予測を更新する幅を小さくし、学習の進み方を抑える正則化のためです。学習率を下げると必要な木の本数が増えます。学習率と本数の関係は後の章で実測します。
勾配ブースティングの名称:二乗誤差の負の勾配と残差の関係
損失を二乗誤差 (y−F)²/2 とすると、予測値Fで微分した負の勾配は y−F で、残差そのものです。勾配ブースティングは「損失を減らす方向(負の勾配)を木で近似して一歩進む」操作を繰り返す、関数の空間での勾配降下として説明されます。二値分類の対数損失なら負の勾配は「正解ラベル−予測確率」になり、回帰と同じ枠組みで扱えます。
ランダムフォレストも決定木を多数使いますが、木を互いに独立に作って平均するバギングです。勾配ブースティングは前の木の結果に依存して直列に木を足す点が違います。決定木そのものの分岐の作り方は決定木分析とは?分類木・回帰木の仕組みと過学習を防ぐ剪定・アンサンブルを実装目線で解説で扱っています。
LightGBMが速い理由:ヒストグラム・leaf-wise・GOSS・EFB
LightGBMの論文(Ke et al., NIPS 2017)は、既存のGBDT実装が分岐点を探すたびに全データを走査する点を問題とし、GOSSとEFBを提案しました。要旨では、従来のGBDTより学習を最大20倍超速くしつつ、精度はほぼ同等と報告しています。
leaf-wise成長の実測:num_leaves=31で分岐段数の中央値10段
公式のFeaturesによると、LightGBMは木をleaf-wise(best-first)に成長させ、損失の減少が最大の葉を選んで分割します。XGBoostの既定(grow_policy=depthwise)は、同じ深さのノードを全部分割してから次の段に進むlevel-wise(depth-wise)です。葉の数をそろえた場合、leaf-wiseのほうが損失を下げやすいとされています。
その代わり、木は片側に偏って深くなります。4万行40列のデータで既定のnum_leaves=31のまま100本学習し、各木の深さをtrees_to_dataframe()で数えた結果が次の表です。
| 設定 | 分岐の段数 | 葉の数 |
|---|---|---|
| num_leaves=31(max_depth=-1) | 最小7・中央値10・最大16 | 31 |
| num_leaves=31, max_depth=5 | 最大5 | 中央値31 |
| 均等に育てた場合(理論値) | 5 | 31 |
葉が31枚なら均等な木は5段で収まりますが、leaf-wiseでは最大16段まで伸びました。深い枝は少数の行だけを説明するので、データが少ないと過学習の原因になります。公式はmax_depthを指定しても成長方式はleaf-wiseのままだと明記しており、max_depthは上限を切るだけです。
ヒストグラムによる分岐探索:max_binの既定は255
連続値の特徴量を、学習前に最大255個のビン(max_bin)へまとめます。分岐の候補がビンの境目だけになるため、候補の数とメモリが減ります。max_binを上げると細かい分岐を拾えますが、学習は遅くなります。
GOSSの設定:4.0.0で追加されたdata_sample_strategy
GOSS(Gradient-based One-Side Sampling)は、勾配の大きい行を残し、勾配の小さい行だけを間引くサンプリングです。Parametersの既定では、勾配の大きい上位20%(top_rate=0.2)を全件残し、残りの行から全体の10%に相当する件数(other_rate=0.1)を抽出し、抽出した小勾配側の勾配とヘッセ行列の成分を補正します。
data_sample_strategyの既定はbaggingで、GOSSは指定したときだけ使われます。指定方法は4.0.0で変わり、boosting="goss"ではなくdata_sample_strategy="goss"と書きます。4.7.0のboostingの選択肢はgbdt・rf・dartの3つです。なお、上と同じ4万行のデータで1,000本学習したところ、GOSSありは8.19秒(AUC 0.9715)、なしは7.16秒(AUC 0.9710)で、速くなりませんでした。この4万行の生成データではGOSSによる高速化は確認できませんでした。大規模データでも効果は特徴量や設定に依存するため、対象データで学習時間と精度を比較します。
EFBの仕組み:同時に非ゼロになりにくい特徴量の束ね方
EFB(Exclusive Feature Bundling)は、One-Hotエンコーディング後の列のように、同時に非ゼロになることがまれな特徴量を1つに束ねて列数を減らします。論文は最適な束ね方の探索がNP困難であることを示したうえで、貪欲法で近似しています。GOSSが行を、EFBが列を減らす分担です。
LightGBMをPythonで動かす:4.7.0のeval_Xとearly stopping
掲載コードの実行にはLightGBMとscikit-learnが必要です。検証に使った版はpip install lightgbm==4.7.0 scikit-learn==1.9.1で指定できます。macOSでは公式READMEのとおり、brew install libompでOpenMPを入れておきます。scikit-learn互換のLGBMClassifier・LGBMRegressorを使う場合、4.7.0では検証データをeval_Xとeval_yに分けて渡します。
import lightgbm as lgb
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
X, y = load_breast_cancer(return_X_y=True)
X_train, X_valid, y_train, y_valid = train_test_split(
X, y, test_size=0.2, random_state=42
)
model = lgb.LGBMClassifier(
n_estimators=500, # 上限。実際の本数は早期終了で決まる
learning_rate=0.05,
num_leaves=31,
verbose=-1,
)
model.fit(
X_train, y_train,
eval_X=(X_valid,), # 4.7.0から。複数ならタプルに並べる
eval_y=(y_valid,),
callbacks=[lgb.early_stopping(stopping_rounds=20)],
)
print(model.best_iteration_) # 114(この環境での実行結果)
このコードを古い書き方と比べて実行した結果は次のとおりです(Python 3.13.14・lightgbm 4.7.0・scikit-learn 1.9.1)。
eval_set=[(X_valid, y_valid)]は学習自体は通りますが、LGBMDeprecationWarning: The argument 'eval_set' is deprecated, use 'eval_X' and 'eval_y' instead.が出ます。4.7.0のリリースノートにも「add eval_X, eval_y, deprecate eval_set」とあります。eval_X=[X_valid]のようにリストで渡すとTypeError: Wrong type(list) for label.で止まります。単体で渡すかタプルにします。fit(early_stopping_rounds=20)はTypeErrorです。古い記事のコードを写すと、ここで止まります。- 早期終了した後の
predict_probaは、何も指定しなくてもbest_iteration_本目までの木で予測しました(num_iteration=best_iteration_を指定した結果と一致)。
早期終了に使う検証データをテスト評価にも流用すると、スコアが楽観的にずれます。分割の設計は交差検証とは?分割手法の選び方とデータリーク対策を実装目線で解説【2026年版】を参照してください。
n_estimatorsの調整:learning_rateと早期終了による反復回数の選択
n_estimatorsはブースティングの反復回数です。通常の回帰・二値分類では木の本数と一致しますが、多クラス分類では1反復でクラス数分の木を作ります。LightGBM本体のパラメータ名はnum_iterationsです。Parametersではnum_boost_round・num_trees・n_estimatorsなどが同じ値のエイリアスとして並んでおり、既定は100です。
最適な本数は学習率でまったく変わります。make_classificationで生成した6万行40列の二値分類データ(n_informative=12、n_redundant=8、flip_y=0.05、class_sep=0.8、random_state=0)を、random_state=0でテスト1万行、続いて検証1万行に分割し、残り4万行を学習に使いました。上限は1万反復とし、検証データのbinary_loglossが50ラウンド改善しなければ打ち切りました。表の「最適な本数」は、この条件で選ばれたbest_iteration_を指し、テストAUCを最大化した本数ではありません。
| learning_rate | 最適な本数 | 学習時間 | テストAUC |
|---|---|---|---|
| 0.3 | 178 | 2.02秒 | 0.9706 |
| 0.1 | 616 | 5.80秒 | 0.9716 |
| 0.05 | 1,348 | 10.69秒 | 0.9717 |
| 0.01 | 6,047 | 49.18秒 | 0.9721 |
| 0.1(既定の100本で固定) | 100 | 1.13秒 | 0.9674 |
読み取れることは2つです。まず、既定の100本はlearning_rate=0.1でも最適の6分の1しかなく、AUCが0.004低くなりました。n_estimatorsは既定のまま使わず、上限を数千に置いて早期終了に任せます。次に、学習率を0.1から0.01に下げると本数と時間は約10倍になりましたが、AUCの差は0.0005でした。試行を回す段階は0.1か0.05で進め、最終モデルだけ学習率を下げるのが時間に見合う使い方です。
学習率と本数以外のパラメータまで探索するなら、Optunaとは?v5.0の既定TPE変更と枝刈り・並列実行を実装目線で解説のように探索を自動化します。
num_leavesと過学習:既定値と実測
LightGBMで木の複雑さを決める主なパラメータはnum_leavesです。v4.7.0の既定値は次のとおりです。
| パラメータ | 既定値 | 主なエイリアス |
|---|---|---|
| num_leaves | 31 | max_leaves, max_leaf_nodes |
| max_depth | -1(無制限) | なし |
| min_data_in_leaf | 20 | min_child_samples |
| learning_rate | 0.1 | eta, shrinkage_rate |
| num_iterations | 100 | n_estimators, num_boost_round |
| max_bin | 255 | max_bins |
scikit-learn APIではmin_data_in_leafをmin_child_samplesという名前で受け取ります。公式のチューニングガイドは、max_depthを指定するならnum_leavesを2^max_depth以下にし、例としてmax_depth=7のときnum_leaves=127は過学習しうるが70〜80なら均等な木より精度が出ることがある、と書いています。
同じ4万行のデータで、本数を300本・学習率0.1に固定してnum_leavesだけ変えた結果です。
| num_leaves | 学習AUC | テストAUC | 学習時間 |
|---|---|---|---|
| 7 | 0.9701 | 0.9634 | 1.21秒 |
| 31 | 0.9963 | 0.9700 | 2.52秒 |
| 127 | 1.0000 | 0.9727 | 7.31秒 |
| 511 | 1.0000 | 0.9736 | 26.29秒 |
| 2047 | 1.0000 | 0.9734 | 46.93秒 |
num_leaves=127で学習AUCは1.0に張り付きましたが、テストAUCは511まで上がり続けました。学習データへの当てはまりが完全になったことだけを根拠にnum_leavesを下げると、精度を取りこぼします。設定値は検証データのスコアと学習時間で選びます。この表はテストAUCの比較なので、ここから127〜511を採用範囲として選ぶことはできません。行数が少なく検証スコアがnum_leavesを上げるほど下がる場合は、min_child_samplesを増やすかmax_depthで上限を切ります。
XGBoost・CatBoost・ランダムフォレストとの違い
同じ決定木ベースでも、木の育て方とカテゴリ変数の扱いが違います。
| 手法 | 木の足し方 | 既定の成長方式 | カテゴリ変数 |
|---|---|---|---|
| LightGBM | 直列(ブースティング) | leaf-wise | category型をそのまま扱える |
| XGBoost | 直列(ブースティング) | depthwise | enable_categoricalで対応 |
| CatBoost | 直列(ブースティング) | 対称木 | cat_features指定で統計量化・One-Hot化 |
| ランダムフォレスト | 並列(バギング) | 各木を独立に構築 | 数値化が必要 |
XGBoostとの差は成長方式が中心です。XGBoostもgrow_policy="lossguide"を指定すればleaf-wiseで育てられるため、方式の違いは既定値の違いと言えます。LightGBM・XGBoost・CatBoostに旧来のscikit-learn実装を加えた4実装の速度と精度の比較はGBDTとは?勾配ブースティング決定木の仕組みと主要4実装の実測比較【2026年版】で実測しています。CatBoostの対称木とカテゴリ処理はCatBoostとは?仕組みの図解・XGBoost/LightGBMとの違いとPython実装【1.2.10】で詳しく扱っています。
LightGBMを選ばない場面:外挿の実測と少量データの実際
明確に向かないのは、学習データの範囲外を予測する用途です。xを0〜10の範囲で一様に取り、y=2x+ノイズを2,000行学習させてから予測しました。
| x | 正解 | 既定 | linear_tree=True |
|---|---|---|---|
| 5 | 10 | 9.906 | 9.923 |
| 10 | 20 | 19.983 | 20.211 |
| 12 | 24 | 19.983 | 28.002 |
| 20 | 40 | 19.983 | 59.167 |
既定では範囲の端の値19.983で止まります。linear_tree=Trueにすると葉ごとに線形モデルを当てるので値は伸びますが、x=20で59.167と正解の40を大きく超えました。売上の伸びや価格の上昇トレンドのように、将来の値が過去の範囲を出る予測では、線形モデルや時系列モデルを主にし、LightGBMは残差の補正に回す構成にします。
一方、「行数が少ないから使えない」とは言い切れませんでした。同じ生成条件のデータを200行と1,000行で作り、5分割交差検証のAUCを3回平均したところ、200行ではLightGBM(既定値)0.8579、ランダムフォレスト0.8569、ロジスティック回帰0.8174で、LightGBMが下回ることはありませんでした。小さなデータで確かめるべきなのは行数そのものより、交差検証のばらつきと、min_child_samples(既定20)が葉を作れないほど行数が少なくないかです。
予測根拠の説明が監査で求められる業務では、特徴量の寄与をSHAPで示せるかを事前に確かめます(モデル解釈性とは?説明可能性との違いとSHAP・LIMEの選び方を実装目線で解説)。画像・音声・自然文を直接入力する用途ではニューラルネットワークを候補にします。数値特徴量や埋め込みに変換してから、決定木ベースのモデルに入力する構成も比較できます。需要予測や離脱予測のモデルを業務システムに組み込むところまで外部に任せる場合は、一想の機械学習モデル開発で要件整理から相談できます。
よくある質問
LightGBMは無料で使えますか?
はい。LightGBMはMIT Licenseのオープンソースで、商用利用も含めて無料です。著作権表示にはMicrosoft CorporationとThe LightGBM developersの両方が含まれます。ソフトウェアのコピーまたは実質的な部分には、これらの著作権表示と許諾表示を含める必要があります。
LightGBMの読み方は何ですか?
「ライトジービーエム」と読みます。GBMはGradient Boosting Machine(勾配ブースティングマシン)の略です。
LightGBMとXGBoostはどちらを使うべきですか?
どちらも勾配ブースティング決定木の実装ですが、既定の成長方式に加えて、カテゴリ変数の処理や利用できる設定にも違いがあります。既存のコードや運用環境がある方を優先し、新規ならLightGBMで基準を作ってからXGBoostと検証スコアを比べる進め方が手戻りの少ない順番です。
n_estimatorsとnum_iterationsとnum_boost_roundは何が違いますか?
同じパラメータの別名です。scikit-learn APIではn_estimators、lgb.train()ではnum_boost_round引数、パラメータ辞書ではnum_iterationsと書くのが一般的です。既定はいずれも100反復で、多クラス分類では木の総数はクラス数×反復回数になります。
LightGBMとランダムフォレストの違いは何ですか?
ランダムフォレストは木を独立に作って平均するバギング、LightGBMの標準的なブースティングは、それまでのモデル全体の予測に対する損失の勾配などを使って、次の木を追加します。ランダムフォレストは本数を増やしても過学習しにくい一方、LightGBMでは反復回数も調整対象です。早期終了のほか、交差検証で反復回数を選ぶ方法もあります。