"BOKU"のITな日常

還暦越えの文系システムエンジニアの”BOKU”は新しいことが大好きです。

ランダムフォレストで回帰してみる/気象情報と電力データその1

気象実績と、関西電力の使用量という現実のデータで学習用データを作ってみたので、今回はそれを使ってランダムフォレストを使って回帰問題をやってみます。

f:id:arakan_no_boku:20190808232239p:plain

 

なんでランダムフォレストなのか

 

ランダムフォレスト(RandomForest)というのは「決定木を複数作って結果を多数決(平均化)することで、決定木の過学習を平準化する」という、いわゆるアンサンブル学習のアルゴリズムです。

決定木のイメージは、こちらの記事の前の方を読めば、なんとなくイメージはつくと思いますので、特に書きません。

dev.classmethod.jp

イメージ的には昔のアルゴリズムで、今時、ディープラーニングを使えばいいじゃないかと思ったりするのですが、実はTensorflowのチュートリアルにこんなことがかかれていたりする「現役の手法」なのです。

キーポイント:一般的に、ディープラーニングが最良の結果となるのは、もっと大きくて、もっと複雑なデータセットです。

この例のように小さなデータセットを使用する際には、強固なベースラインとして、決定木やランダムフォレストを使うことをおすすめします。

で。

今回作成した「気象情報+電力使用量」データなど、まさしく上記の「構造化された小さなデータセット」なので、うってつけだな・・と思うわけです。

あと、もうひとつ。

ランダムフォレストには、すっごく良いところが2つあります。

  • とても気楽に使える(正規化とか標準化とかをあまり気にしなくてよい)
  • 結果に対して重要な特徴量を調べることができる。

です。

なので、とりあえずランダムフォレストであたりをとってみて、特徴量として重要そうな項目に絞り込んだりして方針を考える・・みたいにも使えたりします。

 

データ・環境を用意します

 

今回は、以下の学習とテスト用データを用意しました。

  •  学習データ:2018/6/1~2019/6/30の1年分の気象+電力使用量
  • テストデータ:2019/7/1~2019/7/31の1月分の気象+電力使用量

用意した方法は以下の記事の通りです。

arakan-pgm-ai.hatenablog.com

arakan-pgm-ai.hatenablog.com

 

欠損データ等があれば修正しておく

 

気象情報には観測できなかった場合とかに欠損データが混じっている場合があります。

ここに説明があります。

www.data.jma.go.jp

これを参考に「-」とか「///」みたいな記号があれば、0に置き換えるなりの処理をしておく必要があります。

幸い、今回のデータだと何もする必要はありませんでした。

 

ヘダーは処理しづらいですが、あえて日本語にしてます

 

ヘダー名などは「日本語」を使ってます。

ブログに書くので、わかりやすさ優先です。

そのため。

matplotlibも日本語表示できるように、日本語フォントを設定してます。

日本語化の方法は以下の記事のとおりです。

arakan-pgm-ai.hatenablog.com

 

学習・予測および重要な特徴量の調査をやってみる

 

やることはシンプルです。

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

低いですね。

実績(青線)と予測値(赤線)の比較グラフを見ても、まあ、なんとなくその程度なグラフになってます。 

f:id:arakan_no_boku:20190809221047p:plain

特徴量の重要度です。

1 最高気温(℃) 0.4444090067555015
2 最低気温(℃) 0.35184623528743375
3 平均湿度(%) 0.09215736390544586
4 平均風速(m/s) 0.09144851184927882
5 降水量の合計(mm) 0.020138882202340103

グラフで視覚化した結果は。

f:id:arakan_no_boku:20190809221547p:plain

降水量の重要度が極端に低いです。

 

改善ポイントを考えてみます

 

あまり、精度はよくなかったのですが。

実のところ。

この結果は・・ほぼ予想通りではあります。

学習データに、直近の1年間の実績をつかったからです。

なんとなく良さげなのですが、よく考えてみると・・。

夏場の気温が高い時も、冬場の気温が低い時も同じように電気はつかうわけです。

使用電力量みたいなデータはある程度の範囲で動きますから、データをよーーく眺めてみると、夏場と冬場で倍違う・・なんてことはなく、ピークの電力量も似たような数字になってます。

つまり、まったく違う説明変数で、同じ目的変数が正解になることが頻繁にありえるということなのです。

これは学習データとしては、とてもよろしくないかな・・と。

なので、夏場だけの数年分のデータで学習したほうが良かったかな・・と思います。

あと。

極端に重要度の低かった降水量。

これを外した方が予測精度があがる可能性も高いです。

それらの対策をうってみたら、どの程度予測精度がかわるのか?

試してみたいのですが、長くなりすぎるので、また、別の機会にためしてみます。

ではでは。