-
Notifications
You must be signed in to change notification settings - Fork 302
Change eval_semantic_segmentation #217
Change eval_semantic_segmentation #217
Conversation
I think the return values of eval_* should be reconsidered. There are three types of return values
In my opinion, returning a tuple of (metric, intermediate1, ..., intermedite n) is good. |
I will fix the interface of this function after its design is agreed upon. |
I think there are two groups of metrics/intermediate values. |
d07751c
to
ec2ac61
Compare
Updated interface. |
gt_labels = iter(gt_labels) | ||
|
||
confusion = np.zeros((n_class, n_class), dtype=np.int64) | ||
while True: |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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)`. |
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
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`. |
There was a problem hiding this comment.
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}}` |
There was a problem hiding this comment.
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}
.
examples/segnet/train.py
Outdated
'main/loss', 'main/mean_iou', 'main/mean_accuracy', | ||
'validation/main/loss', | ||
'validation/main/mean_iou', 'validation/main/mean_accuracy']), | ||
'main/loss']), |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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.
5cf0add
to
a390dfc
Compare
a390dfc
to
babf7c9
Compare
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)`. |
There was a problem hiding this comment.
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)
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
9f45e1c
to
41198b3
Compare
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
.. autofunction:: eval_semantic_segmentation_iou | ||
|
||
calc_semantic_segmentation_confusion |
There was a problem hiding this comment.
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`. |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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)) |
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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))
.
1be7061
to
4bfbcdd
Compare
4bfbcdd
to
c4ec9ec
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
No description provided.