Skip to main content

評価指標

扱う問題によって,重視すべき評価指標は変わる.

例えば,癌を検出するモデルを構築する場合,「癌の人を癌だと予測すること」が重要で あるため,再現率の高さを重視すべきである.

モデル構築のためには,それぞれの評価指標の計算方法のみではなく,目的変数などのデ ータセットの特徴を踏まえて,どれを使えば良いかを判断できることが必要となる.

なお,各指標で示すコードの多くは「Kaggle Grandmaster に学ぶ機械学習実践アプロー チ」から引用している.

分類問題での一般的な評価指標#

ここでは分類問題における一般的な評価指標について説明する.

説明で用いる用語をいかにまとめる.簡単に考えると,陽性を誤って予測すれば偽陽性, 陰性を誤って予測すれば偽陰性である.

  • 真陽性(True Positive)(TP)
    • 妊婦であると予測し,実際に妊婦である割合
  • 真陰性(True Negative)(TN)
    • 妊婦でないと予測し,実際に妊婦でない割合
  • 偽陽性(False Positive)(FP)
    • 妊婦であると予測したが,実際は妊婦でない割合
    • 第一種の過誤
  • 偽陰性(False Negative)(FN)
    • 妊婦でないと予測したが,実際は妊婦である場合
    • 第二種の過誤

混同行列(Confusion Matrix)

  • 二値分類や多クラス分類では,混同行列というのをよく見かける
  • 混同行列は,真陽性,真陰性,偽陽性,偽陰性で構成されている
def true_positive(y_true, y_pred):    tp = 0    for yt, yp in zip(y_true, y_pred):        if yt == 1 and yp == 1:            tp += 1    return tp
def true_negative(y_true, y_pred):    tn = 0    for yt, yp in zip(y_true, y_pred):        if yt == 0 and yp == 0:            tn += 1    return tn
def false_positive(y_true, y_pred):    fp = 0    for yt, yp in zip(y_true, y_pred):        if yt == 0 and yp == 1:            fp += 1    return fp
def false_negative(y_true, y_pred):    fn = 0    for yt, yp in zip(y_true, y_pred):        if yt == 1 and yp == 0:            fn += 1    return fn

正解率(Accuracy)#

  • 全予測中での正答率
TP+TNTP+FP+FN+TN\frac{TP + TN}{TP + FP + FN + TN}
  • 正や負と予測したデータの内,実際にそうであるものの割合
  • 妊婦の例: 全検査数に対する妊娠・非妊娠の正答率
def accuracy(y_true, y_pred):    correct_counter = 0    for yt, yp in zip(y_true, y_pred):        if yt == yp:            correct_counter += 1    return correct_counter / len(y_true)

適合率(Precision)#

  • 正予測の正答率
TPTP+FP\frac{TP}{TP + FP}
  • 正と予測したデータのうち,実際に正であるものの割合(別名:陽性適中率)
  • FP を減らしたいときに使う
  • 妊婦の例: 妊婦と診断した中で正しかった(本当に妊娠だった)率
def precision(y_true, y_pred):    tp = true_positive(y_true, y_pred)    fp = false_positive(y_true, y_pred)    precision = tp / (tp + fp)    return precision

再現率(Recall)#

  • 正に対する正答率
  • TPR(True Positive Rate)
TPTP+FN\frac{TP}{TP + FN}
  • 実際に正であるもののうち,正であると予測されたものの割合
  • FN が小さければ小さいほど上がる
  • 妊婦の例: 妊娠中の人で検査結果が正しかった(正しく妊娠と診断された)率
def recall(y_true, y_pred):    tp = true_positive(y_true, y_pred)    fn = false_negative(y_true, y_pred)    recall = tp / (tp + fn)    return recall
良いモデルは,再現率と適合率が高い

ほとんどのモデルは予測確率を出力する.分類結果を予測する際には,閾値を 0.5 にす るのが一般的.適合率と再現率の療法が良くなるような閾値を選ぶのは難しい,

再現率と適合率に着目したい場合,F 値を見るのが良い.

F 値(F1 score)#

  • 適合率と再現率の調和平均
    • 調和平均:逆数の算術平均の逆数 (Wikipedia
    • 例えば 4 と 6 の調和平均は,1/4 と 1/6 の平均が 5/24 なので,それをひっくり 返した 24/5(= 4.8)となる.
2×Precision×RecallPrecision+Recall\frac{2 \times Precision \times Recall}{Precision + Recall}
  • 適合率と再現率の両方の傾向を反映させた指標
    • 適合率と再現率はトレードオフの関係にあり,片方を高くしようとするともう片方が 低くなる
  • どちらの指標も同様に重要な場合,F 値を見るのが良い
def f1(y_true, y_pred):    p = precision(y_true, y_pred)    r = recall(y_true, y_pred)    score = 2 * p * r / (p + r)    return score

特異率(Specificity)#

  • 負に対する正答率
TNFN+TN\frac{TN}{FN + TN}
  • 実際に負であるもののうち, 負であると予測されたものの割合
  • 妊娠検査の例: 非妊娠の人で検査結果が正しかった(正しく非妊娠と診断された)率
  • 1 - FPR
def fpr(y_true, y_pred):    fp = false_positive(y_true, y_pred)    tn = true_negative(y_true, y_pred)    return fp / (tn + fp)
def specificity(y_true, y_pred):    return 1 - fpr(y_true, y_pred)

AUC(Area under the curve)#

  • 不均衡データに対応するための指標
  • ROC 曲線 の下側面積
  • 0~1 の値を取る
    • 1:完璧なモデルであることを意味する
    • 0.5:予測がランダムであることを意味する
    • 0:モデルが非常に悪いことを意味する

Log Loss(Binary Logarithmic Loss)#

  • 陽性か陰性かという分類の正確さ(Accuracy)よりも,陽性もしくは陰性である確率の 高さ(Probability)を評価スコアとして得たい場合がある
  • この場合には,正解率の代わりに LogLoss を使うと良い

他の代表的な指標#

  • Precision at k =P@k
  • Average precisionat k =AP@k
  • Mean average precision at k = MAP@k

回帰問題での一般的な評価指標#

ここでは回帰問題における一般的な評価指標について説明する.

前提#

  • 誤差 = 正解 - 予測値
  • 絶対誤差 = 絶対値 (正解 - 予測値)
  • 二乗誤差 = (正解 - 予測値)^2

平均絶対誤差(Mean Absolute Error)#

  • 各データに対する絶対誤差の平均を求める関数
  • L1 損失,L1 ノルム損失とも呼ばれる
  • 特徴
    • 回帰問題における出力層の評価関数,損失関数として用いられる
    • 絶対値しか計算しないので,元の数値から単位が変わらず,人間にとって解釈しやす い
    • 誤差を二乗しないので,外れ値の影響を受けにくい
    • 予測値=正解値の場合に,数学的に微分不可能となる
MAE=1ni=1nyi^yi\operatorname{MAE}=\frac{1}{n}\sum_{i=1}^n|\hat{y_i}-y_i|
def mae(y_true, y_pred):    error = 0    for yt, yp in zip(y_true, y_pred):        error += np.abs(yt - yp)    return error / len(y_true)
# numpydef mae(y_true, y_pred):    return np.mean(np.abs(y_true-y_pred))

平均二乗誤差(Mean Squared Error)#

  • 各データに対して「予測値と正解値の差(誤差)」の二乗値を計算し,その総和の平均 を求める関数
  • 特徴
    • 0 に近いほど,予測値が正しいことを示す
    • 最も一般的な損失関数,回帰問題における出力層の評価関数として利用されている
    • 誤差を二乗するため,誤差を過大に評価する(間違いを重要視する)
    • ↑ と裏返しで,外れ値に過敏に反応することになるので,損失関数として利用する場 合,過学習しやすい
MSE=1ni=1n(yiyi^)2\operatorname{MSE}=\frac{1}{n}\sum_{i=1}^n(y_i-\hat{y_i})^2
def mse(y_true, y_pred):    error = 0    for yt, yp in zip(y_true, y_pred):        error += np.abs(yt - yp) ** 2    return error / len(y_true)
def mse(y_true, y_pred):    squared_error = np.sum((y_true-y_pred)**2)    return 0.5 * squared_error

平均二乗対数誤差(Mean Squared Logarithmic Error)#

  • 各データに対して「予測値の対数と正解値の対数との差(対数誤差)」の二乗値を計算 し,その総和の平均を求める関数
  • 特徴
    • 主に回帰問題における出力層の評価関数として用いられる
    • 損失関数として使われることもある
    • MSE は誤差を過大評価していたが,MSLE では対数誤差を使うため,誤差を過大評価 しない
    • 対数誤差を二乗して単位が変わってしまうため,人間にとって単純には理解しづらい
MSLE=1ni=1n(log(1+yi^)log(1+yi))2\operatorname{MSLE}=\frac{1}{n}\sum_{i=1}^n(\log(1+\hat{y_i})-\log(1+y_i))^2
def msle(y_true, y_pred):    error = 0    for yt, yp in zip(y_true, y_pred):        error += (np.log(1 + yt) - np.log(1 + yp)) ** 2    return error / len(y_true)

平均平方二乗誤差(Root Mean Squared Error)#

  • MSE のルートを求める関数(二乗した単位を元に戻す)
    • RMSE = SQRT(MSE)
  • 対数平均二乗誤差(未紹介)も MSLE なので混合しないように注意
  • 特徴
    • 回帰問題で最も代表的な指標
    • 観測値と予測値の差が大きいと RMSE の値は大きくなり,外れ値の影響を受けやすい
RMSE=MSE=1ni=1n(yiyi^)2\operatorname{RMSE}=\sqrt{\operatorname{MSE}}=\sqrt{\frac{1}{n}\sum_{i=1}^n(y_i-\hat{y_i})^2}
def rmse(y_true, y_pred):    # 上で定義したmseを利用    return np.sqrt(mse(y_true, y_pred))

平均平方二乗対数誤差(Root Mean Squared Logarithmic Error)#

  • MSLE の結果に対するルートを求める関数
  • 真の値と予測値の対数をそれぞれとったあとの差の二乗の平方根を求める関数
RMSLE=MSLE\operatorname{RMSLE}=\sqrt{\operatorname{MSLE}}
def rmsle(y_true, y_pred):    return np.sqrt(np.mean(((np.log(y_true+1)-np.log(y_pred+1))**2)))

平均パーセンテージ誤差(Mean Percentage Error)#

  • パーセンテージ誤差 = ((正解-予測値)/正解)*100
MPE=100ni=1nyi^yiyi\operatorname{MPE}=\frac{100}{n}\sum_{i=1}^n\frac{\hat{y_i}-y_i}{y_i}
def mpe(y_true, y_pred):    error = 0    for yt, yp in zip(y_true, y_pred):        error += (yt - yp) / yt    return error / len(y_true)
def mpe(y_true, y_pred):    return np.mean((y_true-y_pred)/y_true)*100

平均絶対パーセンテージ誤差(Mean Absolute Percentage Error)#

  • 平均パーセンテージ誤差の絶対値を計算し,その総和の平均を求める関数
  • 実測値と予測値の誤差率(相対誤差)を算出する指標
  • 特徴
    • 誤差を%で分かりやすく伝えたいときに有用
    • 損失関数としては基本的に使われない
    • 予測精度は 0%に近いほど高い
    • MAE や RMSE は誤差の大きさで評価しているのに比べて,MAPE は割合で評価する
      • スケールが異なるデータの誤差を比較しやすい
      • スケールが変わらないデータ(時系列予測など)の場合は,MAE や RMSE のほうが 適切
    • 実測値に 0 が含まれる場合は使用できない
    • 使い所が難しい
MAPE=100ni=1nyi^yiyi\operatorname{MAPE}=\frac{100}{n}\sum_{i=1}^n\left|\frac{\hat{y_i}-y_i}{y_i}\right|
def mape(y_true, y_pred):    return np.mean(np.abs((y_pred-y_true)/y_true)) * 100

決定係数(R^2, R-squared)#

  • 線形回帰における回帰式のモデルが「正解データにどれくらい当てはまるか」の割合を 計算する関数
    • R^2 = 1 - 残差平方和/全平方和
  • 平均二乗誤差を使って,学習済みモデルの予測の当てはまり度を示す数値
  • 特徴
    • 線形回帰の評価関数として利用される
    • 基本的に 0~1.0 の数値をとり,1.0 に近づくほど精度の高い予測ができている
      • 感覚的な指標
        • 0.6 未満:正しく予測できているとは言い難い
        • 0.6~0.8:現実的な数値
        • 0.8~0.9:精度が高い
        • 0.9~:過学習の可能性あり
    • 無茶苦茶な予想をしている場合は 0 未満の値になるらしい(?)
    • 決定係数(R^2)の最大化 == MSE や RMSE の最小化
R2=1SeSxyR^2 = 1-\dfrac{S_{e}}{S_{xy}}
def r2(y_true, y_pred):    # 正解の平均    mean_true_value = np.mean(y_true)    numerator = denominator = 0    for yt, yp in zip(y_true, y_pred):        numerator += (yt-yp)**2        denominator += (yt-mean_true_value)**2    # 割合計算    ratio = numerator/denominator    # 1との差分    return 1 - ratio

コード参考:Kaggle Grandmaster に学ぶ機械学習実践アプローチ

参考文献#