Keras 分割网络自定义评估函数 - mean iou
Keras训练网络过程中需要实时观察性能,mean iou不是keras自带的评估函数,tf的又觉得不好用,自己写了一个,经过测试没有问题,本文记录自定义keras mean iou评估的实现方法。
计算 IoU
用numpy计算的,作为IoU的ground truth用作测试使用:
def iou_numpy(y_true,y_pred): intersection = np.sum(np.multiply(y_true.astype('bool'),y_pred == 1)) union = np.sum((y_true.astype('bool')+y_pred.astype('bool'))>0) return intersection/union复制代码
keras metric IoU
def iou_keras(y_true, y_pred): """ Return the Intersection over Union (IoU). Args: y_true: the expected y values as a one-hot y_pred: the predicted y values as a one-hot or softmax output Returns: the IoU for the given label """ label = 1 # extract the label values using the argmax operator then # calculate equality of the predictions and truths to the label y_true = K.cast(K.equal(y_true, label), K.floatx()) y_pred = K.cast(K.equal(y_pred, label), K.floatx()) # calculate the |intersection| (AND) of the labels intersection = K.sum(y_true * y_pred) # calculate the |union| (OR) of the labels union = K.sum(y_true) + K.sum(y_pred) - intersection # avoid divide by zero - if the union is zero, return 1 # otherwise, return the intersection over union return K.switch(K.equal(union, 0), 1.0, intersection / union)复制代码
计算 mean IoU
mean IoU 简便起见,选取 (0,1,0.05) 作为不同的IoU阈值,计算平均IoU
numpy 真实值计算
def mean_iou_numpy(y_true,y_pred): iou_list = [] for thre in list(np.arange(0.0000001,0.99,0.05)): y_pred_temp = y_pred >= thre iou = iou_numpy(y_true, y_pred_temp) iou_list.append(iou) return np.mean(iou_list)复制代码
Keras mean IoU
def mean_iou_keras(y_true, y_pred): """ Return the mean Intersection over Union (IoU). Args: y_true: the expected y values as a one-hot y_pred: the predicted y values as a one-hot or softmax output Returns: the mean IoU """ label = 1 # extract the label values using the argmax operator then # calculate equality of the predictions and truths to the label y_true = K.cast(K.equal(y_true, label), K.floatx()) mean_iou = K.variable(0) thre_list = list(np.arange(0.0000001,0.99,0.05)) for thre in thre_list: y_pred_temp = K.cast(y_pred >= thre, K.floatx()) y_pred_temp = K.cast(K.equal(y_pred_temp, label), K.floatx()) # calculate the |intersection| (AND) of the labels intersection = K.sum(y_true * y_pred_temp) # calculate the |union| (OR) of the labels union = K.sum(y_true) + K.sum(y_pred_temp) - intersection iou = K.switch(K.equal(union, 0), 1.0, intersection / union) mean_iou = mean_iou + iou return mean_iou / len(thre_list)复制代码
测试
## 随机生成预测值 y_true_np = np.ones([10,10]) y_pred_np = np.random.rand(10,10) ## 真实IoU值 print(f' iou : {iou_numpy(y_true_np, y_pred_np)}') print(f' mean_iou_numpy : {mean_iou_numpy(y_true_np, y_pred_np)}') y_true = tf.Variable(y_true_np) y_pred = tf.Variable(y_pred_np) ## 计算节点 iou_res = iou_keras (y_true, y_pred) m_iou_res = mean_iou_keras (y_true, y_pred) ## 变量初始化 init_op = tf.global_variables_initializer() with tf.Session() as sess: sess.run(init_op) ## 由于存在误差,结果在0.0000001范围内即可认为相同 result = sess.run(iou_res) print(f'result : {result} \nsame with ground truth: {abs(iou_numpy(y_true_np, y_pred_np) - result)< 0.0000001}') result = sess.run(m_iou_res) print(f'result : {result} \nsame with ground truth: {abs(mean_iou_numpy(y_true_np, y_pred_np) - result) < 0.0000001}') 复制代码
输出:
iou : 0.0 mean_iou_numpy : 0.5295 result : 0.0 same with ground truth: True result : 0.5295000076293945 same with ground truth: True
作者:为为为什么
链接:https://juejin.cn/post/7018847057246945317