気象データから電力使用量を予測するニューラルネットワークの構築

作成: 日大生産工 MA 大前

  • ここでは、気象データ(気温や湿度など)から、その地域の電力使用量を予測する人工知能の構築について言及します。
  • 2020年のデータを利用します。
  • 対象地域は東京とします。

これは、大前研究室の卒業研究テーマの学習資料として作成されたものです。他のゼミ生がこのページを参考にして卒業研究を行う場合は、必ず事前に相談してください。異なる研究室なのに、同じテーマが卒業研究概要集に並んでいると、問題になるかもしれません。

1. データの取得

まず、分析に使用するデータを取得します。以下のコードを実行してください。

In [ ]:
import numpy as np
import matplotlib.pyplot as plt
from sklearn.neural_network import MLPRegressor
import scipy.stats as st

!wget http://int-info.com/PyLearn/Grad_4/data_for_study/tokyo_elec_dat_2020.csv
dat = np.loadtxt("tokyo_elec_dat_2020.csv", delimiter=",", skiprows=1, dtype=str)
day_all = dat[:, 0]
y_all = dat[:, 1].astype(float)
x_all = dat[:, 2:].astype(float)

def MinMaxStand_Xtrain_Xtest(fX_train, fX_test):
    
    # trainデータについて、各特徴量の最大値・最小値取得
    MaxVal, MinVal = [], []
    for i in range(0, len(fX_train[0, :])):
        MaxVal.append(np.max(fX_train[:,i]))
        MinVal.append(np.min(fX_train[:,i]))

    # trainデータの規格化
    newX_train = np.zeros(np.shape(fX_train))
    for i in range(0, len(fX_train[:,0])):
         for j in range(0, len(fX_train[0, :])):
                newX_train[i, j] = (fX_train[i, j] - MinVal[j]) / (MaxVal[j] - MinVal[j])
                
    # testデータの規格化
    newX_test = np.zeros(np.shape(fX_test))
    for i in range(0, len(fX_test[:,0])):
         for j in range(0, len(fX_test[0, :])):
                newX_test[i, j] = (fX_test[i, j] - MinVal[j]) / (MaxVal[j] - MinVal[j])

    # 規格化trainデータ、規格化testデータ、train最大値、train最小値を返却
    return newX_train, newX_test, MaxVal, MinVal

2. 電力使用量

東京都の電力使用量(正確には、東京電力パワーグリッドが発電し、消費された電力)は、y_allに格納されています。1行1行が1日1日を表し、2020年は閏年でしたらか、366個のデータで構成されます。単位は GW/day です。G(ギガ)は、10の9乗を意味します。試しにこのデータの中身を見てみます。

In [2]:
split = 30
x_num = np.arange(0, len(day_all), split)
x_str = []
for i in range(0, len(day_all), split):
    x_str.append(day_all[i])

plt.plot(y_all) # <- y_all(電力使用量をプロット)
plt.ylabel("[GW/day]")
plt.xticks(x_num, x_str, rotation=90)
plt.grid()
plt.show()

真夏と冬に、電力使用量が高いことがわかりました。ある程度直感的な結果かと思います。

3. 気象データ

続いて、電力使用量を予測するための情報である、気象データに注目します。気象データはx_allに格納されており、

  • 0列目: 平均気温(度)
  • 1列目: 平均風速(m/s)
  • 2列目: 降水量(mm)→(1日あたりの総量)
  • 3列目: 日照時間(h)→ 太陽が出ている合計時間。曇りや雨だと少ない。hは時間のこと。
  • 4列目: 平均湿度(%)

となります。こちらも、試しに平均気温をプロットしてみます。

In [3]:
plt.plot(x_all[:, 0]) # <- 0列目に平均気温があるので、列の指定を0にする
plt.ylabel("Temperature [°C]")
plt.xticks(x_num, x_str, rotation=90)
plt.grid()
plt.show()

夏の気温は高く、冬の気温が低いことがわかりました。こちらも直感的に問題ない結果かと思います。余裕があれば、気温以外も見てみることをお勧めします。

4. データセット分割

続いて、データセットを2つ(教師データ、テストデータ)に分割します。それぞれ、以下の意味を持ちます。

  • 教師データ: ニューラルネットワークに学習させるためのデータ
  • テストデータ: 構築したニューラルネットワークが、未知のデータを予測できるのか評価するためのデータ

人工知能とは、学習に使用しなかった、つまり、初めてみるデータに正解できることが重要です。そのため、教師データとテストデータを独立させることが必要です。なお今回は、2020年1月1日〜8月31日を教師データ、2020年9月1日〜12月31日をテストデータとします。

In [4]:
sp = 244 # 0〜243日を教師データ、244 〜 最後までをテストデータとする基準日
x_train = x_all[:sp, :]
x_test = x_all[sp:, :]
x_train_s, x_test_s, xmax, xmin = MinMaxStand_Xtrain_Xtest(x_train, x_test)

ymin = np.min(y_all[:sp])
ymax = np.max(y_all[:sp])
y_train = (y_all[:sp] - ymin)/(ymax - ymin)
y_test = (y_all[sp:] - ymin)/(ymax - ymin)

day_train = day_all[:sp]
day_test = day_all[sp:]

split = 15
x_num_train = np.arange(0, len(day_train), split)
x_str_train = []
for i in range(0, len(day_train), split):
    x_str_train.append(day_train[i])
    
x_num_test = np.arange(0, len(day_test), split)
x_str_test = []
for i in range(0, len(day_test), split):
    x_str_test.append(day_test[i])

print("### 教師データ: ", day_train[0], " 〜 ", day_train[-1])
print("### テストデータ: ", day_test[0], " 〜 ", day_test[-1])
### 教師データ:  2020/1/1  〜  2020/8/31
### テストデータ:  2020/9/1  〜  2020/12/31

5. ニューラルネットワークの構築

続いて、ニューラルネットワークについて簡単に説明します。今回構築するニューラルネットワークは、5個の情報(気温、風速、降水量、日照時間、湿度)を与えると、電力使用量を教えてくれる、という構造をしています(つまり、入力側が5次元、出力側が1次元となります)。

ニューラルネットワークを構築する際、重要なパラメータとして、学習回数と学習係数があります。すごくざっくりと説明すると、

  • 学習回数: ニューラルネットワークが学習を行う際、思考を何回変化させるか
  • 学習係数: 1回の学習に対する、思考の変化の大きさ(細かな学習か、大雑把な学習か)

という意味となります。一つの例として、

  • 学習回数: 2000回
  • 学習係数: 0.001

でニューラルネットワークを構築してみます。

In [5]:
NNreg = MLPRegressor(
    hidden_layer_sizes=(3, ),
    max_iter= 2000, # 学習回数を変更するには、ここの数字を変更すること
    learning_rate_init=0.001, # 学習係数を変更するには、ここの数字を変更すること
    random_state=0, # 乱数シード
    tol=10**-20, 
    verbose=False)
NNreg.fit(x_train_s, y_train)
/Users/yuto.omae/.pyenv/versions/3.7.1/lib/python3.7/site-packages/sklearn/neural_network/_multilayer_perceptron.py:585: ConvergenceWarning: Stochastic Optimizer: Maximum iterations (2000) reached and the optimization hasn't converged yet.
  % self.max_iter, ConvergenceWarning)
Out[5]:
MLPRegressor(hidden_layer_sizes=(3,), max_iter=2000, random_state=0, tol=1e-20)

これで学習が終わりました(学習回数が多いと、時間がかかるので注意してください)。もし、モデルをよりよくしたい場合は、3, 4行目の学習回数と学習係数を任意の値に変更してみてください。学習回数は5000や8000、学習係数は0.01、0.0001などのように、キリが良い値をおすすめします。

6. 性能評価(教師データ)

続いて、どのような予測結果になったのか確認してみます。学習に利用した教師データの結果を表示します。

In [6]:
# 教師データ
y_train_pred = NNreg.predict(x_train_s)
gt_train = (y_train)*(ymax-ymin) + ymin
pred_train = (y_train_pred)*(ymax-ymin) + ymin
plt.plot(gt_train, linestyle="-.", label="Ground truth")
plt.plot(pred_train, label="Prediction")
plt.title("Training data")
plt.ylabel("[GW/day]")
plt.xticks(x_num_train, x_str_train, rotation=90)
plt.grid()
plt.legend()
plt.show()

横軸が日にち、縦軸が電力使用量となります。線が2つあり、それぞれ以下を意味します。

  • Ground truth: 実際の電力使用量です。
  • Prediction: ニューラルネットワークにより予測された電力使用量です。

重なっていることが望ましい結果となります。夏と冬ごろは性能が良いようですが、春はちょっと微妙な感じです。このずれを定量化するために、絶対誤差を算出してみます(絶対誤差とは、1日ごとの誤差に、絶対値をつけ、それを平均したものです。したがって、1日だいたいどれくらい電力使用料がずれるのかを意味します)。

In [7]:
err_train = np.mean(np.abs(gt_train - pred_train))
print("絶対誤差(教師データ): ", np.round(err_train, 2), "[GW/day]")
絶対誤差(教師データ):  59.75 [GW/day]

1日あたり、平均で60GWほどズレがあるようです。

7. 性能評価(テストデータ)

教師データは、ニューラルネットワークが学習のために使用したデータでしかありません。実際は、初めてみるデータに当てられるということが重要になります。そのためここでは、テストデータで性能評価を行います。

In [8]:
# テストデータ
y_test_pred = NNreg.predict(x_test_s)
gt_test = (y_test)*(ymax-ymin) + ymin
pred_test = (y_test_pred)*(ymax-ymin) + ymin
plt.plot(gt_test, linestyle="-.", label="Ground truth")
plt.plot(pred_test, label="Prediction")
plt.title("Test data")
plt.ylabel("[GW/day]")
plt.xticks(x_num_test, x_str_test, rotation=90)
plt.grid()
plt.legend()
plt.show()

テストデータは先ほど記載したように、9月〜12月となります。こちらも割と当たっているでしょうか? 定量評価のために、絶対誤差を算出してみます。

In [9]:
err_test = np.mean(np.abs(gt_test - pred_test))
print("絶対誤差(テストデータ): ", np.round(err_test, 2), "[GW/day]")
絶対誤差(テストデータ):  57.43 [GW/day]

初めてみるデータに対しても、60GWくらいのズレに収まるようです。このように、何らかの自動判定モデルの性能評価を行う場合は、構築に関与していないデータの性能を示してあげる必要があります。

8. 予測値の取得

続いて、構築したニューラルネットワークを使用して、「どんな日だと、どれくらいみんな電力を使うのか?」という問いの答えを得てみます。今回は、暑くもなく寒くもない、風も強くなく、天気が良い日を想定してみます。いわゆる、普通の日でしょうか。

In [10]:
x0 = 25 # 平均気温(度)/ 5〜30度(東京なので)
x1 =  3 # 平均風速(m/s)/ 強風 4〜6くらい、普通の風2〜3くらい、ほとんど風がないならば1〜2
x2 = 0 # 降水量(mm)/大雨ならば60〜120くらい、小雨ならば30〜10くらい、晴れならば0
x3 = 10 # 日照時間(h)/ 晴天ならば10時間くらい 〜 1日中曇りor雨ならば0時間
x4 = 40 # 平均湿度(%)/ 30〜100%

x = [x0, x1, x2, x3, x4]
for i in range(len(x)):
    x[i] = (x[i] - xmin[i])/(xmax[i] - xmin[i])

res = NNreg.predict([x])
res = res * (ymax-ymin) + ymin
print("電力使用量の予測値: ", np.round(res[0] ,2), "[GW/day]")
電力使用量の予測値:  718.36 [GW/day]

普通の日の電力使用量は、720GWほどという結果になりました。先に見せた電力使用量のグラフを見る限り、あまり電気を使っていない日と言えそうです。x0 〜 x4 に任意の値を入れることで、シミュレーションしたい状況を設定することができます。なお、

  • 降水量が多いのに、日照時間が長い
  • 降水量が多いのに、湿度が低い

などのような、現実的にはあり得ない条件で試すことに意味はありませんので、注意してください(予測自体は行われます)。

9. 演習問題

  • 学習回数と学習係数の意味を今一度よく理解し、それらを変化させ、もっと性能の良いニューラルネットワークを構築してください。性能が良いとは、絶対誤差が低くなることを指します。
  • そのニューラルネットワークで、自分が考える色々な条件で、電力使用量を予測してください。
  • 上の結果を踏まえ、どのような条件だと発電量が高くなり、あるいは、低くなるのか、考察してください。

10. 卒業研究概要集への手引き

  • このテーマを卒業研究のテーマにしたい場合は、ここの対応をお願いします(必ず事前に相談してください)。
  • 以下、すべて含めて、A4用紙2枚にまとめてください。
  • 厳密に守る必要はありませんが、文章量の比率を目安にしてください(15%とは、A4用紙2枚分の15%という意味)。

1章 はじめに:(文章量の比率: 30%)

  • 電力使用量を予測する必要性を、自分で調べ、まとめてください。
  • その後、ニューラルネットワークで電力使用量を予測するという文脈を入れてください。
  • その際、ニューラルネットワークとは何か、簡単に紹介してください。
  • 電力使用量やニューラルネットワークについて説明する際、2, 3個の文献を引用してください。
  • 必要に応じて、図などがあってもいいかもしれません。

2章 入出力の関係:(文章量の比率: 20%)

  • 何から(気象データ)、何を(電力使用量)予測するしようとしているか、説明してください。
  • 「気象データ」と一言だけ書いても意味がわからないので、注意してください。その中身の要素などをきちんと書くこと。
  • 電力使用量にせよ、気象データにせよ、単位の説明もしっかり行なってください。

3章 ニューラルネットワークの実験:(文章量の比率: 30%)

  • この章では、演習問題でまとめたことを記載します。

3.1節 概要:

  • どのような条件設定で、どのような分析を行うのか、簡単に記載してください。
  • 性能の良いニューラルネットワークを作るとか、どのような日が電力使用量が多いのか明らかにするとか、そのためにあれをする・これをするとか。

3.2節 結果と考察:

  • 色々な学習回数・学習係数でニューラルネットワークを構築し、絶対誤差を表などにまとめてください。
  • また、一番性能の良いニューラルネットワークの予測結果について、グラフなどを使い、電力使用量を示してください。
  • 上の結果を自由に考察してください。
  • また、色々な条件設定で予測させ、表などにまとめ、どのような条件だと電力使用量が多くなるのか、考察してください。
  • 必要に応じて、図・表を作成してください。

4章 おわりに:(文章量の比率: 20%)

  • 今回の分析に対する感想などを記載してください。

参考文献: 参考にした資料を、2〜3件記載してください。以下、書き方の例です。

  • [1] 大前ほか, XXXに関する分析, XXX学会論文誌, 2020.
  • [2] XXXに関する情報, http://xxx.ddd.ttt.com, 2020年4月20日閲覧

本文中で引用する場合は「大前らはXXXを実施している [1]。また、〜」のように、どこで引用したのか明白にしてください。

Appendix:

本項で使用しているデータは、以下から取得したものです。

東京電力パワーグリッド, 過去の気象データ・ダウンロード:

気象庁, 過去の気象データ・ダウンロード(東京都)