Skip to content
This repository has been archived by the owner on Jul 2, 2021. It is now read-only.

Change eval_semantic_segmentation #217

Merged
merged 17 commits into from
Jun 2, 2017

Conversation

yuyu2172
Copy link
Member

No description provided.

@yuyu2172
Copy link
Member Author

I think the return values of eval_* should be reconsidered.

There are three types of return values

  • mean of Metric (e.g. mIoU mAP)
  • Metric (e.g. IoU, AP for each class)
  • intermediate values (e.g. confusion matrix, prec, rec)

In my opinion, returning a tuple of (metric, intermediate1, ..., intermedite n) is good.
So in that case, eval_semantic_segmentation returns iou, confusion and
eval_detection_voc returns ap, prec, rec.

@yuyu2172
Copy link
Member Author

I will fix the interface of this function after its design is agreed upon.

@Hakuyume
Copy link
Member

Hakuyume commented Jun 1, 2017

I think there are two groups of metrics/intermediate values.
First group is values that computed for each class. For example, AP, prec and rec (detection) and IoU ( (semantic segmentation).
Second group is values that computed for the entire classes. For example, confusion of semantic segmentation. This is not an mean value of any class-wise values. I guess your proposal can not treat this group. How do you think of it?

@yuyu2172 yuyu2172 force-pushed the eval-semantic-segmentation-change branch from d07751c to ec2ac61 Compare June 1, 2017 10:58
@yuyu2172
Copy link
Member Author

yuyu2172 commented Jun 1, 2017

Updated interface.

gt_labels = iter(gt_labels)

confusion = np.zeros((n_class, n_class), dtype=np.int64)
while True:
Copy link
Member

@Hakuyume Hakuyume Jun 1, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can write this loop as follows.

pred_labels = iter(pred_labels)
gt_labels = iter(gt_labels)

for pred_label, gt_label in six.moves.zip(pred_labels, gt_labels):
     ...

# Check if all iterators are same length.
for iter_ in (pred_labels, gt_labels):
    # If one of them has more items, we can pop more item from it.
    # This code assumes any iterator does not contain None as its item.
    if next(iter_, None) is not None:
        raise ValueError('Length of input iterables need to be same.')

"""Collect confusion matrix.

Args:
pred_label (iterable of numpy.ndarray): A collection of predicted
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pred_label -> pred_labels

is :math:`(H, W)`. :math:`H` and :math:`W`
are height and width of the label.
For example, This is an array of shape :math:`(N, H, W)`.
gt_label (iterable of numpy.ndarray): A collection of ground
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gt_label -> gt_labels

labels. The shape of a label array
is :math:`(H, W)`. :math:`H` and :math:`W`
are height and width of the label.
For example, This is an array of shape :math:`(N, H, W)`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This example is not good because this function can take images whose shapes are different each other. (N, H, W) sounds that all images should have the same shape. How about [label0, label1, ...], where label0.shape = (H0, W0), label1.shape = (H1, W1) .. ?

truth label. The shape of a ground truth label array is
:math:`(H, W)`. The corresponding prediction label should
have the same shape.
A pixel with value "-1" will be ignored during evaluation.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"-1" -> :obj:-1

A confusion matrix. Its shape is :math:`(n\_class, n\_class)`.
The :math:`(i, j)` th element corresponds to the number of times
a pixel with ground truth class :math:`i` is predicted
to be class :math:`j`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about the number of pixels that is labelled as class i in ground truth and predicted as class j?

The definition of Intersection over Union (IoU) is as follows.

* :math:`\\text{IoU of the i-th class} = \
\\frac{N_{ii}}{\\sum_{j=1}^k N_{ij} + \\sum_{j=1}^k N_{ji} - N_{ii}}`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps, we need denote the definition of N_{ij}.

'main/loss', 'main/mean_iou', 'main/mean_accuracy',
'validation/main/loss',
'validation/main/mean_iou', 'validation/main/mean_accuracy']),
'main/loss']),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you remove validation/main/loss?

def _pred_iterator():
pred_labels = np.repeat([[[1, 1, 0], [0, 0, 1]]], 2, axis=0)
for pred_label in pred_labels:
yield pred_label
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use iter() to make an iterator from an iterable.

@yuyu2172 yuyu2172 force-pushed the eval-semantic-segmentation-change branch from 5cf0add to a390dfc Compare June 2, 2017 02:33
@yuyu2172 yuyu2172 force-pushed the eval-semantic-segmentation-change branch from a390dfc to babf7c9 Compare June 2, 2017 02:36
@yuyu2172
Copy link
Member Author

yuyu2172 commented Jun 2, 2017

Thanks. I fixed the code.

are height and width of the label.
For example, this is a list of labels
:obj:`[label_0, label_1, ...]`, where
:obj:`label_i.shape= (H_i, W_i)`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:obj:label_i.shape= (H_i, W_i) -> :obj:label_i.shape = (H_i, W_i) (space)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks

mask = (gt_label >= 0) & (gt_label < n_class)
confusion += np.bincount(
n_class * gt_label[mask].astype(int) +
pred_label[mask], minlength=n_class**2).reshape(n_class, n_class)
Copy link
Member

@Hakuyume Hakuyume Jun 2, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can expand the confusion matrix dynamically. n_class can be removed.

n_class = 0
...
lb_max = gt_label.max()
if  lb_max >= n_class:
    expanded_confusion = np.zeros((lb_max + 1, lb_max + 1))
    expanded_confusion[0:n_class, 0:n_class] = confusion

    n_class = lb_max + 1
    confusion = expanded_confusion

This expansion may affect performance. But I think it will be ignorable because neural networks are much slower.
How do you think of it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That code seems simple enough.
I left it as is because I thought the code gets too complex.

I will try it.

@yuyu2172 yuyu2172 force-pushed the eval-semantic-segmentation-change branch from 9f45e1c to 41198b3 Compare June 2, 2017 05:37
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. autofunction:: eval_semantic_segmentation_iou

calc_semantic_segmentation_confusion
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not an alphabetical order. I guess you put these functions here because they are helper functions of eval_semantic_segmentation_iou. How about nesting these items to show the hierarchy more explicitly?

"""Collect a confusion matrix.

The number of classes :math:`n\_class` is computed as the maximum
class id among :obj:`pred_labels` and :obj:`gt_labels`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It sounds n_class = max(pred_labels, gt_labels). as -> from? Perhaps, an equation like n_class = max(pred_labels, gt_labels) + 1 will be helpful.

is :math:`(H, W)`. :math:`H` and :math:`W`
are height and width of the label.
gt_labels (iterable of numpy.ndarray): A collection of ground
truth label. The shape of a ground truth label array is
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

label -> labels

# Dynamically expand the confusion matrix if necessary.
lb_max = np.max((pred_label, gt_label))
if lb_max >= n_class:
expanded_confusion = np.zeros
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this line?

lb_max = np.max((pred_label, gt_label))
if lb_max >= n_class:
expanded_confusion = np.zeros
expanded_confusion = np.zeros((lb_max + 1, lb_max + 1))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps it is better to use dtype=np.int64 option. You are using this option at L.36 but it will be overwritten by expansion.

confusion = expanded_confusion

# Count statistics from valid pixels.
mask = (gt_label >= 0) & (gt_label < n_class)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(gt_label < n_class) is always true because n_class > lb_max = np.max((pred_label, gt_label)).

@yuyu2172 yuyu2172 force-pushed the eval-semantic-segmentation-change branch from 1be7061 to 4bfbcdd Compare June 2, 2017 07:31
@yuyu2172 yuyu2172 force-pushed the eval-semantic-segmentation-change branch from 4bfbcdd to c4ec9ec Compare June 2, 2017 07:33
Copy link
Member

@Hakuyume Hakuyume left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@Hakuyume Hakuyume merged commit 7990fc2 into chainer:master Jun 2, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants