LightGBMの実装方法を解説します。
params = {
"objective" : "regression",
"metric" : "rmse"
}
model = lgb.train(
params = params,
train_set = train_set,
valid_sets = [train_set, valid_set],
num_boost_round = 100
)
実装が簡単なわりに精度が高いのでベースラインモデルとして優秀です。

回帰モデル
A:〇〇万円です
こんな感じで連続した数値を予測するのが回帰モデルです。
load_boston
import pandas as pd
from sklearn.datasets import load_boston
data = load_boston()
df = pd.DataFrame(data["data"], columns = data["feature_names"])
df["target"] = data["target"]
print(df.shape)
df.head()
load_boston:住宅価格データセット
pandasの.DataFrameでデータを表に起こしましょう。
予測したい目的変数を”target”としました。

データ分割
モデルを作成する前にデータを分割します。
from sklearn.model_selection import KFold
kf = KFold(n_splits = 5, shuffle = True)
df["fold"] = -1
for fold, (train_idx, valid_idx) in enumerate(kf.split(df)):
df.loc[valid_idx, "fold"] = fold
print(df["fold"].value_counts())
KFoldはデータを等分に分割してくれます。n_splits = 5なので5分割です。
fold = 0
train = df.loc[df["fold"] != fold].copy()
valid = df.loc[df["fold"] == fold].copy()
print(train.shape, valid.shape)
今回は0番のデータを評価用にしました。
feat_cols = train.drop(columns = ["fold", "target"]).columns.tolist()
print(feat_cols)
X_train = train[feat_cols]
X_valid = valid[feat_cols]
y_train = train["target"]
y_valid = valid["target"]
予測に使う特徴量をX、予測したい”target”をyにしました。
“fold”と”target”は特徴として使いません。
モデル作成
モデル作成で必要なことは以下の通りです。
②Dataset形式に変換
③パラメータ設定
④trainで学習
まずLightGBMをインポートします。
import lightgbm as lgb
次にDatasetでLightGBM専用の形式に変換します。
学習データ(train)と評価データ(valid)の両方で変換しましょう。
train_set = lgb.Dataset(X_train, y_train)
valid_set = lgb.Dataset(X_valid, y_valid)
最後にパラメータ(学習条件)を辞書型データで設定しましょう。
params = {
"objective" : "regression",
"metric" : "rmse"
}
metric:モデルを評価する方法。”rmse”は平均二乗誤差の平方根。
パラメータはたくさんあります。
過学習を防ぐためには”num_leaves”などを設定することが有効です。
詳しくは公式ドキュメントを見ることをおススメします。
model = lgb.train(
params = params,
train_set = train_set,
valid_sets = [train_set, valid_set],
num_boost_round = 100
)
train_set:学習用データ
valid_sets:性能評価するデータ(metricで設定した指標で計算)
num_boost_round:モデルを改善する回数
LightGBMはnum_boost_roundの数だけ評価指標が改善されるようにモデルを作り直します。
実行すると以下ように、各学習でのモデル性能を出力します。

“training’s”が学習データでの、”valid_1’s”が評価データでの計算結果です。
予測結果
predictで予測できます。評価データ(valid)を渡しましょう。
pred = model.predict(X_valid)
print(pred)
printで予測結果を出力しました。正解データと比較してみましょう。
print(pred[:10])
print("=" * 100)
print(y_valid.values[:10])

y_validが正解データです。ボチボチ近い値を予測してそうですね。
では回帰タスクでよく使われる平均二乗誤差の平方根(RMSE)を計算しましょう。
from sklearn.metrics import mean_squared_error
import numpy as np
mse = mean_squared_error(y_valid, pred)
rmse = np.sqrt(mse)
print(rmse)
mean_squared_error(平均二乗誤差)をインポートしました。
正解データと予測値を入れると誤差を計算してくれます。np.sqrtで平方根にしましょう。
ランダム要素が入ってくるので必ずではありませんが、3~5くらいになると思います。
予測結果を可視化してみます。↓
import matplotlib.pyplot as plt
plt.scatter(y_valid, pred, alpha = 0.5)
x_line = np.linspace(0, 60, 100)
plt.plot(x_line, x_line, color = "red")
plt.show()

赤線はy = xの直線なので、この線上にあれば正確に予測できています。
いい感じですね。
学習状況可視化
result_data = {}
model = lgb.train(
params = params,
train_set = train_set,
valid_sets = [train_set, valid_set],
num_boost_round = 100,
evals_result = result_data
)
学習状況を保存するために新しく辞書型の”result_data”を作りました。
trainの引数”evas_result”に渡しましょう。
すると各回数目での学習結果が保存されます。
plt.plot(result_data["training"]["rmse"], color = "red", label = "train")
plt.plot(result_data["valid_1"]["rmse"], color = "blue", label = "valid")
plt.legend()
plt.show()

学習データの結果は”training”に評価データの結果は”valid_1″に入っています。
さらにその中にmetricで設定した指標である”rmse”があります。
赤が学習データでの結果で青が評価データでの結果ですね。
・評価データ(青)で頭打ちになっていないか
・学習データと評価データとの差がどれくらいか(データによる)
この辺りに注目するとよいかと思います。
EarlyStoppingRounds
評価データでのスコアが頭打ちになるとそれ以降の学習は時間のムダですよね。
そこで”early_stopping_rounds”を設定してみます。↓
result_data = {}
model = lgb.train(
params = params,
train_set = train_set,
valid_sets = [train_set, valid_set],
num_boost_round = 100,
early_stopping_rounds = 5,
verbose_eval = 50,
evals_result = result_data
)
引数”early_stopping_rounds”を数値で設定しましょう。
指定した回数だけ評価データの改善が見られなかった(ほぼ同じスコアだった)とき、学習を自動で止めてくれる機能です。
5回スコアの改善がなかったらストップするようにしました。
plt.plot(result_data["training"]["rmse"], color = "red", label = "train")
plt.plot(result_data["valid_1"]["rmse"], color = "blue", label = "valid")
plt.legend()
plt.show()

このようにしばらく改善が見られないと学習が止まります。
もちろん改善が続いていればnum_boost_roundの回数まで進みますよ。
・early_stopping_roundsを設定(だいたい10くらい)
で過不足のない学習ができるかと思います。
特徴量重要度
LightGBMでは予測における特徴量重要度を計算できます。
importance = model.feature_importance()
print(importance)
“feature_importance”で特徴量を計算できます。
数値のリストが出力されますが、これが特徴量重要度です。
importance_df = pd.DataFrame({"imoportance" : importance})
importance_df.index = feat_cols
importance_df.T

データフレームとして表にしました。
“LSTAT”が大きいですね。
plt.barh(width = importance_df.values.ravel(), y = importance_df.index)
plt.show()

このように棒グラフで可視化するとわかりやすいですね。
ただし、特徴量重要度にはいくつかの種類があります。
gain:目的変数への寄与度
splitだとカテゴリ特徴よりも数値特徴が重要になりやすいみたいです。(この辺は曖昧です)
“feature_importance”ではデフォルトでsplitの重要度を計算します。
gainを確認したい場合は引数”importance_type”を設定しましょう。
importance = model.feature_importance(importance_type = "split")
print(importance)
importance = model.feature_importance(importance_type = "gain")
print(importance)

下段がgainでの重要度です。
for t in ["split", "gain"]:
importance = model.feature_importance(importance_type = t)
importance_df = pd.DataFrame({"imoportance" : importance})
importance_df.index = feat_cols
plt.barh(width = importance_df.values.ravel(), y = importance_df.index)
plt.title(t)
plt.show()


全然違いますね。どちらにせよ”LSTAT”は重要そうです。
二値分類モデル
A:降る or 降らない
こんな感じで2択の分類をするのが二値分類です。
パラメータ設定まではほとんど回帰モデルと同じなので割愛して紹介しますね。
load_breast_cancer
import pandas as pd
from sklearn.datasets import load_breast_cancer
data = load_breast_cancer()
df = pd.DataFrame(data["data"], columns = data["feature_names"])
df["target"] = data["target"]
print(df.shape)
df.head()
load_breast_cancerをインポートしました。
病院での検査結果を予測するデータセットで、0が陰性を1が陽性を示します。

30列の特徴量から”target”が0か1かを予測するわけですね。
データ分割
from sklearn.model_selection import StratifiedKFold
skf = StratifiedKFold(n_splits = 5, shuffle = True)
df["fold"] = -1
for fold, (train_idx, valid_idx) in enumerate(skf.split(X = df, y = df["target"])):
df.loc[valid_idx, "fold"] = fold
print(df["fold"].value_counts())
学習データと評価データに分割しました。
分類問題ではラベル(今回でいう”target”)の分布に偏りがないように分割するといいです。
そこでStratifiedKFoldを使います。
引数yに分布を保ちたいデータを指定して分割しましょう。
df.groupby("fold").mean()["target"]
このコードで分割した番号ごとでの”target”の割合が見れます。だいたい6割くらい。
fold = 0
train = df.loc[df["fold"] != fold].copy()
valid = df.loc[df["fold"] == fold].copy()
print(train.shape, valid.shape)
feat_cols = train.drop(columns = ["fold", "target"]).columns.tolist()
print(feat_cols)
X_train = train[feat_cols]
X_valid = valid[feat_cols]
y_train = train["target"]
y_valid = valid["target"]
今回も番号0を評価データとして使いましょう。
モデル作成
回帰との大きな違いはパラメータ設定です!
import lightgbm as lgb
train_set = lgb.Dataset(X_train, y_train)
valid_set = lgb.Dataset(X_valid, y_valid)
params = {
"objective" : "binary",
"metric" : "binary_logloss"
}
result_data = {}
model = lgb.train(
params = params,
train_set = train_set,
valid_sets = [train_set, valid_set],
num_boost_round = 100,
early_stopping_rounds = 5,
verbose_eval = 50,
evals_result = result_data
)
metric:binary_logloss
“binary”は二値を意味します。
“binary_logloss”は損失関数の1つです。
学習過程を見てみましょう。↓
import matplotlib.pyplot as plt
plt.plot(result_data["training"]["binary_logloss"], color = "red", label = "train")
plt.plot(result_data["valid_1"]["binary_logloss"], color = "blue", label = "valid")
plt.legend()
plt.show()

いい感じですね。
予測結果
predictで予測できます。
pred = model.predict(X_valid)
print(pred)
予測結果はラベルの0or1ではなく、”ラベル1である確率”を出力します。

例えば1個目のデータはラベル1(陽性)である確率が0.2%です。
3つ目のデータは98.9%でラベル1ですね。
これを0or1のラベルに変換しましょう。↓
import numpy as np
pred = np.where(pred > 0.5, 1, 0)
print(pred)
print("=" * 100)
print(y_valid.values)

numpyのwhereで0.5以上ならラベル1としました。
y_validが正解データです。だいたい合っていそうですね。
では正解率を計算してみましょう!
from sklearn.metrics import accuracy_score
acc = accuracy_score(y_valid, pred)
print(acc)
“accuracy_score”で正解率を計算できます。だいたい95%くらいになるはず。
AUCも計算してみましょう。
from sklearn.metrics import roc_auc_score
auc = roc_auc_score(y_valid, pred)
print(auc)
AUCは”roc_auc_score”で計算しました。
これも95%くらいで高いはずです。
AUCなら偽陽性や偽陰性なども考慮して評価できます。
多クラス分類モデル
A:晴れ or 曇り or 雨
こんな感じで複数選択肢があるのが他クラス分類。
これもパラメータ設定以外は共通です。
load_iris
import pandas as pd
from sklearn.datasets import load_iris
data = load_iris()
df = pd.DataFrame(data["data"], columns = data["feature_names"])
df["target"] = data["target"]
print(df.shape)
df.head()
loasd_irisは花の種類を0,1,2の3つのラベルで分類するデータセットです。

“target”の数値が0~2の3種類になっています。これを予測しましょう。
データ分割
from sklearn.model_selection import StratifiedKFold
skf = StratifiedKFold(n_splits = 3, shuffle = True)
df["fold"] = -1
for fold, (train_idx, valid_idx) in enumerate(skf.split(X = df, y = df["target"])):
df.loc[valid_idx, "fold"] = fold
print(df["fold"].value_counts())
データ分割をします。やってることはこれまでと同じです。
今回もStratifiedKFoldにしてラベル分布を保ちましょう。
fold = 0
train = df.loc[df["fold"] != fold].copy()
valid = df.loc[df["fold"] == fold].copy()
print(train.shape, valid.shape)
print(train["target"].value_counts())
feat_cols = train.drop(columns = ["fold", "target"]).columns.tolist()
print(feat_cols)
X_train = train[feat_cols]
X_valid = valid[feat_cols]
y_train = train["target"]
y_valid = valid["target"]
特徴量と目的変数への分割です。
“target”に入っているラベルの分布を確認しておきましょう。
モデル作成
import lightgbm as lgb
train_set = lgb.Dataset(X_train, y_train)
valid_set = lgb.Dataset(X_valid, y_valid)
params = {
"objective" : "multiclass",
"metric" : "multi_logloss",
"num_class" : 3
}
result_data = {}
model = lgb.train(
params = params,
train_set = train_set,
valid_sets = [train_set, valid_set],
num_boost_round = 100,
early_stopping_rounds = 5,
verbose_eval = 50,
evals_result = result_data
)
metric:multi_logloss
num_class:ラベルの種類数(今回は3)
“num_class”でラベル数を指定することだけ注意しましょう!
学習結果はこんな感じ。↓
import matplotlib.pyplot as plt
plt.plot(result_data["training"]["multi_logloss"], color = "red", label = "train")
plt.plot(result_data["valid_1"]["multi_logloss"], color = "blue", label = "valid")
plt.legend()
plt.show()

評価データ(青)も小さいですね。
予測結果
predictで予測します。
pred = model.predict(X_valid)
print(pred.shape)
print(pred)
今回は3種のラベルなので、各行につき3つの確率が出力されます。

確率が高い列をラベルとして変換しましょう。
pred = pred.argmax(axis = 1)
print(pred)
print("=" * 100)
print(y_valid.values)
argmaxは数値が最も大きい位置を返してくれます。
次に正解率を見ましょう。
from sklearn.metrics import accuracy_score
acc = accuracy_score(y_valid, pred)
print(acc)
98%くらいになるかと思います。
多クラス分類ではAUCが計算できません。
適合率(precision)や再現率(recall)を計算しておきましょう。
from sklearn.metrics import precision_score, recall_score
precision = precision_score(y_valid, pred, average = "micro")
recall = recall_score(y_valid, pred, average = "micro")
print(precision, recall)
再現率:実際にラベル0だったデータのうち、0と予測した割合
これをラベル0,1,2において計算し、平均をとります。
だいたい98%くらいなのでかなり優秀です。
まとめ
今回はLightGBMの使い方を解説しました。
パラメータ設定以外はどのモデルでも使い方は同じです。
>>【無料説明会あり】キカガクのAI人材育成コースで勉強する

コメント