EnsekiTT Blog

EnsekiTTが書くブログです。

Pythonで機械学習をやった時にその予測結果を評価する誤差関数の話

つまりなにしたの?

機械学習ディープラーニングだっ!と予測アルゴリズムを弄くりまわしたくなる気持ちをぐっと抑えて、
構築したアルゴリズムの予測結果を評価するための誤差(Error)の話。
ってことでデータ解析のコンテストとかでもよく使う誤差とその派生を幾つかまとめて、
すぐ使えるように式と Python (Numpy)コードで残しておくことにした。

f:id:ensekitt:20171127221853j:plain

今回紹介する誤差

  • Absolute Error
  • Mean Absolute Error
  • Mean Squared Error
  • Mean Consequential Error
  • Root Mean Squared Error
  • Root Mean Squared Persentage Error
  • Root Mean Squared Logarithmic Error

一応経緯

先日、「仮想通貨の値動きって予測できないのかな!?」って話を他業種混じった飲み会で聞かれた。
僕、ファイナンスは門外漢なので、「やって評価してみれば良いともいますよ!PDCAっすよPDCA〜(ヘラヘラ」という雑っぷりを発揮。

自分でやってみるものの、最近(2017年11月17日-27日 Bitcoin)上がり調子過ぎてトレンドだけは当たる。
ただ、値動きが激しいので外す時のインパクトがでかい。この時はファイナンス扱いなのかなーってことでMSEを使ってみていた。

実際にやるなら、売買額と時期までちゃんと意思決定するようにして過去データでシミュレーションを回すことをおすすめする。

共通説明

  • 概要
  • コード

{ \displaystyle y_i, \hat{y}_i}はそれぞれi番目の実測データと実測より前に実施した予測データ(コードではnumpy.arrayとして扱う)

# 長さ
length = 100
# ノイズ
noise = np.r_[np.zeros(50), (np.random.rand(50)-0.5)*0.5]
print('Noise info')
print('Mean: ', str(np.mean(noise)))
print('Var: ', str(np.var(noise)))
print('Std: ', str(np.std(noise)))
# 実測データ
y = np.array([np.sin(2 * np.pi * i * 0.01) for i in range(length)]) + noise + 2
# 予測データ
y_pred = np.array([np.sin(2 * np.pi * i * 0.01) for i in range(length)]) + 2

f:id:ensekitt:20171127210424p:plain

Absolute Error

各誤差の絶対値の総和。AEとか絶対誤差とかいう。

{ \displaystyle
{\rm AE} = \sum_{i=0}^{n} |y_i - \hat{y}_i|
}

コード

AE = np.sum(np.abs(y-y_pred))

Mean Absolute Error

各誤差の絶対値の平均値。MAEとか平均絶対誤差とかいう。
予測の間違っている量が重要な時につかう。

{ \displaystyle
{\rm MAE} = \frac{1}{n} \sum_{i=0}^{n} |y_i - \hat{y}_i|
}

コード

MAE = np.sum(np.abs(y-y_pred))

Mean Squared Error

各誤差の2乗の平均値。MSEとか平均二乗誤差とかいう。
ファイナンス分野でよく使うらしい。

{ \displaystyle
{\rm MSE} = \frac{1}{n} \sum_{i=0}^{n} (y_i - \hat{y}_i)^2
}

コード

MSE = np.sum((y-y_pred)**2)

Mean Consequential Error

教師と予測が一致したら0、一致しなかったら1とした時の平均値。
実数だと必要に応じて値を丸めたり、値域を指定しないと意味をなさない。
日本語はよくわからないけど平均重大誤差?MEC?とかになるんだろうか。
これはKaggleのサイトで見かけた。

{ \displaystyle
{\rm MCE} = \frac{1}{n}\sum_{y_i \neq \hat{y}_i } 1
}

コード

MCE = np.mean(np.abs(y-y_pred))

Root Mean Squared Error

すべての誤差の平方根の平均。結構よく使われる。
MAEに比べて大きな誤差に敏感。RMSEとか平均平方二乗誤差とかいう。
よく使われるから日本語訳がいろいろあってRMSEっていうのが無難だと持ってる

{ \displaystyle
{\rm RMSE} = \sqrt{ \frac{1}{n} \sum_{i = 1}^n (y_i - \hat{y}_i)^2 }
}

コード

RMSE = np.sqrt(np.mean((y-y_pred)**2))

Root Mean Squared Persentage Error

RMSEに似ているけど今度は割合の差の二乗誤差。平方平均二乗誤差率とかいう。
分子が0になりそうなとき注意する。

{ \displaystyle
{\rm RMSPE} = \Biggl( 
 \sqrt{
  \frac{1}{n} \sum_{i=1}^n \biggl\{ \frac{y_i-\hat{y}_i}{y_i} \biggr\}^2
 }
\Biggr) \times 100
}

コード

RMSPE = np.sqrt(np.mean(((y-y_pred)/y)**2))*100

20190524: @s_tyd_さんよりnp.sqrt漏れのご指摘をいただき訂正いたしました。

Root Mean Squared Logarithmic Error

対数の差をとった平方平均二乗誤差。RMSLEとか対数平方平均二乗誤差とかいう。
対数正規分布に近い分布で使うみたい。KaggleのMercariの売価予測の指標がこれだった。

{ \displaystyle
{\rm RMSLE} = \sqrt{ \frac{1}{n} \sum_{i=1}^{n} \biggl( \log(y_i + 1) - \log(\hat{y}_i + 1) \biggr)^2 }
}

コード

RMSLE = np.sqrt(np.mean(((np.log(y+1)-np.log(y_pred+1))**2)))

20190524: @s_tyd_さんよりnp.sqrt漏れのご指摘をいただき訂正いたしました。

全実行したコードはこちら

blog/Error.ipynb at master · EnsekiTT/blog · GitHub
github.com
ちなみに、scikitとかインポートすればほぼ全部関数が用意されてるんじゃないかな。*1

クリエイティブ・コモンズ・ライセンス
この 作品 は クリエイティブ・コモンズ 表示 4.0 国際 ライセンスの下に提供されています。