機械学習のメトリクス1【AAAMLP】
AAAMLP
今回は、機械学習のメトリクス、評価指標について学んだことを記録します。
AAAMLP (Approaching (Almost) Any Machine Learning Problem)という書籍で勉強した内容の整理です。
この書籍は多くの言語に翻訳されていて、2021年8月に「Kaggle Grandmasterに学ぶ 機械学習 実践アプローチ」として日本語版も発売されています。
Motivtion
私は、近い将来に海外で働いてみたいと思っています。
そのためには、グローバルに通用する資格や実績が必要です。
AWSも業務で使うため考えましたが、会社で資格を取る機会があるかなと思うのでそのときに勉強しようと思います。 あんまり自習するのはおもしろくなさそうなのもあり。
とりあえずは、Kaggleを通して機械学習を勉強しようかなと思います。
Metrics
まずは、2クラス問題に関するメトリクスを見ていきます。 書いてみたら長すぎたので、マルチクラス問題、マルチラベルのメトリクスは分けて書きます。
Confusion Matrix
まず、予測結果の分類を紹介します。
Confusion Matrixとは、予測と真値の関係を表す行列です。 2クラスの場合は2×2の行列です。 各成分をTP, TN, FP, FNと呼びます。
これ、予測と真値どっちがTrue or FalseでどっちがPositive or Negativeなのかすぐ忘れるんですよね。。
TP: True Positive
真値1に対し予測も1の場合、つまりPositiveな予測がTrueだった場合がTPです。
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
TN: True Negative
真値0に対し予測も0の場合、つまりNegativeな予測がTrueだった場合がTNです。
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
FP: False Positive
真値0に対し予測も1の場合、つまりPositiveな予測がFalseだった場合がFPです。
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
FN: False Negative
真値1に対し予測も0の場合、つまりNegativeな予測がFalseだった場合がFNです。
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
単純にの割合です。 Confusion matrixの成分を使って書くと、以下のように書けます。
コードは、以下の通りです。
accuracy_v2
では、Confusion matrixの成分を使っています。
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)
def accuracy_v2(y_true, y_pred): tp = true_positive(y_true, y_pred) fp = false_positive(y_true, y_pred) tn = true_negative(y_true, y_pred) fn = false_negative(y_true, y_pred) accuracy_score = (tp + tn) / (tp + tn + fp + fn) return accuracy_score
このAccuracyには問題があります。 それは、データセットに偏りがある場合に、モデルのよさを表現できないことです。
例えば、2クラス問題で90%の真値が1のデータがあるとします。 このとき、すべて1と予測する、つまり、何も考えていないような場合でも、Accuracyは0.9と高い値をとります。
このような場合には、Confusion Matrixの各成分を見る必要があります。
Precision
予測1の正解率を表します。
コードは、以下の通りです。
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
真値1の正解率を表します。
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
F1
PrecisionとRecallの両方が高い値をとるモデルがよいモデルといえます。
そこで、Precision とRecallを重み付き平均により合わせたメトリクスがF1です。
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
TPR: True Positive Rate
TPRはRecallと同じ定義で、sensitivityを表します。
def tpr(y_true, y_pred): return recall(y_true, y_pred)
FPR: False Positive Rate
1-FPRをTNR (True Negative Rate)と呼び、specificityを表します。
def fpr(y_true, y_pred): fp = false_positive(y_true, y_pred) tn = true_negative(y_true, y_pred) return fp / (tn + fp)
ROC curve: Receiver Operating Characteristic curve
2クラスで閾値を変化させた場合のTPR-FPRのグラフです。
この曲線の積分値をAUC (Area Under Curve)と呼び、これも指標になる。
AUC=1は、完璧なモデルを意味する。しかし実際には、Validationでミスをしている可能性が高い。
AUC=0は、すべてを誤るモデルを意味する。反転することでAUC=1と等しくなるため、AUC=1と同じくValidationでミスをしている可能性が高い。
AUC=0.5は、完全にランダムなモデルを意味する。まったくあてにならないモデルであるといえる。
具体的に、PositiveサンプルとNegativeサンプルをそれぞれランダムに取り出したとき、PositiveサンプルがNegativeサンプルより高い予測がされる(つまり正しい予測)確率をAUCは表します。
問題によって、結果として確率が欲しい場合と、クラス(0 or 1)が欲しい場合があります。 もしクラスが欲しい場合は、適切な閾値を選ぶ必要があります。
この閾値の選択に、ROCカーブは有用です。 TPRが高くFPRが小さい、具体的には、グラフの左上の角の閾値がベストです。
Log Loss
2クラスの場合の定義を下に示します。
ここで、はそれぞれ、真値、予測値を表しています。
Log Lossは、誤った予測や大きく異なる予測値に対し、大きなペナルティを課します。 たとえ正解しても、信頼度が低ければ値が小さくなります。
例えば、精度100%の予測をした場合でも、予測値が閾値付近で信頼度が高くない場合、Log Lossは大きくなります。
def log_loss(y_true, y_proba): epsilon = 1e-15 loss = [] for yt, yp in zip(y_true, y_proba) yp = np.clip(yp, epsilon, 1 - epsilon) temp_loss = - 1.0 * (yt * np.log(yp) + (1 - yt) * np.log(1 - yp)) loss.append(temp_loss) return np.mean(loss)
Conclusion
一応勉強したことを記録しようとしたら、長すぎて3つに分けました。 それでもかなり長い。
技術ブログをやっている方々はどんなパイプラインでやっているのかすごく気になりますね。 一つ書くだけで心折れそうになる。
とりあえず2クラス問題を前提に、機械学習のメトリクスを整理できました。 次の多クラス問題と、マルチラベルのメトリクスは、今回出てきたメトリクスをもとにしてできているので、少しは楽になるかな。
Link
GitHub - abhishekkrthakur/approachingalmost: Approaching (Almost) Any Machine Learning Problem