機械学習でガソリンの価格を予測する!②
- そらまめ
- 2020年8月16日
- 読了時間: 6分
更新日:2020年8月28日

はじめに
こんにちは、そらまめです!
今回は前回紹介したデータセットについて実際に分析を行っていきたいと思います。
前回の記事記事からの続きとなっていますので、また読んでない方は、こちらもよろしくお願いします!!
前回の記事:機械学習でガソリンの価格を予測する!①
今回使用するデータ:
ガソリンデータセットの確認
早速データセットを読み込み、データの概要について見ていきましょう!
#モジュールのインポート
import pandas as pd
from matplotlib import pyplot as plt
import seaborn as sns
import japanize_matplotlib
%matplotlib inline
#データ読み込み
Gasoline = pd.read_csv('Gasoline.csv')
Gasoline.head() #先頭5行確認

#行数と列数を確認
Gasoline.shape
(286, 13)
・レコード数:286
・カラム数は:13
・データ型
#データ型を確認
Gasoline.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 286 entries, 0 to 285
Data columns (total 13 columns):
日付 286 non-null object
レギュラー
286 non-null float64
ハイオク
286 non-null float64
軽油 286 non-null float64
原油_終値 286 non-null float64
原油_始値 286 non-null float64
原油_高値 286 non-null float64
原油_安値 286 non-null float64
原油_前日比% 286 non-null object
為替_始値 285 non-null float64
為替_高値 285 non-null float64
為替_安値 285 non-null float64
為替_終値 285 non-null float64
dtypes: float64(11), object(2)
memory usage: 29.1+ KB
日付、原油_前日比%はobject型←モデルに学習させるために数値に変換する必要がある!
その他はfloat64型(浮動小数点型)
また各カラムの意味は下記の通りです。

データの可視化
まずはレギュラー、ハイオク、軽油の値段の推移を見ていきます。
今回予測する値となります!
#日付をdatetime型に変換する
Gasoline['日付'] = pd.to_datetime(Gasoline['日付'], infer_datetime_format=True)
#グラフ用データを作成
x = Gasoline[:,0]
y1 = Gasoline.iloc[:,1]#レギュラー
y2 = Gasoline.iloc[:,2]#ハイオク
y3 = Gasoline.iloc[:,3] #軽油
# グラフの作成
plt.plot(x, y1, label="レギュラー")
plt.plot(x, y2, label="ハイオク")
plt.plot(x, y3, label="軽油")
#タイトルの追加
plt.title('ガソリン価格の推移')
# 縦軸のラベル名の追加
plt.ylabel("円")
# 図の左上に凡例を表示
plt.legend(loc='upper left')

このグラフからレギュラー、ハイオク、軽油の価格がほとんど連動し合っていることが確認できます。
次にガソリンの価格に対して原油先物価格、為替がどれほど関係しているのか散布図で確認してみましょう。このグラフからは特に原油価格が上がるとレギュラーの値段も上がる傾向にあることが分かります。
また2020年5月に原油先物価格が初のマイナスになったことが左のグラフにも反映されていることが確認できると思います!
こうした他の値から大きく外れた通称「外れ値」と呼ばれる値は機械学習モデルの学習の妨げとなるので、外れ値の存在する行を削除するなどの対応が必要となってきます。
#グラフ用データを作成
y1 = Gasoline.iloc[:,1]#レギュラー
y2 = Gasoline.iloc[:,4]#原油_終値
y3 = Gasoline.iloc[:,12]#為替_終値
# figureの作成
plt.figure(figsize=(8, 4))
# 1つ目のグラフ領域の作成
plt.subplot(1, 2, 1)
# 1つ目のグラフ
plt.scatter(y1, y2)
plt.xlabel('レギュラーの値段') # X軸
plt.ylabel('原油価格_終値')
#グリッド線
plt.grid()
# 2つ目のグラフ領域の作成
plt.subplot(1, 2, 2)
# 2つ目のグラフ
plt.scatter(y1, y3)
plt.xlabel('レギュラーの値段') # X軸
plt.ylabel('ドル円レート_終値')
#グリッド線
plt.grid()

前処理
今回はレギュラーの1週先の価格を目的変数として予測していきたいと思います。
pythonのshift()関数の引数を-1にすることで行を1つ下にずらすことが出来るのでこれを利用します!
#目的変数を作成 レギュラーの値を1つ下にずらして1週先の予測を行えるようにする
Gasoline['レギュラー_y'] = Gasoline.iloc[:,1].shift(-1)
Gasoline = Gasoline.dropna()
#原油_前日比%を%を削除してから数値化
Gasoline['原油_前日比%'] = Gasoline['原油_前日比%'].str.replace('%','')
Gasoline['原油_前日比%'] = Gasoline['原油_前日比%'].astype(float)
#説明変数 日付とレギュラー_y以外のすべての変数
X = Gasoline.drop(["日付","レギュラー_y"],axis=1)
#目的変数 レギュラーの1週先の価格
y = Gasoline['レギュラー_y']
次に、train_test_split()関数を用いて訓練データとテスト用データを8:2に分割します。
# train_test_splitのインポート
from sklearn.model_selection import train_test_split
# 学習データおよび検証データと、評価データに80:20の割合で2分割する
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20, shuffle=False)
モデルの学習
記事でも用いられていたXGBoost Regressorを使っていきます。
ハイパーパラメータチューニング等はまた別の機会に話していけたらと思います。
#XGBoost Regressorのインポート !pip install xgboost ←初めての人は
import xgboost as xgb
from xgboost import XGBRegressor
model = XGBRegressor(max_depth=5,random_state=0)
model.fit(X_train,y_train)
予測精度の算出
予測精度の確認方法として、平均平方根誤差(RMSE, Root Mean Squared Error)と(自由度調整済み)決定係数(R2, R-squared, coefficient of determination)を使ってみたいと思います。
平均平方根誤差は、実際の値と予測値の絶対値の2乗を平均したものに対して平方根をとったものです。値が大きいほど誤差の多いモデルとなります。
(自由度調整済み)決定係数は、モデルの当てはまりの良さを示す指標です。最も当てはまる場合は、1.0となり、全然当てはまらない場合は0.0となります。
※決定係数は説明変数が増えるたびに1に近づくという性質を持っています。そこで今回のように説明変数を複数使うモデルの精度評価にはこの点を補完した自由度調整済み決定係数を使用します。
・RMSE

・自由度調整済み決定係数

・平均平方根誤差による予測結果
# 平均二乗誤差による予測精度算出
import numpy as np
from sklearn.metrics import mean_squared_error
y_test_pred = model.predict(X_test) #テストデータを用いて目的変数を予測
y_trainval_pred = model.predict(X_trainval) #検証データに対する目的変数を 予測
print('RMSE trainval data: ', np.sqrt(mean_squared_error(y_trainval, y_trainval_pred)))
print('RMSE test data: ', np.sqrt(mean_squared_error(y_test, y_test_pred)))
RMSE trainval data: 0.21536661920922692 RMSE test data: 1.4380331371491655
・決定係数による予測結果
# 決定係数による予測精度算出
from sklearn.metrics import r2_score
print('r^2 train data: ', r2_score(y_train, y_train_pred))
print('r^2 test data: ', r2_score(y_test, y_test_pred))
r^2 train data: 0.9996410420370064 r^2 test data: 0.9671842175732768
結果を見ていただくと分かるようにかなりの精度でガソリンの価格を予測できていることが確認できます。特に決定係数を見てみるとtrainデータでは約99.9%、testデータでも約96%と今回用意した説明変数でガソリンの価格をほとんど説明できていることが見て取れます。
さて次にどの変数が予測に寄与したのかについてXGBoostのFeature Importanceから見ていきましょう。
#Feature Importance
_, ax = plt.subplots(figsize=(12, 4))
xgb.plot_importance(model,
ax=ax,
importance_type='weight'
#show_values=False
)

このグラフからやはり1週前のレギュラーの価格が1週後のレギュラーの価格に一番寄与していることが確認できますね!
今回はそこまで説明変数が多くありませんが、コンペによってはこれが100を超えることもざらにあり、今回のようにFeature Importanceを確認し、それの上位何個の変数だけを取り出してモデルを再構築することで計算コストの低減等を図ることもあるので参考になれば幸いです。
まとめ
今回は実データを用いたガソリン価格の予測に挑戦していきました。
前処理もそこまで行わず高い精度を出すことが出来ましたが、実際のコンペなどでは前処理や変数同士を組み合わせるなどして新たな特徴量を作成することが必須になってきますので、それらについても今後また紹介できたらと思います。
コメント