Ccmmutty logo
Commutty IT
0 pv2 min read

メジャーな評価指標まとめ

https://cdn.magicode.io/media/notebox/mitchel-boot-hOf9BaYUN88-unsplash.jpg
予測モデルの評価指標に関して、最適化も含め学ぶ。

回帰問題(Regression)に使われる評価指標

  • MSE, RMSE, R-squared
  • MAE
  • (R)MSPE, MAPE
  • (R)MSLE
notation
  • NN : オブジェクト数
  • yRNy\in\mathbb{R}^N : ターゲット値のN次元ベクトル
  • y^RN\hat y\in\mathbb{R}^N : 予測値のN次元ベクトル
  • yiRy_i\in\mathbb{R} : オブジェクトxix_iのターゲット値
  • y^iR\hat y_i\in\mathbb{R} : オブジェクトxix_iの予測値

MSE, RMSE, R-squared

MSE: Mean Square Error

MSE(y,y^)=1Ni=1N(yiy^i)2MSE(y,\hat y)=\frac{1}{N}\sum^N_{i=1}(y_i-\hat y_i)^2
評価指標の特性を考える際、一定の予測値y^i=α\hat y_i = \alphaがどの値をとる時に一番良い評価指標の値が得られるかを考えると良く、今回は
minαf(α)=1Ni=1N(αyi)2 \min_{\alpha} f(\alpha) = \frac{1}{N} \sum_{i=1}^N (\alpha - y_i)^2
のようにα\alphaに関して微分可能な関数f(α)f(\alpha)の最小化問題に帰結できます。これを満たすα\alpha^*の必要条件は
dfdαα=α=0 \frac{d f}{d \alpha}\bigg|_{\alpha=\alpha^*} = 0
となります。よってこれを解くと、
dfdαα=α=2Ni=1N(αyi)=0 \frac{d f}{d \alpha}\bigg|_{\alpha=\alpha^*} = \frac{2}{N} \sum_{i=1}^N (\alpha^* - y_i) = 0
2Ni=1Nα2Ni=1Nyi=0 \frac{2}{N} \sum_{i=1}^N \alpha^* - \frac{2}{N} \sum_{i=1}^N y_i = 0
α1Ni=1Nyi=0 \alpha^* - \frac{1}{N} \sum_{i=1}^N y_i = 0
より、
α=1Ni=1Nyi(=yˉ) \alpha^* = \frac{1}{N} \sum_{i=1}^N y_i(=\bar y)
α\alpha^*における2次導関数 d2fdα2\frac{d^2 f}{d \alpha^2} は正なのでMSEにおけるbest constantは、ターゲット値の平均(target mean value)となります。

RMSE: Root Mean Square Error

RMSE=MSE RMSE=\sqrt{MSE}
RMSEy^i=12MSEMSEy^i \frac{\partial RMSE}{\partial\hat y_i}=\frac{1}{2\sqrt{MSE}}\frac{\partial MSE}{\partial\hat y_i}

R-squared

R2=1MSE1Ni=1N(yiyˉ)2 R^2=1-\frac{MSE}{\frac{1}{N}\sum^N_{i=1}(y_i-\bar y)^2}

最適化の仕方

MSE・RMSE・R-squaredは基本的に同じ意味を持つ評価指標で、また最適化する際もそのまま目的関数として使用することができます。詳しくは各ライブラリのdocを読みましょう。

MAE: Mean Absolute Error

MAE(y,y^)=1Ni=1Ny^iyi MAE(y, \hat y) = \frac{1}{N} \sum_{i=1}^N |\hat y_i - y_i|
同様にbest constant α\alpha^*を求めてみましょう。
minαf(α)=1Ni=1Nαyi \min_{\alpha} f(\alpha) = \frac{1}{N} \sum_{i=1}^N |\alpha - y_i|
ここで xdx=sign(x) \frac{\partial |x|}{dx} = sign(x)signsign符号関数, signum functionを指す)であるので、
dfdαα=α=1Ni=1Nsign(αyi)=0 \frac{d f}{d \alpha}\bigg|_{\alpha=\alpha^*} = \frac{1}{N} \sum_{i=1}^N sign(\alpha^* - y_i) = 0
定数項を無視すると、
g(α)=i=1Nsign(αyi)=0 g(\alpha^*) = \sum_{i=1}^N sign(\alpha^* - y_i) = 0
をみたす α\alpha^* を求めればよいことが分かります。例えばここで、ターゲットのN次元ベクトルがy=[3,1,1.5,0,1,2,3]y=[-3,-1,-1.5,0,1,2,3]とすると、g(α)g(\alpha)のグラフは以下のようになります。
python
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

def sgn(x,y):
  if x < y:
    return -1
  elif x == y:
    return 0
  else:
    return 1

def g(alpha,y):
  total = 0
  for i in y:
    total += sgn(alpha,i)
  return total

y = np.array([-3,-1,-1.5,0,1,2,3])
alpha = np.arange(y.min()-0.5,y.max()+0.5,0.01)
median = np.median(y)

gs_a = []
for a in alpha:
  gs_a.append(g(a,y))

gs_y = []
for yi in y:
  gs_y.append(g(yi,y))

plt.figure(figsize=(10,7))
plt.xlabel("α")
plt.ylabel('g(α)')
plt.xlim(alpha.min()-0.1,alpha.max()+0.1)
plt.ylim(-len(y)-0.5,len(y)+0.5)
plt.plot(alpha,gs_a,label='g(α)')
plt.scatter(y,gs_y,label='g($y_i$)')
plt.scatter(median,g(median,y),label='median')
plt.legend(loc='upper left')
plt.show()
png
このように、値がN回不連続的に飛び飛びの値をとることがわかり、0になるには約N2\frac{N}{2}回飛ばなければならないことが分かります。グラフの様にその値はターゲットの中央値(target median)となることが分かります。Nが偶数奇数の場合分けが必要ですが、いずれの場合もbest constantはtarget medianとなります。
note: MAEのbest constantはターゲットの中央値であることから、MAEはターゲットの外れ値(outliers)の影響を受けずらいことが分かる。一方MSEはoutliersの影響を受けやすい。よって、ターゲットにouteliersを含む場合はMAEがよりrobustな評価指標と言える。

最適化の仕方

MAEも目的関数として扱うことができますが、y^i=yi\hat y_i=y_iの時に微分可能でないのでsmoothingして0に近いエラーに関しても処理できるようにする必要があります。このsmoothingには様々な方法がありますが、有名なものにHuber lossがあります。0に近い時はMSE、エラーが大きい値ではMAEのような挙動を示す関数です。詳しくは各ライブラリのdocを読みましょう。

(R)MSPE, MAPE: Percentage Error

単純なMSEやMAEでは、ターゲットの値が大きい時に同じ精度の予測値に対して過小評価されてしまいます。例えば、
MSE(10,9)=1 MSE(10,9)=1
MSE(1000,900)=10000 MSE(1000,900)=10000
のように同じ90%の予測精度でもMSEの値が大きくなることが分かります。そこで、MSE・MAEそれぞれに対し、ターゲット値の逆数で重みを付けた評価指標がそれぞれMSPE・MAPEという訳です。
MSPE(y,y^)=100%Ni=1N(yiy^iyi)2 MSPE(y,\hat y)=\frac{100\%}{N}\sum^N_{i=1}(\frac{y_i-\hat y_i}{y_i})^2
MAPE(y,y^)=100%Ni=1Nyiy^iyi MAPE(y,\hat y)=\frac{100\%}{N}\sum^N_{i=1}|\frac{y_i-\hat y_i}{y_i}|
それではそれぞれのbest constantはどの値をとるのでしょうか? MSPE、MAPEそれぞれその値は重み付け平均値、重み付け中央値を取ります。小さい値のターゲットに重みを大きくつけた新しいターゲット値の平均、中央値という訳です。ターゲット値にwi=1/yii=1N1/yiw_i=\frac{1/y_i}{\sum^N_{i=1}1/y_i}を付加した後、MSE・MAE同様の議論をすれば証明できます。

最適化の仕方

MSPE・MAPEを直接モデル最適化の目的関数として扱うことは難しく、以下のステップが必要となります。
  1. ターゲットの値を用いて各オブジェクトxix_iに対してSample weights: wiw_iを対応させる
  2. その重みに従って新たに元のデータからサンプリングを行う
  3. サンプリングされた新たなデータセットに対して、MSE・MAEを適用する
wiw_iに関してはMSPE・MASEについてそれぞれ、
MSPE:wi=1/yi2i=1N1/yi2 MSPE: w_i=\frac{1/y_i^2}{\sum^N_{i=1}1/y_i^2}
MAPE:wi=1/yii=1N1/yi MAPE: w_i=\frac{1/y_i}{\sum^N_{i=1}1/y_i}
となります。
note: wiw_iの合計は必ずしも1である必要はない。また、サンプル数はもとのデータセットのオブジェクト数Nを超えても良い。

(R)MSLE: (Root) Mean Square Logarithmic Error

RMSLE(y,y^)=1Ni=1N(log(yi+1)log(y^i+1))2=RMSE(log(y+1),log(y^+1))=MSE(log(y+1),log(y^+1)) RMSLE(y,\hat y)=\sqrt{\frac{1}{N}\sum^N_{i=1}(log(y_i+1)-log(\hat y_i+1))^2} =RMSE(log(y+1),log(\hat y+1))=\sqrt{MSE(log(y+1),log(\hat y+1))}
こちらもターゲットのスケールによる誤差の見積もり変化に対して、頑強な評価指標です。MSEの対数バージョンということですね。
ではbest constantはどの値をとるかというとこの場合はlog spaceでのtarget meanです。log spaceでの平均が分かった後にその値を指数化して戻してあげる必要がありますがコンセプトはMSEと変わりません。

最適化の仕方

これも単純に目的関数としては使えないので以下のステップが必要です。
  1. ターゲット値をlog spaceに変換する; zi=log(yi+1)z_i=log(y_i+1)
  2. 変換された新しいターゲットに対して、目的関数をMSEに設定しモデルをfitする
  3. 予測値を指数化し想定されるスケールに戻す; y^i=exp(z^i)1\hat y_i=exp(\hat z_i)-1
詳しくは各ライブラリのdocを読みましょう。

分類問題(Classification)に使われる評価指標

  • Accuracy
  • Logarithmic Loss
  • Area under ROC curve
  • (Quadratic weighted) Kappa
notation
  • NN : オブジェクト数
  • LL : カテゴリ数
  • yy : 真値
  • y^\hat y : 予測値
  • [a=b][a=b] : 1 if a=b else 0

Accuracy

Accuracy=1Ni=1N[y^i=yi] Accuracy=\frac{1}{N}\sum^N_{i=1}[\hat y_i=y_i]
この指標はクラス予測がどのくらいの頻度で正しいか表しています。best constantは最も現れる頻度の高いカテゴリ値です。例えばターゲットに猫が10、犬が90あるとしたら、常にイッヌと予測したら0.9が得られ最大となります。

最適化の仕方

  1. 何でもいいのである評価指標でモデルを最適化・fitする
  2. 最適化済みのモデルの各カテゴリに対する確率予測値に対して、閾値を調節する
閾値の最適解によってそのモデルの実力を最も発揮したAccuracyが求められます。 詳しくは各ライブラリのdocを読みましょう。

Logarithmic Loss

Binary
LogLoss=1Ni=1Nyilog(y^i)+(1yi)log(1y^i) LogLoss=-\frac{1}{N}\sum^N_{i=1}y_ilog(\hat y_i)+(1-y_i)log(1-\hat y_i)
Multiclass
LogLoss=1Ni=1Nl=1Lyillog(y^il) LogLoss=-\frac{1}{N}\sum^N_{i=1}\sum^L_{l=1}y_{il}log(\hat y_{il})
2値分類と多クラス分類のタスクで上のように書き分けられますが、多クラス分類の方は一般化されている形になっています。実践的にはloglogの中身xxに対して1015x1101510^{-15}\leqq x \leqq 1-10^{-15}のようにクリッピングした関数
LogLoss=1Ni=1Nl=1Lyillog(min(max(y^il,1015),11015)) LogLoss=-\frac{1}{N}\sum^N_{i=1}\sum^L_{l=1}y_{il}log(min(max(\hat y_{il},10^{-15}),1-10^{-15}))
が使われます。下のグラフはターゲットが0の時の予測確率値とLogLossを示していますが、誤ったクラスの予測確率値が大きいほど、つまり間違った答えをはっきりこれだと言ってしまうほど大きいペナルティが課せられることが分かります。
python
y_pred = np.arange(0,1,0.01)

def logloss(y_pred):
  return -np.log(1-y_pred)

plt.figure(figsize=(10,7))
plt.xlabel("$\hat y$")
plt.ylabel('Loss')
plt.xlim(-0.01,1.01)
plt.ylim(-0.1,6)
plt.plot(y_pred,logloss(y_pred),label='LogLoss')
plt.legend(loc='upper left')
plt.show()

Discussion

コメントにはログインが必要です。