Notice
Recent Posts
Recent Comments
Link
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

ufris

[Segmentation] IOU(Intersection Over Union) 본문

딥러닝/segmentation

[Segmentation] IOU(Intersection Over Union)

ufris 2018. 3. 1. 00:51

classification의 경우에 one hot을 한 라벨값의 arg_max 와 예측값의 arg_max 가 같은 경우를 평균내는 것으로 정확도를 산출합니다. 

segmentation는 라벨 이미지의 픽셀값과 예측해서 나온 이미지 픽셀값 하나 하나를 매치시켜 그것이 얼마나 겹치는지를 통해 정확도를 측정합니다.






설명보다 그림 한장이 이해가 더 빠릅니다. 위의 그림을 보시면 대충 어떤 느낌인지 이해가 되실 겁니다.


아래는 IOU에 대한 설명과 코드입니다. tensorlayer 라는 패키지 안에 IOU가 구현되어 있기 때문에 tensorlayer를 설치하시고 쓰시면 됩니다.


def iou_coe(output, target, threshold=0.5, axis=[1, 2, 3], smooth=1e-5):
    """Non-differentiable Intersection over Union (IoU) for comparing the
    similarity of two batch of data, usually be used for evaluating binary image segmentation.
    The coefficient between 0 to 1, 1 means totally match.

    Parameters
    -----------
    output : tensor
        A distribution with shape: [batch_size, ....], (any dimensions).
    target : tensor
        A distribution with shape: [batch_size, ....], (any dimensions).
    threshold : float
        The threshold value to be true.
    axis : list of integer
        All dimensions are reduced, default ``[1,2,3]``.
    smooth : float
        This small value will be added to the numerator and denominator, see ``dice_coe``.

    Notes
    ------
    - IoU cannot be used as training loss, people usually use dice coefficient for training, IoU and hard-dice for evaluating.
    """


# 바로 위의 설명에서 볼 수 있듯이 IOU 는 훈련시 loss 값으로 사용하지 않고 측정할 때만 쓰인다고 나와있습니다.

    pre = tf.cast(output > threshold, dtype=tf.float32)
    truth = tf.cast(target > threshold, dtype=tf.float32)
    inse = tf.reduce_sum(tf.multiply(pre, truth), axis=axis)  # AND
    union = tf.reduce_sum(tf.cast(tf.add(pre, truth) >= 1, dtype=tf.float32), axis=axis)  # OR
    ## old axis=[0,1,2,3]
    # epsilon = 1e-5
    # batch_iou = inse / (union + epsilon)
    ## new haodong
    batch_iou = (inse + smooth) / (union + smooth)
    iou = tf.reduce_mean(batch_iou)
    return iou


>> pre = tf.cast(output > threshold, dtype=tf.float32)
     truth = tf.cast(target > threshold, dtype=tf.float32)
output에는 마지막에 모델을 돌리고 나온 예측한 이미지 픽셀값들을 넣습니다. 예측한 이미지 픽셀값들은 라벨값과 비슷하게 나오려고 하는데 이 예측한 픽셀값 전체를 sigmoid 나 softmax 를 써서 0 ~ 1 사이의 값들로 변환합니다. 즉, 확률로 만드는 것이죠. 이것이 threshold(경계값) 0.5 보다 크면 1 로, 0.5 보다 작으면 0 으로 변환시킵니다. 


>> inse = tf.reduce_sum(tf.multiply(pre, truth), axis=axis)  # AND

변환시킨 값들을 pre 와 truth 에 넣고 그 값들을 곱한 것을 inse 라는 변수에 넣습니다. 두 값을 곱하는 이유는 라벨값과 예측값이 겹치는 곳을 나타내기 위해서 입니다. 즉, 1 * 1 = 1 이지만 0 * 1 or 1 * 0 = 0 이게 됩니다. 둘 다 1인곳만 남게 되죠.  


>> union = tf.reduce_sum(tf.cast(tf.add(pre, truth) >= 1, dtype=tf.float32), axis=axis)  # OR

두 값을 더한 결과를 union 이라는 변수에 담는데 이것은 둘 중에 어느 곳이라도 1이 있으면 변수에 담아 전체 이미지를 나타내겠다는 것입니다. 


intersection 부분을 union 부분으로 나눠 평균을 내면 그것이 IOU 되는 것입니다(smooth 는 union 부분이 0인 경우 에러가 나기 때문에 에러를 방지하고자 아주 작은 수를 더해주는 것입니다). 



'딥러닝 > segmentation' 카테고리의 다른 글

[파일 전처리] mha 파일 로드  (0) 2018.02.28
[Segmentation] H-DenseUnet 2D  (0) 2018.02.28