LoginSignup
14
14

More than 5 years have passed since last update.

いつか学びたかったLightGBM

Posted at

タイトルはこれで適当につけています。

きっかけ

一回試してみたかったので、以下を読みながらLightGBMを試してみた。
https://www.codexa.net/lightgbm-beginner/

インストールするのがめんどくさかったので、環境はGoogle Colabにて。

座学

アンサンブル

アンサンブルの手法は大きく分けると「バギング」「ブースティング」「スタッキング」となる
参考:https://www.codexa.net/what-is-ensemble-learning/

  • バギング
    • 並列的に学習
  • ブースティング
    • 前の弱学習器の結果を次の学習データに反映
  • スタッキング
    • 二段階に学習を積み上げる

※今回はアンサンブルの各手法を掘り下げるのが目的ではないので、ふんわりとさせておく。

LightGBMって?

勾配ブースティングは複数の弱学習器(LightGBMの場合は決定木)を一つにまとめるアンサンブル学習の「ブースティング」を用いた手法

仮に最初に訓練を行う決定木を1号、次に訓練を行う決定木を2号としましょう。まずは決定木(1号)でモデル訓練を行い推測結果を評価します。決定木(1号)の推測結果と実際の値の「誤差」を訓練データとして、決定木(2号)の訓練を行います。N号の決定木はN-1号の決定木の誤差(Residuals)を学習するわけです。

実践

せっかくなので、こっちのデータでやってみる
https://prob.space/c

ただ、codexaとコンペだとファイルの数が違うけど、いったん無視して続けてみる。

kmnist-test-imgs.npz
kmnist-train-imgs.npz
kmnist-train-labels.npz

ファイルアップロード

# filesモジュールでアップロード
from google.colab import files
uploaded = files.upload()

これでファイル選択できるようになるので、対象ファイルをアップロードする

ファイル読み込み

# 訓練データの読み込み
X_train = np.load('kmnist-train-imgs.npz')['arr_0']
y_train = np.load('kmnist-train-labels.npz')['arr_0']
# テストデータの読み込み
X_test = np.load('kmnist-test-imgs.npz')['arr_0']

# データのサイズ確認
print(X_train.shape)
print(X_test.shape)

アップロードしたファイルを読み込み、想定通りの件数になっているかを確認

データの確認

print(X_train.min())
print(X_train.max())

print(y_train[423])

plt.imshow(X_train[423], cmap = plt.cm.gray)
plt.show()

どういう中身かを確認

データ前処理

正規化

# 処理前データ確認
X_train[0,10:15,10:15]
# 訓練/テストデータの正規化
X_train = X_train / 255 
X_test = X_test/ 255
# 処理後データ確認
X_train[0,10:15,10:15]

リサイズ

# 処理前データ確認
print(X_train.shape)
print(X_test.shape)
X_train = X_train.reshape(X_train.shape[0], 784)
X_test = X_test.reshape(X_test.shape[0], 784)

# 処理後データ確認
print(X_train.shape)
print(X_test.shape)

LightGBM モデル訓練

# 訓練・テストデータの設定
train_data = lgb.Dataset(X_train, label=y_train)
eval_data = lgb.Dataset(X_test, label=y_test, reference= train_data)

ハイパーパラメータはとりあえず初期値としておく。

このタイミングでvalidation用のデータとラベルが必要なのだが、どちらも無いことに気が付く。
なので訓練データを分割して作成することにする。
件数的にはとりあえず3割ぐらいにしておく。

validation_size = 0.3
np.random.seed()
perm_idx = np.random.permutation(len(X_train))
_X_train = X_train[perm_idx]
_y_train = y_train[perm_idx]

# split train and validation
validation_num = int(len(y_train) * validation_size)

validation_imgs = _X_train[:validation_num]
validation_lbls = _y_train[:validation_num]

train_imgs = _X_train[validation_num:]
train_lbls = _y_train[validation_num:]

このデータを使って、改めてモデル設定

# 訓練・テストデータの設定
train_data = lgb.Dataset(train_imgs, label=train_lbls)
eval_data = lgb.Dataset(validation_imgs, label=validation_lbls, reference= train_data)
params = {
'task': 'train',
'boosting_type': 'gbdt',
'objective': 'multiclass',
'num_class': 10,
'verbose': 2,
}

boosting_typeのgbdtは「Gradient Boosting Decistion Tree」の略です。分類クラスは3つ以上ですので多項分類(multiclass)を目的(objective)に指定します。またターゲットクラスは10種類の平仮名ですのでnum_classは10となります。

学習

gbm = lgb.train(
params,
train_data,
valid_sets=eval_data,
num_boost_round=150,
verbose_eval=5,
)

サンプルでは100回訓練していたが、もちっと繰り返してもよさそうだったので150回にしてみる。

検証

y_pred = []
eval_predicts = gbm.predict(validation_imgs)
for x in eval_predicts:
    y_pred.append(np.argmax(x))

confusion_matrix(validation_lbls, y_pred)
accuracy_score(validation_lbls, y_pred)

0.9426111111111111

思ってた以上よりいい感じ。高すぎる気もするけど。

予測

_predicts = gbm.predict(X_test)
predicts

predicts = []
for x in _predicts:
    predicts.append(np.argmax(x))

ファイル作成

submit = pd.DataFrame(data={"ImageId": [], "Label": []})
submit.ImageId = list(range(1, _predicts.shape[0]+1))
submit.Label = predicts


submit.to_csv("submit.csv", index=False)
files.download('submit.csv')

これで予測した結果をDLできる。

提出してみた結果

2019-05-06_19h21_08.png

0.862

こんなもんか。過学習しちゃっているような感じなのかなぁ。
もちっとパラメータをいじってみたり、XGBoostも試してみての差を見てみたりしたいけど、とりあえず連休はもうおしまいなのである。。

今回作ったものは以下
https://github.com/RyoNakamae/LightGBM

14
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
14