LightGBMで回帰分析をやってみる1
LightGBM で回帰分析 1
Kaggle などで、カリフォルニアの家の価格分析などをやっているのを見て、LightGBM を利用した回帰分析は有用そうだなと感じました。しかし、回帰分析の結果って本当にあっているの?と疑問に思うことが多々あります。
そこで、単純なモデルからランダムなデータを作成し、そこから LightGBM にて学習、予想してみます。
この記事の結果は次のとおりです。
- 予測はかなり精度が良い
- 予測は学習の範囲内でしか利用できない
なお、この記事で利用している LightGBM のハイパーパラメータはすべてデフォルト値であるため、すべての環境でこの結果とならない可能性もあります。
もし、外挿でも精度を保つことができる方法がありましたら教えてください!
準備
今回は分析を簡単にするために y = a + 2b という式を作成し、a および b にそれぞれ任意の数値(0 ~ 100)を割り当てた後、10%の誤差をそれぞれランダムに与えています。データはこの記事の Github にアップロードしています。
データ分析
まずは学習に必要なライブラリをインポートします。
import pandas as pd
import lightgbm as lgb
from sklearn.model_selection import train_test_split
続いて、データの読み込みを行います。
df = pd.read_csv("./your/path/to/lgb_sample.csv", encoding = "cp932")
元データをエクセルで作成しているため、文字コードが cp932 となっています。utf-8 だとエラーが出てくるためご注意下さい。
学習・テストデータの作成
ライブラリを用いて学習用のデータを作成します。
x_train, x_test, y_train, y_test = train_test_split(df.iloc[:,1:], df.iloc[:,:1], test_size=0.2)
モデルの作成と学習
今回はトライアルということでハイパーパラメータを指定せずにデフォルトで利用します。結果として、この程度の分析だったらかなり精度が高い予想ができるようです。
model = lgb.LGBMRegressor()
pred_y = model.fit(x_train,y_train)
特徴量の重要度
a.feature_importances_
# array([1442, 1558])
変数 a と b だとあまり重要度が変わらないようです。a と b は線形結合しており、その割合もランダムな誤差からの影響しか受けていません。したがって、この結論は妥当だと考えます。
予測精度
実際に予測したときの精度はいかがなものでしょうか?
pred_y.score(x_test,y_test)
# 0.9982130515044173
高っ!まじか!と思いましたが、過学習しているだけかもしれません。まだ信じていけませんよ?
新たなデータを用いた予測精度の分析
過学習を起こしているのであれば、追加するデータでは予測精度が下がってしまうはずです。ということで、新たな a,b を作成、理論値(y=a+2b)に基づいた y をそれぞれ作成した後、モデルで予測して精度を確認します。
新たなデータを作成する。
numpy を用いて a,b を網羅的に割り当てます。
import numpy as np
x1 = np.linspace(0,100)
x2 = np.linspace(0,100)
データの格納用 DataFrame を作成します。
df_t = pd.DataFrame({"a":[],"b":[],"result":[]})
網羅的にデータを格納するためのリストを作成します。その後で DataFrame に格納します。
list_a = []
list_b = []
for aa in x1:
for bb in x2:
list_a.append(aa)
list_b.append(bb)
df_t.a = list_a
df_t.b = list_b
新規データの予測
作成した a, b のデータから再度予測します。
df_t.result = a.predict(df_t.iloc[:,:-1])
予測精度の確認
予測精度を再度確認します。新たに Y というカラムを作成しました。ここには理論値の答えが入っています。
df_t["Y"] = df_t.a + df_t.b *2
最終スコアは 0.9981 となりました。素晴らしいですね。
pred_y.score(df_t.iloc[:,:-2], df_t.Y)
# 0.9981580767679779
外挿できるのか?
さて、回帰分析などを行う場合は、基本的にそれぞれの係数は計算に用いた範囲で実行する必要があります。しかし、今回のような単純な式の場合は a,b の係数を計算し、それを用いることで外挿することができます。機械学習で得られた結果に対して外挿することができるのか、確認してみましょう。
今回、a, b の新規データの予想を-100 ~ 500 としました。やることは上記と同じなので詳細なコードは割愛します。
結果はこの通りです。
pred_y.score(df_t.iloc[:,:-2], df_t.Y)
# -0.6360057727238666
予測はできていないですね。
変数が少ないので、Pairplot のデータも見てます。理論値 Y に対して予測値である result のレンジが全く違います。これで予測できていないことがわかりますね。
ちなみに、0 ~ 100 のときはこの様な形です。
一目瞭然だと思います。外挿がまったく機能しておらず、内挿であればかなりの精度が出ています。
まとめ
今回用いた LightGBM だと何も考えずにモデルを作成した場合、外挿することはできないと考えられます。ただし、内挿の場合は精度が非常に良かったので、うまく使えば良いモデルを作れるのではないでしょうか?次回以降はハイパーパラメータを検討してみたいです。
Discussion