Keras で自前の評価関数を作成する
Keras の出力で異なる活性化関数を使いそれぞれの損失関数を指定する - プログラマのメモ書き で、評価関数 を作成してみました。この評価関数で、bbox の評価値として Intersection over Union (IOU) を計算します。
作成したプログラムは、以下のところにあります。
bbox の評価値は、exists の正解値と予測値の組み合わせにより、以下のようになります。
exists の正解値 | exists の予測値 | bbox の評価値 |
---|---|---|
< 0.5 | <0.5 | 1.0 |
< 0.5 | >=0.5 | 0.0 |
>=0.5 | <0.5 | 0.0 |
>=0.5 | >=0.5 | bboxの正解値と予測値の IOU |
作成した評価関数ですが、exists の関数と bbox の関数があります。
exists の評価関数 exists_acc は、以下のようになります。
from keras.metrics import binary_accuracy y_acc_true_exists = None y_acc_pred_exists = None def exists_acc(y_true, y_pred): global y_acc_true_exists, y_acc_pred_exists y_acc_true_exists = y_true[:, 0] y_acc_pred_exists = y_pred[:, 0] return binary_accuracy(y_true, y_pred)
exists_acc では、keras.metrics.binary_accuracy を使って評価値を計算します。
また、この正解値と予測値は bbox の評価値の計算で使用するため、
グローバル変数に保存します:-(
bbox の評価関数 bbox_acc は、次の通りです。
def bboxes_acc(y_true, y_pred): global y_acc_true_exists, y_acc_pred_exists zeros = tf.zeros_like(y_acc_true_exists) ones = tf.ones_like(y_acc_true_exists) # 正解と予測の両方が存在しない場合、評価値は 1、それ以外は 0 both_not_exists = tf.logical_and( tf.less(y_acc_true_exists, 0.5), tf.less(y_acc_pred_exists, 0.5)) acc_1 = tf.where(both_not_exists, ones, zeros) # 正解と予測の両方が存在する場合、IOU を計算する。 both_exists = tf.logical_and( tf.greater_equal(y_acc_true_exists, 0.5), tf.greater_equal(y_acc_pred_exists, 0.5)) acc_2 = tf.where(both_exists, bboxes_acc_iou(y_true, y_pred), acc_1) return acc_2
bbox の IOU を計算する関数 bboxes_acc_iou は、次のようになります。
def bboxes_acc_iou(y_true, y_pred): x1, y1, w1, h1 = y_true[:, 0], y_true[:, 1], y_true[:, 2], y_true[:, 3] x2, y2, w2, h2 = y_pred[:, 0], y_pred[:, 1], y_pred[:, 2], y_pred[:, 3] zeros = tf.zeros_like(x1) w_I = tf.maximum(zeros, tf.minimum(x1 + w1, x2 + w2) - tf.maximum(x1, x2)) h_I = tf.maximum(zeros, tf.minimum(y1 + h1, y2 + h2) - tf.maximum(y1, y2)) I = w_I * h_I U = w1 * h1 + w2 * h2 - I return I / U
w_I と h_I は、二つの bbox の重なりの幅と高さです。
重なっていない場合は 0 になります。