気象実績と、関西電力の使用量という現実のデータで学習用データを作ってみたので、今回はそれを使ってランダムフォレストを使って回帰問題をやってみます。
なんでランダムフォレストなのか
ランダムフォレスト(RandomForest)は「決定木を複数作って結果を多数決(平均化)することで、決定木の過学習を平準化する」、いわゆるアンサンブル学習のアルゴリズムです。
決定木のイメージは、こちらの記事の前の方を読めばイメージはつくと思います。
ランダムフォレストは一昔前の手法のように思えますが、実はTensorflowのチュートリアルにこんなことがかかれていたりする「現役の手法」なのです。
キーポイント:一般的に、ディープラーニングが最良の結果となるのは、もっと大きくて、もっと複雑なデータセットです。
この例のように小さなデータセットを使用する際には、強固なベースラインとして、決定木やランダムフォレストを使うことをおすすめします。
で。
今回作成した「気象情報+電力使用量」データなど、まさしく上記の「構造化された小さなデータセット」で、うってつけだな・・と思うわけです。
あと、もうひとつ。
ランダムフォレストには、すごく良いところが2つあります。
- とても気楽に使える(正規化とか標準化とかをあまり気にしなくてよい)
- 結果に対して重要な特徴量を調べることができる。
です。
なので、とりあえずランダムフォレストであたりをとってみて、特徴量として重要そうな項目に絞り込んで方針を考える・・みたいに検討段階にも使えます。
データ・環境を用意します
今回は、以下の学習とテスト用データを用意しました。
- 学習データ:2018/6/1~2019/6/30の1年分の気象+電力使用量
- テストデータ:2019/7/1~2019/7/31の1月分の気象+電力使用量
用意した方法は以下の記事の通りです。
欠損データ等があれば修正しておく
気象情報には観測できなかったことを示す欠損データが混じっている場合があります。
これを参考に「-」とか「///」みたいな記号があれば、0に置き換えるなりの処理をしておく必要があります。
幸い、今回のデータにはありませんでした。
ヘダーは処理しづらいですが、あえて日本語にしてます
ヘダー名は「日本語」を使ってます。
ブログに書くので、わかりやすさ優先です。
そのため。
matplotlibにも日本語フォントを設定してます。
日本語化の方法は以下の記事のとおりです。
学習・予測および重要な特徴量の調査をやってみる
1年間分の学習データと7月度1カ月分のテストデータを用意して、ランダムフォレストで学習と予測をします。
7月度分には実際の数値があります。
予測値とどの程度一致しているかを決定係数とグラフの視覚化で確認します。
続けて、予測に利用した特徴量の重要度を取得して、文字とグラフで出力します。
さて、ソースです。
ちょっと長いですけど、コメントを見ると大したことしてないのはわかります。
sk_rf_kansai.py
import pandas as pd import numpy as np import matplotlib.pyplot as plt from sklearn.ensemble import RandomForestRegressor from sklearn.metrics import r2_score # 学習データCSVファイル読み込み df_train_all = pd.read_csv('train_kanden.csv') # 最大電力量を目的変数(ターゲット)にする y_train = df_train_all[u'電力量(最大)'].values.tolist() # 不要な列を切り落として説明変数にする data_train = df_train_all.drop([u'年月日', u'電力量(最大)', u'電力量(最小)'], axis=1) x_train = data_train.values.tolist() # テスト用データCSV読み込み df_test_all = pd.read_csv('test_kanden.csv') # 最大電力量を目的変数(ターゲット)にする y_test = df_test_all[u'電力量(最大)'].values.tolist() # 不要な列を切り落として説明変数にする data_test = df_test_all.drop([u'年月日', u'電力量(最大)', u'電力量(最小)'], axis=1) x_test = data_test.values.tolist() # ランダムフォレスト回帰オブジェクト生成 rfr = RandomForestRegressor(n_estimators=100) # 学習の実行 rfr.fit(x_train, y_train) # テストデータで予測実行 predict_y = rfr.predict(x_test) # R2決定係数で評価 r2_score = r2_score(y_test, predict_y) print(r2_score) # 特徴量の重要度を取得 feature = rfr.feature_importances_ # 特徴量の名前ラベルを取得 label = data_train.columns[0:] # 特徴量の重要度順(降順)に並べて表示 indices = np.argsort(feature)[::-1] for i in range(len(feature)): print(str(i + 1) + " " + str(label[indices[i]]) + " " + str(feature[indices[i]])) # 最大電力量の実績と予測値の比較グラフ plt.subplot(121, facecolor='white') plt.title('7月の電力量') plt_label = [i for i in range(1, 32)] plt.plot(plt_label, y_test, color='blue') plt.plot(plt_label, predict_y, color='red') # 特徴量の重要度の棒グラフ plt.subplot(122, facecolor='white') plt.title('特徴量の重要度') plt.bar( range( len(feature)), feature[indices], color='blue', align='center') plt.xticks(range(len(feature)), label[indices], rotation=45) plt.xlim([-1, len(feature)]) plt.tight_layout() # グラフの表示 plt.show()
補足します。
RandomForestRegressorのパラメータは、ほぼデフォルトですが、n_estimatorだけは100にしてます。
しないと、以下の警告がでるからです。
FutureWarning: The default value of n_estimators will change from 10 in
version 0.20 to 100 in 0.22."10 in version 0.20 to 100 in 0.22.", FutureWarning)
今はデフォルトが10ですが、将来はデフォルトが100になるということです。
実行結果はあまり良くありませんが
実行してみます。
コンソールに出力された結果です。
まず決定係数
0.46765316988936834
低いですね。
実績(青線)と予測値(赤線)の比較グラフを見てもいまいちなグラフです。
特徴量の重要度です。
1 最高気温(℃) 0.4444090067555015
2 最低気温(℃) 0.35184623528743375
3 平均湿度(%) 0.09215736390544586
4 平均風速(m/s) 0.09144851184927882
5 降水量の合計(mm) 0.020138882202340103
グラフで視覚化した結果は。
降水量の重要度が極端に低いです。
改善ポイントを考えてみます
学習データに、直近の1年間の実績をつかったのが、まず問題でした。
電気を使うという観点で見ると暑くても、寒くても同じです。
夏場も、冬場も同じように電気はつかうわけです。
これをデータとして眺めてみると、まったく違う説明変数で、同じ目的変数が正解になることが頻繁にありえるので、学習データとしては、とてもよろしくありません。
なので、夏場の予測をするなら、その時期に絞った数年分のデータで学習したほうが良いのではないかと思えます。
あと。
極端に重要度の低かった降水量。
これは外した方が予測精度があがるのではないか?という仮説がたちます。
それらの対策をうってみたら、どの程度予測精度がかわるのか?
それは次回「その2」で試すことにします。
ではでは。