目次
気象情報と電力データを使いランダムフォレストで回帰するサンプル
オープンデータの気象実績と、関西電力の使用量で学習データを作成し、ランダムフォレストを使って、とりあえず回帰してみます。
学習用データの準備
気象実績と、関西電力の使用量の学習用データを作ってみました。
- 学習データ:2018/6/1~2019/6/30の1年分の気象+電力使用量
- テストデータ:2019/7/1~2019/7/31の1月分の気象+電力使用量
用意した方法は以下の記事の通りです。
学習用データチェック
学習用データをランダムフォレストにかける前に、データチェックします。
気象情報には観測できなかった欠損データが混じっている場合があるためです。
これを参考に「-」とか「///」みたいな記号があれば、0に置き換えるなりの処理をしておく必要があります。
幸い、今回のデータにはありませんでした。
なお、ブログに書くので、わかりやすさ優先でヘダー名は「日本語」を使います。
matplotlibにも日本語フォントを設定しました。
日本語化の方法は以下の記事のとおりです。
ランダムフォレスト
ランダムフォレスト(RandomForest)は「決定木を複数作って結果を多数決(平均化)することで、決定木の過学習を平準化する」、いわゆるアンサンブル学習のアルゴリズムです。
決定木のイメージは、こちらの記事の前の方を読めばイメージはつくと思います。
ランダムフォレストは一昔前の手法のように思えますが、実はTensorflowのチュートリアルにこんなことがかかれていたりする「現役の手法」です。
キーポイント:一般的に、ディープラーニングが最良の結果となるのは、もっと大きくて、もっと複雑なデータセットです。
この例のように小さなデータセットを使用する際には、強固なベースラインとして、決定木やランダムフォレストを使うことをおすすめします。
ランダムフォレストには、すごく良いところが2つあります。
- とても気楽に使える(正規化とか標準化とかをあまり気にしなくてよい)
- 結果に対して重要な特徴量を調べることができる。
です。
なので、とりあえずランダムフォレストであたりをとってみて、特徴量として重要そうな項目に絞り込んで方針を考える・・みたいに検討段階にも使えます。
ランダムフォレストで学習・予測および重要な特徴量の調査
学習データには1年間分を使います。
テストデータは7月の1月分としました。
7月度分にはリアルの実績数値があるので、ランダムフォレストで学習と予測をして決定係数をもとめてみようと思います。
決定係数は回帰分析の当てはまりが良い(目的変数が十分に説明されているという表現で書かれていることも多いですが)かどうかを数値化したもので、0以上1以下の値をとります。
値が大きいほうが当てはまりが良いそうです。
0.5を超えると当てはまりが良いと聞いたことがありますけれど、正直、目安はよくわかりません。
あと、結果に影響を与えた特徴量の重要度をグラフで出力してみます。
Pythonソースコードと補足
ちょっと長いです。
けど、コメントを見ると大したことしてないのはわかると思います。
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
実に微妙に低いです。
0.5に近いから「まあまあ」なのかもしれないのですが、なんか、いまいちすっきりはしませんし、実績(青線)と予測値(赤線)の比較グラフを見ても、なんとも微妙にいまいちな感じがします。
次に特徴量の重要度を見てみます。
出力結果はこうです。
1 最高気温(℃) 0.4444090067555015
2 最低気温(℃) 0.35184623528743375
3 平均湿度(%) 0.09215736390544586
4 平均風速(m/s) 0.09144851184927882
5 降水量の合計(mm) 0.020138882202340103
グラフで視覚化した結果は。
降水量の重要度が極端に低いです。
改善ポイントを考えてみます
学習データに、直近の1年間の実績をつかってみたのが、問題だったのかもしれないと思っています。
なぜかというと、電気を使うという観点で見ると暑くても、寒くても同じだからです。
夏場も、冬場も同じように電気はつかうわけです。
これをデータとして眺めてみると、まったく違う説明変数で、同じ目的変数が正解になることが頻繁にありえるので、学習データとしては、とてもよろしくありません。
なので、夏場の予測をするなら、その時期に絞った数年分のデータで学習したほうが良いのではないかと思えます。
あと。
極端に重要度の低かった降水量。
これは外した方が予測精度があがるのではないか?という仮説がたちます。
それらの対策をうってみたら、どの程度予測精度がかわるのか?
それは次回「その2」で試すことにします。
ではでは。