From 4179b00ea2efa27388aafd77c043315e7e72e66d Mon Sep 17 00:00:00 2001 From: Toru Ogawa Date: Tue, 27 Feb 2018 11:22:45 +0900 Subject: [PATCH 01/18] add n_input option --- .../iterator/apply_prediction_to_iterator.py | 65 ++++++++++--------- 1 file changed, 35 insertions(+), 30 deletions(-) diff --git a/chainercv/utils/iterator/apply_prediction_to_iterator.py b/chainercv/utils/iterator/apply_prediction_to_iterator.py index 60a95f11a9..19088b0ecb 100644 --- a/chainercv/utils/iterator/apply_prediction_to_iterator.py +++ b/chainercv/utils/iterator/apply_prediction_to_iterator.py @@ -1,7 +1,7 @@ from chainercv.utils.iterator.unzip import unzip -def apply_prediction_to_iterator(predict, iterator, hook=None): +def apply_prediction_to_iterator(func, iterator, n_input=1, hook=None): """Apply a prediction function/method to an iterator. This function applies a prediction function/method to an iterator. @@ -89,52 +89,57 @@ def apply_prediction_to_iterator(predict, iterator, hook=None): will be empty. """ - imgs, pred_values, gt_values = unzip( - _apply(predict, iterator, hook)) + in_values, out_values, rest_values = unzip( + _apply(func, iterator, n_input, hook)) - # imgs: iter of [img] -> iter of img - imgs = _flatten(imgs) + # in_values: iter of ([in_val0], [in_val1], ...) + # -> (iter of in_val0, iter of in_val1, ...) + in_values = _flatten(in_values) - # pred_values: iter of ([pred_val0], [pred_val1], ...) - # -> (iter of pred_val0, iter of pred_val1, ...) - pred_values = tuple(map(_flatten, unzip(pred_values))) + # out_values: iter of ([out_val0], [out_val1], ...) + # -> (iter of out_val0, iter of out_val1, ...) + out_values = tuple(map(_flatten, unzip(out_values))) - # gt_values: iter of ([gt_val0], [gt_val1], ...) - # -> (iter of gt_val0, iter of gt_val1, ...) - gt_values = tuple(map(_flatten, unzip(gt_values))) + # rest_values: iter of ([rest_val0], [rest_val1], ...) + # -> (iter of rest_val0, iter of rest_val1, ...) + rest_values = tuple(map(_flatten, unzip(rest_values))) - return imgs, pred_values, gt_values + return in_values, out_values, rest_values -def _apply(predict, iterator, hook): +def _apply(func, iterator, n_input, hook): for batch in iterator: - # batch: [(img, gt_val0, gt_val1, ...)] or [img] + # batch: [(in_val0, in_val1, ... , rest_val0, rest_val1, ...)] or + # [in_val] - imgs = list() - gt_values = list() + in_values = list() + rest_values = list() for sample in batch: if isinstance(sample, tuple): - imgs.append(sample[0]) - gt_values.append(sample[1:]) + in_values.append(sample[0:n_input]) + rest_values.append(sample[n_input:]) else: - imgs.append(sample) - gt_values.append(tuple()) + in_values.append((sample,)) + rest_values.append(tuple()) - # imgs: [img] + # in_values: [(in_val0, in_val1, ...)] + # -> ([in_val0], [in_val1], ...) + in_values = tuple(list(v) for v in zip(*in_values)) - # gt_values: [(gt_val0, gt_val1, ...)] -> ([gt_val0], [gt_val1], ...) - gt_values = tuple(list(v) for v in zip(*gt_values)) + # rest_values: [(rest_val0, rest_val1, ...)] + # -> ([rest_val0], [rest_val1], ...) + rest_values = tuple(list(v) for v in zip(*rest_values)) - # pred_values: ([pred_val0], [pred_val1], ...) or [pred_val] - pred_values = predict(imgs) - if not isinstance(pred_values, tuple): - # pred_values: [pred_val] -> ([pred_val],) - pred_values = pred_values, + # out_values: ([out_val0], [out_val1], ...) or [out_val] + out_values = func(*in_values) + if not isinstance(out_values, tuple): + # pred_values: [out_val] -> ([out_val],) + out_values = out_values, if hook: - hook(imgs, pred_values, gt_values) + hook(in_values, out_values, rest_values) - yield imgs, pred_values, gt_values + yield in_values, out_values, rest_values def _flatten(iterator): From 6ebf6e6f2e8c4e2be5e4778089a8d4a66432c88b Mon Sep 17 00:00:00 2001 From: Toru Ogawa Date: Tue, 27 Feb 2018 11:24:15 +0900 Subject: [PATCH 02/18] update ProgressHook --- chainercv/utils/iterator/progress_hook.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/chainercv/utils/iterator/progress_hook.py b/chainercv/utils/iterator/progress_hook.py index f895361e20..4835752a33 100644 --- a/chainercv/utils/iterator/progress_hook.py +++ b/chainercv/utils/iterator/progress_hook.py @@ -19,16 +19,16 @@ def __init__(self, n_total=None): self.start = time.time() self.n_processed = 0 - def __call__(self, imgs, pred_values, gt_values): - self.n_processed += len(imgs) + def __call__(self, in_values, out_values, rest_values): + self.n_processed += len(in_values[0]) fps = self.n_processed / (time.time() - self.start) if self.n_total is not None: sys.stdout.write( - '\r{:d} of {:d} images, {:.2f} FPS'.format( + '\r{:d} of {:d} samples, {:.2f} samples/sec'.format( self.n_processed, self.n_total, fps)) else: sys.stdout.write( - '\r{:d} images, {:.2f} FPS'.format( + '\r{:d} samples, {:.2f} samples/sec'.format( self.n_processed, fps)) sys.stdout.flush() From 4afd154a36654e64bf1ae778c8f2889365cdda4f Mon Sep 17 00:00:00 2001 From: Toru Ogawa Date: Tue, 27 Feb 2018 12:58:52 +0900 Subject: [PATCH 03/18] update test --- .../iterator/apply_prediction_to_iterator.py | 2 +- .../test_apply_prediction_to_iterator.py | 130 +++++++++++------- .../iterator_tests/test_progress_hook.py | 20 +-- 3 files changed, 89 insertions(+), 63 deletions(-) diff --git a/chainercv/utils/iterator/apply_prediction_to_iterator.py b/chainercv/utils/iterator/apply_prediction_to_iterator.py index 19088b0ecb..666ec63f48 100644 --- a/chainercv/utils/iterator/apply_prediction_to_iterator.py +++ b/chainercv/utils/iterator/apply_prediction_to_iterator.py @@ -94,7 +94,7 @@ def apply_prediction_to_iterator(func, iterator, n_input=1, hook=None): # in_values: iter of ([in_val0], [in_val1], ...) # -> (iter of in_val0, iter of in_val1, ...) - in_values = _flatten(in_values) + in_values = tuple(map(_flatten, unzip(in_values))) # out_values: iter of ([out_val0], [out_val1], ...) # -> (iter of out_val0, iter of out_val1, ...) diff --git a/tests/utils_tests/iterator_tests/test_apply_prediction_to_iterator.py b/tests/utils_tests/iterator_tests/test_apply_prediction_to_iterator.py index 54b0006bff..18580a6894 100644 --- a/tests/utils_tests/iterator_tests/test_apply_prediction_to_iterator.py +++ b/tests/utils_tests/iterator_tests/test_apply_prediction_to_iterator.py @@ -10,83 +10,109 @@ @testing.parameterize(*testing.product({ - 'multi_pred_values': [False, True], - 'with_gt_values': [False, True], + 'multi_in_values': [False, True], + 'multi_out_values': [False, True], + 'with_rest_values': [False, True], 'with_hook': [False, True], })) class TestApplyPredictionToIterator(unittest.TestCase): def test_apply_prediction_to_iterator(self): - if self.multi_pred_values: - def predict(imgs): - n_img = len(imgs) + if self.multi_in_values: + n_input = 2 + else: + n_input = 1 + + in_values_expect = list() + for _ in range(n_input): + in_value = list() + for _ in range(5): + H, W = np.random.randint(8, 16, size=2) + in_value.append(np.random.randint(0, 256, size=(3, H, W))) + in_values_expect.append(in_value) + + if self.multi_out_values: + def func(*in_values): + n_sample = len(in_values[0]) return ( - [np.random.uniform(size=(10, 4)) for _ in range(n_img)], - [np.random.uniform(size=10) for _ in range(n_img)], - [np.random.uniform(size=10) for _ in range(n_img)]) + [np.random.uniform(size=(10, 4)) for _ in range(n_sample)], + [np.random.uniform(size=10) for _ in range(n_sample)], + [np.random.uniform(size=10) for _ in range(n_sample)]) - n_pred_values = 3 + n_output = 3 else: - def predict(imgs): - n_img = len(imgs) - return [np.random.uniform(size=(48, 64)) for _ in range(n_img)] + def func(*in_values): + n_sample = len(in_values[0]) + return [np.random.uniform(size=(48, 64)) + for _ in range(n_sample)] - n_pred_values = 1 + n_output = 1 - dataset_imgs = list() - for _ in range(5): - H, W = np.random.randint(8, 16, size=2) - dataset_imgs.append(np.random.randint(0, 256, size=(3, H, W))) - - if self.with_gt_values: + if self.with_rest_values: strs = ['a', 'bc', 'def', 'ghij', 'klmno'] nums = [0, 1, 2, 3, 4] arrays = [np.random.uniform(size=10) for _ in range(5)] + rest_values_expect = (strs, nums, arrays) + n_rest = 3 dataset = chainer.datasets.TupleDataset( - dataset_imgs, strs, nums, arrays) - dataset_gt_values = (strs, nums, arrays) + *in_values_expect, *rest_values_expect) else: - dataset = dataset_imgs - dataset_gt_values = tuple() + rest_values_expect = tuple() + n_rest = 0 + + dataset = list(zip(*in_values_expect)) + iterator = SerialIterator(dataset, 2, repeat=False, shuffle=False) if self.with_hook: - def hook(imgs, pred_values, gt_values): - self.assertEqual(len(pred_values), n_pred_values) - for pred_vals in pred_values: - self.assertEqual(len(pred_vals), len(imgs)) - - self.assertEqual(len(gt_values), len(dataset_gt_values)) - for gt_vals in gt_values: - self.assertEqual(len(gt_vals), len(imgs)) - else: - hook = None + def hook(in_values, out_values, rest_values): + n_sample = len(in_values[0]) - imgs, pred_values, gt_values = apply_prediction_to_iterator( - predict, iterator, hook=hook) + self.assertEqual(len(in_values), n_input) + for in_vals in in_values: + self.assertEqual(len(in_vals), n_sample) - for img, dataset_img in zip_longest(imgs, dataset_imgs): - np.testing.assert_equal(img, dataset_img) + self.assertEqual(len(out_values), n_output) + for out_vals in out_values: + self.assertEqual(len(out_vals), n_sample) - self.assertEqual(len(pred_values), n_pred_values) - for vals in pred_values: - self.assertEqual(len(list(vals)), len(dataset_imgs)) + self.assertEqual(len(rest_values), n_rest) + for rest_vals in rest_values: + self.assertEqual(len(rest_vals), n_sample) + else: + hook = None - for vals, dataset_vals in zip_longest(gt_values, dataset_gt_values): - for val, dataset_val in zip_longest(vals, dataset_vals): - if isinstance(dataset_val, np.ndarray): - np.testing.assert_equal(val, dataset_val) + in_values, out_values, rest_values = apply_prediction_to_iterator( + func, iterator, n_input=n_input, hook=hook) + + self.assertEqual(len(in_values), n_input) + for in_vals, in_vals_expect in \ + zip_longest(in_values, in_values_expect): + for in_val, in_val_expect in zip_longest(in_vals, in_vals_expect): + np.testing.assert_equal(in_val, in_val_expect) + + self.assertEqual(len(out_values), n_output) + for out_vals in out_values: + self.assertEqual(len(list(out_vals)), len(dataset)) + + self.assertEqual(len(rest_values), n_rest) + for rest_vals, rest_vals_expect in \ + zip_longest(rest_values, rest_values_expect): + for rest_val, rest_val_expect in \ + zip_longest(rest_vals, rest_vals_expect): + if isinstance(rest_val_expect, np.ndarray): + np.testing.assert_equal(rest_val, rest_val_expect) else: - self.assertEqual(val, dataset_val) + self.assertEqual(rest_val, rest_val_expect) class TestApplyPredictionToIteratorWithInfiniteIterator(unittest.TestCase): def test_apply_prediction_to_iterator_with_infinite_iterator(self): - def predict(imgs): - n_img = len(imgs) - return [np.random.uniform(size=(48, 64)) for _ in range(n_img)] + def func(*in_values): + n_sample = len(in_values[0]) + return [np.random.uniform(size=(48, 64)) for _ in range(n_sample)] dataset = list() for _ in range(5): @@ -95,14 +121,14 @@ def predict(imgs): iterator = SerialIterator(dataset, 2) - imgs, pred_values, gt_values = apply_prediction_to_iterator( - predict, iterator) + in_values, out_values, rest_values = apply_prediction_to_iterator( + func, iterator) for _ in range(10): - next(imgs) + next(in_values[0]) for _ in range(10): - next(pred_values[0]) + next(out_values[0]) testing.run_module(__name__, __file__) diff --git a/tests/utils_tests/iterator_tests/test_progress_hook.py b/tests/utils_tests/iterator_tests/test_progress_hook.py index c3e569f1c0..90c242e503 100644 --- a/tests/utils_tests/iterator_tests/test_progress_hook.py +++ b/tests/utils_tests/iterator_tests/test_progress_hook.py @@ -11,11 +11,11 @@ class TestProgressHook(unittest.TestCase): def setUp(self): - def predict(imgs): - n_img = len(imgs) - return [np.random.uniform() for _ in range(n_img)] + def func(*in_values): + n_sample = len(in_values[0]) + return [np.random.uniform() for _ in range(n_sample)] - self.predict = predict + self.func = func self.dataset = list() for _ in range(5): @@ -25,22 +25,22 @@ def predict(imgs): def test_progress_hook(self): iterator = SerialIterator(self.dataset, 2, repeat=False) - imgs, pred_values, gt_values = apply_prediction_to_iterator( - self.predict, iterator, + in_values, out_values, rest_values = apply_prediction_to_iterator( + self.func, iterator, hook=ProgressHook(n_total=len(self.dataset))) # consume all data - for _ in imgs: + for _ in in_values[0]: pass def test_progress_hook_with_infinite_iterator(self): iterator = SerialIterator(self.dataset, 2) - imgs, pred_values, gt_values = apply_prediction_to_iterator( - self.predict, iterator, hook=ProgressHook()) + in_values, out_values, rest_values = apply_prediction_to_iterator( + self.func, iterator, hook=ProgressHook()) for _ in range(10): - next(imgs) + next(in_values[0]) testing.run_module(__name__, __file__) From 14d0973eb96dca4cb2f15746ebbb474ee7560358 Mon Sep 17 00:00:00 2001 From: Toru Ogawa Date: Tue, 27 Feb 2018 13:31:00 +0900 Subject: [PATCH 04/18] rename and update docs --- chainercv/utils/__init__.py | 2 +- chainercv/utils/iterator/__init__.py | 2 +- ...ction_to_iterator.py => apply_to_batch.py} | 109 ++++++++++-------- docs/source/reference/utils.rst | 6 +- ..._to_iterator.py => test_apply_to_batch.py} | 11 +- .../iterator_tests/test_progress_hook.py | 6 +- 6 files changed, 71 insertions(+), 65 deletions(-) rename chainercv/utils/iterator/{apply_prediction_to_iterator.py => apply_to_batch.py} (50%) rename tests/utils_tests/iterator_tests/{test_apply_prediction_to_iterator.py => test_apply_to_batch.py} (92%) diff --git a/chainercv/utils/__init__.py b/chainercv/utils/__init__.py index 47f48e3e77..7d4c5eeea4 100644 --- a/chainercv/utils/__init__.py +++ b/chainercv/utils/__init__.py @@ -6,7 +6,7 @@ from chainercv.utils.image import read_image # NOQA from chainercv.utils.image import tile_images # NOQA from chainercv.utils.image import write_image # NOQA -from chainercv.utils.iterator import apply_prediction_to_iterator # NOQA +from chainercv.utils.iterator import apply_to_batch # NOQA from chainercv.utils.iterator import ProgressHook # NOQA from chainercv.utils.iterator import unzip # NOQA from chainercv.utils.testing import assert_is_bbox # NOQA diff --git a/chainercv/utils/iterator/__init__.py b/chainercv/utils/iterator/__init__.py index f7c736a059..3a9d3f2d7b 100644 --- a/chainercv/utils/iterator/__init__.py +++ b/chainercv/utils/iterator/__init__.py @@ -1,3 +1,3 @@ -from chainercv.utils.iterator.apply_prediction_to_iterator import apply_prediction_to_iterator # NOQA +from chainercv.utils.iterator.apply_to_batch import apply_to_batch # NOQA from chainercv.utils.iterator.progress_hook import ProgressHook # NOQA from chainercv.utils.iterator.unzip import unzip # NOQA diff --git a/chainercv/utils/iterator/apply_prediction_to_iterator.py b/chainercv/utils/iterator/apply_to_batch.py similarity index 50% rename from chainercv/utils/iterator/apply_prediction_to_iterator.py rename to chainercv/utils/iterator/apply_to_batch.py index 666ec63f48..963575ad12 100644 --- a/chainercv/utils/iterator/apply_prediction_to_iterator.py +++ b/chainercv/utils/iterator/apply_to_batch.py @@ -1,32 +1,31 @@ from chainercv.utils.iterator.unzip import unzip -def apply_prediction_to_iterator(func, iterator, n_input=1, hook=None): - """Apply a prediction function/method to an iterator. +def apply_to_batch(func, iterator, n_input=1, hook=None): + """Apply a function/method to an iterator of batches. - This function applies a prediction function/method to an iterator. - It assumes that the iterator returns a batch of images or - a batch of tuples whose first element is an image. In the case that - it returns a batch of tuples, the rests are treated as ground truth - values. + This function applies a function/method to an iterator of batches. + It assumes that the iterator returns a batch of input data or + a batch of tuples whose first elements ara input data. - >>> imgs = next(iterator) - >>> # imgs: [img] - or >>> batch = next(iterator) - >>> # batch: [(img, gt_val0, gt_val1)] + >>> # batch: [in_val] + or + >>> # batch: [(in_val0, in_val1, ...)] + or + >>> # batch: [(in_val0, in_val1, ..., rest_val0, rest_val1, ...)] - This function applys :func:`predict` to a batch of images and gets - predicted value(s). :func:`predict` should take a batch of images and - return a batch of prediction values - or a tuple of batches of prediction values. + This function applies :func:`func` to batch(es) of input data and gets + computed value(s). :func:`func` should take a batch of data and + return a batch of computed values + or a tuple of batches of computed values. - >>> pred_vals0 = predict(imgs) - >>> # pred_vals0: [pred_val0] + >>> out_vals = func(in_val0, in_val1, ...) + >>> # out_vals: [out_val] or - >>> pred_vals0, pred_vals1 = predict(imgs) - >>> # pred_vals0: [pred_val0] - >>> # pred_vals1: [pred_val1] + >>> out_vals0, out_vals1, ... = func(in_val0, in_val1) + >>> # out_vals0: [out_val0] + >>> # out_vals1: [out_val1] Here is an exmple, which applies a pretrained Faster R-CNN to PASCAL VOC dataset. @@ -35,7 +34,7 @@ def apply_prediction_to_iterator(func, iterator, n_input=1, hook=None): >>> >>> from chainercv.datasets import VOCDetectionDataset >>> from chainercv.links import FasterRCNNVGG16 - >>> from chainercv.utils import apply_prediction_to_iterator + >>> from chainercv.utils import apply_to_batch >>> >>> dataset = VOCDetectionDataset(year='2007', split='test') >>> # next(iterator) -> [(img, gt_bbox, gt_label)] @@ -45,47 +44,55 @@ def apply_prediction_to_iterator(func, iterator, n_input=1, hook=None): >>> # model.predict([img]) -> ([pred_bbox], [pred_label], [pred_score]) >>> model = FasterRCNNVGG16(pretrained_model='voc07') >>> - >>> imgs, pred_values, gt_values = apply_prediction_to_iterator( + >>> in_values, out_values, rest_values = apply_to_batch( ... model.predict, iterator) >>> - >>> # pred_values contains three iterators - >>> pred_bboxes, pred_labels, pred_scores = pred_values - >>> # gt_values contains two iterators - >>> gt_bboxes, gt_labels = gt_values + >>> # in_values contains one iterator + >>> imgs, = in_values + >>> # out_values contains three iterators + >>> pred_bboxes, pred_labels, pred_scores = out_values + >>> # rest_values contains two iterators + >>> gt_bboxes, gt_labels = rest_values Args: - predict: A callable that takes a batch of images and returns - prediction. - iterator (chainer.Iterator): An iterator. Each sample should have - an image as its first element. This image is passed to - :func:`predict` as an argument. - The rests are treated as ground truth values. + func: A callable that takes batch(es) of input data and returns + computed data. + iterator (chainer.Iterator): An iterator of batch. + The first :obj:`n_input` elements in each sample are + treated as input values. They are passed to :obj:`func`. + n_input (int): The number of input data. The default value is :obj:`1`. hook: A callable that is called after each iteration. - :obj:`imgs`, :obj:`pred_values` and :obj:`gt_values` are passed as - arguments. + :obj:`in_values`, :obj:`out_values`, and :obj:`rest_values` + are passed as arguments. Note that these values do not contain data from the previous iterations. Returns: - An iterator and two tuples of iterators: - This function returns an iterator and two tuples of iterators: - :obj:`imgs`, :obj:`pred_values` and :obj:`gt_values`. - - * :obj:`imgs`: An iterator that returns an image. - * :obj:`pred_values`: A tuple of iterators. Each iterator \ - returns a corresponding predicted value. \ - For example, if :func:`predict` returns \ - :obj:`([pred_val0], [pred_val1])`, :obj:`next(pred_values[0])` \ - and :obj:`next(pred_values[1])` will be \ - :obj:`pred_val0` and :obj:`pred_val1`. - * :obj:`gt_values`: A tuple of iterators. Each iterator \ - returns a corresponding ground truth value. \ + Three tuples of iterators: + This function returns three tuples of iterators: + :obj:`in_values`, :obj:`out_values` and :obj:`rest_values`. + + * :obj:`in_values`: A tuple of iterators. Each iterator \ + returns a corresponding input value. \ + For example, if :func:`func` takes \ + :obj:`[in_val0], [in_val1]`, :obj:`next(in_values[0])` \ + and :obj:`next(in_values[1])` will be \ + :obj:`in_val0` and :obj:`in_val1`. + * :obj:`out_values`: A tuple of iterators. Each iterator \ + returns a corresponding computed value. \ + For example, if :func:`func` returns \ + :obj:`([out_val0], [out_val1])`, :obj:`next(out_values[0])` \ + and :obj:`next(out_values[1])` will be \ + :obj:`out_val0` and :obj:`out_val1`. + * :obj:`rest_values`: A tuple of iterators. Each iterator \ + returns a corresponding rest value. \ For example, if the :obj:`iterator` returns \ - :obj:`[(img, gt_val0, gt_val1)]`, :obj:`next(gt_values[0])` \ - and :obj:`next(gt_values[1])` will be \ - :obj:`gt_val0` and :obj:`gt_val1`. \ + :obj:`[(in_val0, in_val1, rest_val0, rest_val1)]`, \ + :obj:`next(rest_values[0])` \ + and :obj:`next(rest_values[1])` will be \ + :obj:`rest_val0` and :obj:`rest_val1`. \ If the input \ - iterator does not give any ground truth values, this tuple \ + iterator does not give any rest values, this tuple \ will be empty. """ diff --git a/docs/source/reference/utils.rst b/docs/source/reference/utils.rst index 3b952002b4..4e863715b8 100644 --- a/docs/source/reference/utils.rst +++ b/docs/source/reference/utils.rst @@ -51,9 +51,9 @@ write_image Iterator Utilities ------------------ -apply_prediction_to_iterator -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.. autofunction:: apply_prediction_to_iterator +apply_to_batch +~~~~~~~~~~~~~~ +.. autofunction:: apply_to_batch ProgressHook ~~~~~~~~~~~~ diff --git a/tests/utils_tests/iterator_tests/test_apply_prediction_to_iterator.py b/tests/utils_tests/iterator_tests/test_apply_to_batch.py similarity index 92% rename from tests/utils_tests/iterator_tests/test_apply_prediction_to_iterator.py rename to tests/utils_tests/iterator_tests/test_apply_to_batch.py index 18580a6894..938e5f0555 100644 --- a/tests/utils_tests/iterator_tests/test_apply_prediction_to_iterator.py +++ b/tests/utils_tests/iterator_tests/test_apply_to_batch.py @@ -6,7 +6,7 @@ from chainer.iterators import SerialIterator from chainer import testing -from chainercv.utils import apply_prediction_to_iterator +from chainercv.utils import apply_to_batch @testing.parameterize(*testing.product({ @@ -17,7 +17,7 @@ })) class TestApplyPredictionToIterator(unittest.TestCase): - def test_apply_prediction_to_iterator(self): + def test_apply_to_batch(self): if self.multi_in_values: n_input = 2 else: @@ -83,7 +83,7 @@ def hook(in_values, out_values, rest_values): else: hook = None - in_values, out_values, rest_values = apply_prediction_to_iterator( + in_values, out_values, rest_values = apply_to_batch( func, iterator, n_input=n_input, hook=hook) self.assertEqual(len(in_values), n_input) @@ -109,7 +109,7 @@ def hook(in_values, out_values, rest_values): class TestApplyPredictionToIteratorWithInfiniteIterator(unittest.TestCase): - def test_apply_prediction_to_iterator_with_infinite_iterator(self): + def test_apply_to_batch_with_infinite_iterator(self): def func(*in_values): n_sample = len(in_values[0]) return [np.random.uniform(size=(48, 64)) for _ in range(n_sample)] @@ -121,8 +121,7 @@ def func(*in_values): iterator = SerialIterator(dataset, 2) - in_values, out_values, rest_values = apply_prediction_to_iterator( - func, iterator) + in_values, out_values, rest_values = apply_to_batch(func, iterator) for _ in range(10): next(in_values[0]) diff --git a/tests/utils_tests/iterator_tests/test_progress_hook.py b/tests/utils_tests/iterator_tests/test_progress_hook.py index 90c242e503..0d3128daa9 100644 --- a/tests/utils_tests/iterator_tests/test_progress_hook.py +++ b/tests/utils_tests/iterator_tests/test_progress_hook.py @@ -4,7 +4,7 @@ from chainer.iterators import SerialIterator from chainer import testing -from chainercv.utils import apply_prediction_to_iterator +from chainercv.utils import apply_to_batch from chainercv.utils import ProgressHook @@ -25,7 +25,7 @@ def func(*in_values): def test_progress_hook(self): iterator = SerialIterator(self.dataset, 2, repeat=False) - in_values, out_values, rest_values = apply_prediction_to_iterator( + in_values, out_values, rest_values = apply_to_batch( self.func, iterator, hook=ProgressHook(n_total=len(self.dataset))) @@ -36,7 +36,7 @@ def test_progress_hook(self): def test_progress_hook_with_infinite_iterator(self): iterator = SerialIterator(self.dataset, 2) - in_values, out_values, rest_values = apply_prediction_to_iterator( + in_values, out_values, rest_values = apply_to_batch( self.func, iterator, hook=ProgressHook()) for _ in range(10): From cdbc657cc8ac5f389a8a2a80c1cc1fe4e0a2f2c0 Mon Sep 17 00:00:00 2001 From: Toru Ogawa Date: Tue, 27 Feb 2018 13:34:19 +0900 Subject: [PATCH 05/18] update related evaluator --- .../evaluator/detection_voc_evaluator.py | 19 +++++++++---------- .../semantic_segmentation_evaluator.py | 13 ++++++------- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/chainercv/extensions/evaluator/detection_voc_evaluator.py b/chainercv/extensions/evaluator/detection_voc_evaluator.py index d7b73b1613..654c1f0721 100644 --- a/chainercv/extensions/evaluator/detection_voc_evaluator.py +++ b/chainercv/extensions/evaluator/detection_voc_evaluator.py @@ -5,7 +5,7 @@ import chainer.training.extensions from chainercv.evaluations import eval_detection_voc -from chainercv.utils import apply_prediction_to_iterator +from chainercv.utils import apply_to_batch class DetectionVOCEvaluator(chainer.training.extensions.Evaluator): @@ -72,17 +72,16 @@ def evaluate(self): else: it = copy.copy(iterator) - imgs, pred_values, gt_values = apply_prediction_to_iterator( - target.predict, it) - # delete unused iterator explicitly - del imgs + in_values, out_values, rest_values = apply_to_batch(target.predict, it) + # delete unused iterators explicitly + del in_values - pred_bboxes, pred_labels, pred_scores = pred_values + pred_bboxes, pred_labels, pred_scores = out_values - if len(gt_values) == 3: - gt_bboxes, gt_labels, gt_difficults = gt_values - elif len(gt_values) == 2: - gt_bboxes, gt_labels = gt_values + if len(rest_values) == 3: + gt_bboxes, gt_labels, gt_difficults = rest_values + elif len(rest_values) == 2: + gt_bboxes, gt_labels = rest_values gt_difficults = None result = eval_detection_voc( diff --git a/chainercv/extensions/evaluator/semantic_segmentation_evaluator.py b/chainercv/extensions/evaluator/semantic_segmentation_evaluator.py index 25872f865d..a9035c7ab9 100644 --- a/chainercv/extensions/evaluator/semantic_segmentation_evaluator.py +++ b/chainercv/extensions/evaluator/semantic_segmentation_evaluator.py @@ -5,7 +5,7 @@ import chainer.training.extensions from chainercv.evaluations import eval_semantic_segmentation -from chainercv.utils import apply_prediction_to_iterator +from chainercv.utils import apply_to_batch class SemanticSegmentationEvaluator(chainer.training.extensions.Evaluator): @@ -79,13 +79,12 @@ def evaluate(self): else: it = copy.copy(iterator) - imgs, pred_values, gt_values = apply_prediction_to_iterator( - target.predict, it) - # delete unused iterator explicitly - del imgs + in_values, out_values, rest_values = apply_to_batch(target.predict, it) + # delete unused iterators explicitly + del in_values - pred_labels, = pred_values - gt_labels, = gt_values + pred_labels, = out_values + gt_labels, = rest_values result = eval_semantic_segmentation(pred_labels, gt_labels) From 592d30a6f70e73a8cadffc3e2a251fdc0a4c30a0 Mon Sep 17 00:00:00 2001 From: Toru Ogawa Date: Tue, 27 Feb 2018 13:37:22 +0900 Subject: [PATCH 06/18] update related examples --- examples/classification/eval_imagenet.py | 10 +++++----- examples/detection/eval_voc07.py | 12 ++++++------ examples/segnet/eval_camvid.py | 10 +++++----- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/examples/classification/eval_imagenet.py b/examples/classification/eval_imagenet.py index 90215c60e3..c6bdece997 100644 --- a/examples/classification/eval_imagenet.py +++ b/examples/classification/eval_imagenet.py @@ -11,7 +11,7 @@ from chainercv.links import FeaturePredictor from chainercv.links import VGG16 -from chainercv.utils import apply_prediction_to_iterator +from chainercv.utils import apply_to_batch from chainercv.utils import ProgressHook @@ -42,12 +42,12 @@ def main(): model.to_gpu() print('Model has been prepared. Evaluation starts.') - imgs, pred_values, gt_values = apply_prediction_to_iterator( + in_values, out_values, rest_values = apply_to_batch( model.predict, iterator, hook=ProgressHook(len(dataset))) - del imgs + del in_values - pred_probs, = pred_values - gt_labels, = gt_values + pred_probs, = out_values + gt_labels, = rest_values accuracy = F.accuracy( np.array(list(pred_probs)), np.array(list(gt_labels))).data diff --git a/examples/detection/eval_voc07.py b/examples/detection/eval_voc07.py index e5d9c81452..e8fe6fef6b 100644 --- a/examples/detection/eval_voc07.py +++ b/examples/detection/eval_voc07.py @@ -9,7 +9,7 @@ from chainercv.links import FasterRCNNVGG16 from chainercv.links import SSD300 from chainercv.links import SSD512 -from chainercv.utils import apply_prediction_to_iterator +from chainercv.utils import apply_to_batch from chainercv.utils import ProgressHook @@ -56,13 +56,13 @@ def main(): iterator = iterators.SerialIterator( dataset, args.batchsize, repeat=False, shuffle=False) - imgs, pred_values, gt_values = apply_prediction_to_iterator( + in_values, out_values, rest_values = apply_to_batch( model.predict, iterator, hook=ProgressHook(len(dataset))) - # delete unused iterator explicitly - del imgs + # delete unused iterators explicitly + del in_values - pred_bboxes, pred_labels, pred_scores = pred_values - gt_bboxes, gt_labels, gt_difficults = gt_values + pred_bboxes, pred_labels, pred_scores = out_values + gt_bboxes, gt_labels, gt_difficults = rest_values result = eval_detection_voc( pred_bboxes, pred_labels, pred_scores, diff --git a/examples/segnet/eval_camvid.py b/examples/segnet/eval_camvid.py index 2e25d3c7db..7fcf91ed33 100644 --- a/examples/segnet/eval_camvid.py +++ b/examples/segnet/eval_camvid.py @@ -11,7 +11,7 @@ from chainercv.datasets import CamVidDataset from chainercv.evaluations import eval_semantic_segmentation from chainercv.links import SegNetBasic -from chainercv.utils import apply_prediction_to_iterator +from chainercv.utils import apply_to_batch from chainercv.utils import ProgressHook @@ -60,12 +60,12 @@ def main(): it = chainer.iterators.SerialIterator(test, batch_size=args.batchsize, repeat=False, shuffle=False) - imgs, pred_values, gt_values = apply_prediction_to_iterator( + in_values, out_values, rest_values = apply_to_batch( model.predict, it, hook=ProgressHook(len(test))) # Delete an iterator of images to save memory usage. - del imgs - pred_labels, = pred_values - gt_labels, = gt_values + del in_values + pred_labels, = out_values + gt_labels, = rest_values result = eval_semantic_segmentation(pred_labels, gt_labels) From 2a6a4a284ed901dfbc78609de7949e64aed6ead2 Mon Sep 17 00:00:00 2001 From: Toru Ogawa Date: Tue, 27 Feb 2018 14:32:48 +0900 Subject: [PATCH 07/18] for Python2 --- tests/utils_tests/iterator_tests/test_apply_to_batch.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/utils_tests/iterator_tests/test_apply_to_batch.py b/tests/utils_tests/iterator_tests/test_apply_to_batch.py index 57e820ec39..89bebd4169 100644 --- a/tests/utils_tests/iterator_tests/test_apply_to_batch.py +++ b/tests/utils_tests/iterator_tests/test_apply_to_batch.py @@ -56,7 +56,7 @@ def func(*in_values): n_rest = 3 dataset = chainer.datasets.TupleDataset( - *in_values_expect, *rest_values_expect) + *(in_values_expect + rest_values_expect)) else: rest_values_expect = tuple() n_rest = 0 From 7a57c6c6284cda877b8c0ce254ea209d6285f594 Mon Sep 17 00:00:00 2001 From: Toru Ogawa Date: Tue, 27 Feb 2018 15:08:24 +0900 Subject: [PATCH 08/18] fix --- tests/utils_tests/iterator_tests/test_apply_to_batch.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/utils_tests/iterator_tests/test_apply_to_batch.py b/tests/utils_tests/iterator_tests/test_apply_to_batch.py index 89bebd4169..ccde2ae094 100644 --- a/tests/utils_tests/iterator_tests/test_apply_to_batch.py +++ b/tests/utils_tests/iterator_tests/test_apply_to_batch.py @@ -30,6 +30,7 @@ def test_apply_to_batch(self): H, W = np.random.randint(8, 16, size=2) in_value.append(np.random.randint(0, 256, size=(3, H, W))) in_values_expect.append(in_value) + in_values_expect = tuple(in_values_expect) if self.multi_out_values: def func(*in_values): From 77acf2e49bb1d3af5b424c6fe981750d2c5d1ced Mon Sep 17 00:00:00 2001 From: Toru Ogawa Date: Tue, 27 Feb 2018 17:37:05 +0900 Subject: [PATCH 09/18] apply_to_batch -> apply_to_iterator --- .../evaluator/detection_voc_evaluator.py | 5 +++-- .../evaluator/semantic_segmentation_evaluator.py | 5 +++-- chainercv/utils/__init__.py | 2 +- chainercv/utils/iterator/__init__.py | 2 +- .../{apply_to_batch.py => apply_to_iterator.py} | 6 +++--- docs/source/reference/utils.rst | 6 +++--- examples/classification/eval_imagenet.py | 4 ++-- examples/detection/eval_voc07.py | 4 ++-- examples/segnet/eval_camvid.py | 4 ++-- ...apply_to_batch.py => test_apply_to_iterator.py} | 14 +++++++------- .../iterator_tests/test_progress_hook.py | 6 +++--- 11 files changed, 30 insertions(+), 28 deletions(-) rename chainercv/utils/iterator/{apply_to_batch.py => apply_to_iterator.py} (97%) rename tests/utils_tests/iterator_tests/{test_apply_to_batch.py => test_apply_to_iterator.py} (91%) diff --git a/chainercv/extensions/evaluator/detection_voc_evaluator.py b/chainercv/extensions/evaluator/detection_voc_evaluator.py index c2a34f4b82..1bd4b38df7 100644 --- a/chainercv/extensions/evaluator/detection_voc_evaluator.py +++ b/chainercv/extensions/evaluator/detection_voc_evaluator.py @@ -5,7 +5,7 @@ import chainer.training.extensions from chainercv.evaluations import eval_detection_voc -from chainercv.utils import apply_to_batch +from chainercv.utils import apply_to_iterator class DetectionVOCEvaluator(chainer.training.extensions.Evaluator): @@ -72,7 +72,8 @@ def evaluate(self): else: it = copy.copy(iterator) - in_values, out_values, rest_values = apply_to_batch(target.predict, it) + in_values, out_values, rest_values = apply_to_iterator( + target.predict, it) # delete unused iterators explicitly del in_values diff --git a/chainercv/extensions/evaluator/semantic_segmentation_evaluator.py b/chainercv/extensions/evaluator/semantic_segmentation_evaluator.py index 0472578b86..9ac53552e5 100644 --- a/chainercv/extensions/evaluator/semantic_segmentation_evaluator.py +++ b/chainercv/extensions/evaluator/semantic_segmentation_evaluator.py @@ -5,7 +5,7 @@ import chainer.training.extensions from chainercv.evaluations import eval_semantic_segmentation -from chainercv.utils import apply_to_batch +from chainercv.utils import apply_to_iterator class SemanticSegmentationEvaluator(chainer.training.extensions.Evaluator): @@ -79,7 +79,8 @@ def evaluate(self): else: it = copy.copy(iterator) - in_values, out_values, rest_values = apply_to_batch(target.predict, it) + in_values, out_values, rest_values = apply_to_iterator( + target.predict, it) # delete unused iterators explicitly del in_values diff --git a/chainercv/utils/__init__.py b/chainercv/utils/__init__.py index 7d4c5eeea4..9ee7dd02ab 100644 --- a/chainercv/utils/__init__.py +++ b/chainercv/utils/__init__.py @@ -6,7 +6,7 @@ from chainercv.utils.image import read_image # NOQA from chainercv.utils.image import tile_images # NOQA from chainercv.utils.image import write_image # NOQA -from chainercv.utils.iterator import apply_to_batch # NOQA +from chainercv.utils.iterator import apply_to_iterator # NOQA from chainercv.utils.iterator import ProgressHook # NOQA from chainercv.utils.iterator import unzip # NOQA from chainercv.utils.testing import assert_is_bbox # NOQA diff --git a/chainercv/utils/iterator/__init__.py b/chainercv/utils/iterator/__init__.py index 3a9d3f2d7b..fb657c7e86 100644 --- a/chainercv/utils/iterator/__init__.py +++ b/chainercv/utils/iterator/__init__.py @@ -1,3 +1,3 @@ -from chainercv.utils.iterator.apply_to_batch import apply_to_batch # NOQA +from chainercv.utils.iterator.apply_to_iterator import apply_to_iterator # NOQA from chainercv.utils.iterator.progress_hook import ProgressHook # NOQA from chainercv.utils.iterator.unzip import unzip # NOQA diff --git a/chainercv/utils/iterator/apply_to_batch.py b/chainercv/utils/iterator/apply_to_iterator.py similarity index 97% rename from chainercv/utils/iterator/apply_to_batch.py rename to chainercv/utils/iterator/apply_to_iterator.py index 28779a3162..67e8a35ef2 100644 --- a/chainercv/utils/iterator/apply_to_batch.py +++ b/chainercv/utils/iterator/apply_to_iterator.py @@ -1,7 +1,7 @@ from chainercv.utils.iterator.unzip import unzip -def apply_to_batch(func, iterator, n_input=1, hook=None): +def apply_to_iterator(func, iterator, n_input=1, hook=None): """Apply a function/method to an iterator of batches. This function applies a function/method to an iterator of batches. @@ -34,7 +34,7 @@ def apply_to_batch(func, iterator, n_input=1, hook=None): >>> >>> from chainercv.datasets import VOCDetectionDataset >>> from chainercv.links import FasterRCNNVGG16 - >>> from chainercv.utils import apply_to_batch + >>> from chainercv.utils import apply_to_iterator >>> >>> dataset = VOCDetectionDataset(year='2007', split='test') >>> # next(iterator) -> [(img, gt_bbox, gt_label)] @@ -44,7 +44,7 @@ def apply_to_batch(func, iterator, n_input=1, hook=None): >>> # model.predict([img]) -> ([pred_bbox], [pred_label], [pred_score]) >>> model = FasterRCNNVGG16(pretrained_model='voc07') >>> - >>> in_values, out_values, rest_values = apply_to_batch( + >>> in_values, out_values, rest_values = apply_to_iterator( ... model.predict, iterator) >>> >>> # in_values contains one iterator diff --git a/docs/source/reference/utils.rst b/docs/source/reference/utils.rst index 4e863715b8..2d6a9b83d4 100644 --- a/docs/source/reference/utils.rst +++ b/docs/source/reference/utils.rst @@ -51,9 +51,9 @@ write_image Iterator Utilities ------------------ -apply_to_batch -~~~~~~~~~~~~~~ -.. autofunction:: apply_to_batch +apply_to_iterator +~~~~~~~~~~~~~~~~~ +.. autofunction:: apply_to_iterator ProgressHook ~~~~~~~~~~~~ diff --git a/examples/classification/eval_imagenet.py b/examples/classification/eval_imagenet.py index c6bdece997..79e8ba7025 100644 --- a/examples/classification/eval_imagenet.py +++ b/examples/classification/eval_imagenet.py @@ -11,7 +11,7 @@ from chainercv.links import FeaturePredictor from chainercv.links import VGG16 -from chainercv.utils import apply_to_batch +from chainercv.utils import apply_to_iterator from chainercv.utils import ProgressHook @@ -42,7 +42,7 @@ def main(): model.to_gpu() print('Model has been prepared. Evaluation starts.') - in_values, out_values, rest_values = apply_to_batch( + in_values, out_values, rest_values = apply_to_iterator( model.predict, iterator, hook=ProgressHook(len(dataset))) del in_values diff --git a/examples/detection/eval_voc07.py b/examples/detection/eval_voc07.py index e8fe6fef6b..c6c182a03f 100644 --- a/examples/detection/eval_voc07.py +++ b/examples/detection/eval_voc07.py @@ -9,7 +9,7 @@ from chainercv.links import FasterRCNNVGG16 from chainercv.links import SSD300 from chainercv.links import SSD512 -from chainercv.utils import apply_to_batch +from chainercv.utils import apply_to_iterator from chainercv.utils import ProgressHook @@ -56,7 +56,7 @@ def main(): iterator = iterators.SerialIterator( dataset, args.batchsize, repeat=False, shuffle=False) - in_values, out_values, rest_values = apply_to_batch( + in_values, out_values, rest_values = apply_to_iterator( model.predict, iterator, hook=ProgressHook(len(dataset))) # delete unused iterators explicitly del in_values diff --git a/examples/segnet/eval_camvid.py b/examples/segnet/eval_camvid.py index 7fcf91ed33..683eb416ef 100644 --- a/examples/segnet/eval_camvid.py +++ b/examples/segnet/eval_camvid.py @@ -11,7 +11,7 @@ from chainercv.datasets import CamVidDataset from chainercv.evaluations import eval_semantic_segmentation from chainercv.links import SegNetBasic -from chainercv.utils import apply_to_batch +from chainercv.utils import apply_to_iterator from chainercv.utils import ProgressHook @@ -60,7 +60,7 @@ def main(): it = chainer.iterators.SerialIterator(test, batch_size=args.batchsize, repeat=False, shuffle=False) - in_values, out_values, rest_values = apply_to_batch( + in_values, out_values, rest_values = apply_to_iterator( model.predict, it, hook=ProgressHook(len(test))) # Delete an iterator of images to save memory usage. del in_values diff --git a/tests/utils_tests/iterator_tests/test_apply_to_batch.py b/tests/utils_tests/iterator_tests/test_apply_to_iterator.py similarity index 91% rename from tests/utils_tests/iterator_tests/test_apply_to_batch.py rename to tests/utils_tests/iterator_tests/test_apply_to_iterator.py index ccde2ae094..00ef717bf2 100644 --- a/tests/utils_tests/iterator_tests/test_apply_to_batch.py +++ b/tests/utils_tests/iterator_tests/test_apply_to_iterator.py @@ -6,7 +6,7 @@ from chainer.iterators import SerialIterator from chainer import testing -from chainercv.utils import apply_to_batch +from chainercv.utils import apply_to_iterator @testing.parameterize(*testing.product({ @@ -15,9 +15,9 @@ 'with_rest_values': [False, True], 'with_hook': [False, True], })) -class TestApplyPredictionToIterator(unittest.TestCase): +class TestApplyToIterator(unittest.TestCase): - def test_apply_to_batch(self): + def test_apply_to_iterator(self): if self.multi_in_values: n_input = 2 else: @@ -84,7 +84,7 @@ def hook(in_values, out_values, rest_values): else: hook = None - in_values, out_values, rest_values = apply_to_batch( + in_values, out_values, rest_values = apply_to_iterator( func, iterator, n_input=n_input, hook=hook) self.assertEqual(len(in_values), n_input) @@ -108,9 +108,9 @@ def hook(in_values, out_values, rest_values): self.assertEqual(rest_val, rest_val_expect) -class TestApplyPredictionToIteratorWithInfiniteIterator(unittest.TestCase): +class TestApplyToIteratorWithInfiniteIterator(unittest.TestCase): - def test_apply_to_batch_with_infinite_iterator(self): + def test_apply_to_iterator_with_infinite_iterator(self): def func(*in_values): n_sample = len(in_values[0]) return [np.random.uniform(size=(48, 64)) for _ in range(n_sample)] @@ -122,7 +122,7 @@ def func(*in_values): iterator = SerialIterator(dataset, 2) - in_values, out_values, rest_values = apply_to_batch(func, iterator) + in_values, out_values, rest_values = apply_to_iterator(func, iterator) for _ in range(10): next(in_values[0]) diff --git a/tests/utils_tests/iterator_tests/test_progress_hook.py b/tests/utils_tests/iterator_tests/test_progress_hook.py index 96fc657b0a..2ef4f43599 100644 --- a/tests/utils_tests/iterator_tests/test_progress_hook.py +++ b/tests/utils_tests/iterator_tests/test_progress_hook.py @@ -4,7 +4,7 @@ from chainer.iterators import SerialIterator from chainer import testing -from chainercv.utils import apply_to_batch +from chainercv.utils import apply_to_iterator from chainercv.utils import ProgressHook @@ -25,7 +25,7 @@ def func(*in_values): def test_progress_hook(self): iterator = SerialIterator(self.dataset, 2, repeat=False) - in_values, out_values, rest_values = apply_to_batch( + in_values, out_values, rest_values = apply_to_iterator( self.func, iterator, hook=ProgressHook(n_total=len(self.dataset))) @@ -36,7 +36,7 @@ def test_progress_hook(self): def test_progress_hook_with_infinite_iterator(self): iterator = SerialIterator(self.dataset, 2) - in_values, out_values, rest_values = apply_to_batch( + in_values, out_values, rest_values = apply_to_iterator( self.func, iterator, hook=ProgressHook()) for _ in range(10): From 2d3cb55eeb2fe6f364618bd17d43bbb06fa000e8 Mon Sep 17 00:00:00 2001 From: Toru Ogawa Date: Thu, 1 Mar 2018 12:07:11 +0900 Subject: [PATCH 10/18] update docs --- chainercv/utils/iterator/apply_to_iterator.py | 40 +++++++++++++------ 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/chainercv/utils/iterator/apply_to_iterator.py b/chainercv/utils/iterator/apply_to_iterator.py index 67e8a35ef2..11b6bdf655 100644 --- a/chainercv/utils/iterator/apply_to_iterator.py +++ b/chainercv/utils/iterator/apply_to_iterator.py @@ -2,41 +2,55 @@ def apply_to_iterator(func, iterator, n_input=1, hook=None): - """Apply a function/method to an iterator of batches. + """Apply a function/method to batches from an iterator. This function applies a function/method to an iterator of batches. - It assumes that the iterator returns a batch of input data or - a batch of tuples whose first elements ara input data. + + It assumes that the iterator iterates over a collection of tuples + that contain inputs to :func:`func`. + Additionally, the tuples may contain values that are not used by func. + For convenience, we allow the iterator to iterate over a collection of + inputs that are not tuple. + Here is an illustration of the expected behavior of the iterator. >>> batch = next(iterator) >>> # batch: [in_val] or - >>> # batch: [(in_val0, in_val1, ...)] + >>> # batch: [(in_val0, ..., in_val{n_input})] or - >>> # batch: [(in_val0, in_val1, ..., rest_val0, rest_val1, ...)] + >>> # batch: [(in_val0, ..., in_val{n_input}, rest_val0, ...)] - This function applies :func:`func` to batch(es) of input data and gets - computed value(s). :func:`func` should take a batch of data and - return a batch of computed values - or a tuple of batches of computed values. + :func:`func` should take batch(es) of data and + return batch(es) of computed values. + Here is an illustration of the expected behavior of the function. - >>> out_vals = func(in_val0, in_val1, ...) + >>> out_vals = func(in_val0, ..., in_val{n_input}) >>> # out_vals: [out_val] or - >>> out_vals0, out_vals1, ... = func(in_val0, in_val1) + >>> out_vals0, out_vals1, ... = func(in_val0, ..., in_val{n_input}) >>> # out_vals0: [out_val0] >>> # out_vals1: [out_val1] + With :func:`apply_to_iterator`, users can get iterator(s) of values + returned by :func:`func`. It also returns iterator(s) of input values and + values that are not used for computation. + + >>> in_values, out_values, rest_values = apply_to_iterator( + >>> func, iterator, n_input) + >>> # in_values: (iter of in_val0, ..., iter of in_val{n_input}) + >>> # out_values: (iter of out_val0, ...) + >>> # rest_values: (iter of rest_val0, ...) + Here is an exmple, which applies a pretrained Faster R-CNN to PASCAL VOC dataset. >>> from chainer import iterators >>> - >>> from chainercv.datasets import VOCDetectionDataset + >>> from chainercv.datasets import VOCBBoxDataset >>> from chainercv.links import FasterRCNNVGG16 >>> from chainercv.utils import apply_to_iterator >>> - >>> dataset = VOCDetectionDataset(year='2007', split='test') + >>> dataset = VOCBBoxDataset(year='2007', split='test') >>> # next(iterator) -> [(img, gt_bbox, gt_label)] >>> iterator = iterators.SerialIterator( ... dataset, 2, repeat=False, shuffle=False) From a4e7c2e8dbe4e158d7830d80a97592dbb6122c32 Mon Sep 17 00:00:00 2001 From: Toru Ogawa Date: Thu, 1 Mar 2018 12:15:24 +0900 Subject: [PATCH 11/18] fix docs --- chainercv/utils/iterator/apply_to_iterator.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/chainercv/utils/iterator/apply_to_iterator.py b/chainercv/utils/iterator/apply_to_iterator.py index 11b6bdf655..2cbc6dfbd2 100644 --- a/chainercv/utils/iterator/apply_to_iterator.py +++ b/chainercv/utils/iterator/apply_to_iterator.py @@ -24,10 +24,10 @@ def apply_to_iterator(func, iterator, n_input=1, hook=None): return batch(es) of computed values. Here is an illustration of the expected behavior of the function. - >>> out_vals = func(in_val0, ..., in_val{n_input}) + >>> out_vals = func([in_val0], ..., [in_val{n_input}]) >>> # out_vals: [out_val] or - >>> out_vals0, out_vals1, ... = func(in_val0, ..., in_val{n_input}) + >>> out_vals0, out_vals1, ... = func([in_val0], ..., [in_val{n_input}]) >>> # out_vals0: [out_val0] >>> # out_vals1: [out_val1] From 2e052a40ab46b5f09ec197686c32631cfbaa9229 Mon Sep 17 00:00:00 2001 From: Toru Ogawa Date: Thu, 1 Mar 2018 12:18:05 +0900 Subject: [PATCH 12/18] n_input - 1 --- chainercv/utils/iterator/apply_to_iterator.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/chainercv/utils/iterator/apply_to_iterator.py b/chainercv/utils/iterator/apply_to_iterator.py index 2cbc6dfbd2..68405e5981 100644 --- a/chainercv/utils/iterator/apply_to_iterator.py +++ b/chainercv/utils/iterator/apply_to_iterator.py @@ -16,18 +16,18 @@ def apply_to_iterator(func, iterator, n_input=1, hook=None): >>> batch = next(iterator) >>> # batch: [in_val] or - >>> # batch: [(in_val0, ..., in_val{n_input})] + >>> # batch: [(in_val0, ..., in_val{n_input - 1})] or - >>> # batch: [(in_val0, ..., in_val{n_input}, rest_val0, ...)] + >>> # batch: [(in_val0, ..., in_val{n_input - 1}, rest_val0, ...)] :func:`func` should take batch(es) of data and return batch(es) of computed values. Here is an illustration of the expected behavior of the function. - >>> out_vals = func([in_val0], ..., [in_val{n_input}]) + >>> out_vals = func([in_val0], ..., [in_val{n_input - 1}]) >>> # out_vals: [out_val] or - >>> out_vals0, out_vals1, ... = func([in_val0], ..., [in_val{n_input}]) + >>> out_vals0, out_vals1, ... = func([in_val0], ..., [in_val{n_input - 1}]) >>> # out_vals0: [out_val0] >>> # out_vals1: [out_val1] @@ -37,7 +37,7 @@ def apply_to_iterator(func, iterator, n_input=1, hook=None): >>> in_values, out_values, rest_values = apply_to_iterator( >>> func, iterator, n_input) - >>> # in_values: (iter of in_val0, ..., iter of in_val{n_input}) + >>> # in_values: (iter of in_val0, ..., iter of in_val{n_input - 1}) >>> # out_values: (iter of out_val0, ...) >>> # rest_values: (iter of rest_val0, ...) From f920744891c707ccace90317bcdd852a20eebfc1 Mon Sep 17 00:00:00 2001 From: Toru Ogawa Date: Thu, 1 Mar 2018 12:35:26 +0900 Subject: [PATCH 13/18] fix tuple init --- chainercv/utils/iterator/apply_to_iterator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chainercv/utils/iterator/apply_to_iterator.py b/chainercv/utils/iterator/apply_to_iterator.py index 68405e5981..71b5d06222 100644 --- a/chainercv/utils/iterator/apply_to_iterator.py +++ b/chainercv/utils/iterator/apply_to_iterator.py @@ -141,7 +141,7 @@ def _apply(func, iterator, n_input, hook): rest_values.append(sample[n_input:]) else: in_values.append((sample,)) - rest_values.append(tuple()) + rest_values.append(()) # in_values: [(in_val0, in_val1, ...)] # -> ([in_val0], [in_val1], ...) From cc911960eac169971fb68437282fb005eab4bf77 Mon Sep 17 00:00:00 2001 From: Toru Ogawa Date: Thu, 1 Mar 2018 12:42:19 +0900 Subject: [PATCH 14/18] fix tuple init --- tests/utils_tests/iterator_tests/test_apply_to_iterator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/utils_tests/iterator_tests/test_apply_to_iterator.py b/tests/utils_tests/iterator_tests/test_apply_to_iterator.py index 00ef717bf2..969d9c47f2 100644 --- a/tests/utils_tests/iterator_tests/test_apply_to_iterator.py +++ b/tests/utils_tests/iterator_tests/test_apply_to_iterator.py @@ -59,7 +59,7 @@ def func(*in_values): dataset = chainer.datasets.TupleDataset( *(in_values_expect + rest_values_expect)) else: - rest_values_expect = tuple() + rest_values_expect = () n_rest = 0 dataset = list(zip(*in_values_expect)) From 0bd2f6d970aeaca436e6858b0e53661e364c1fd6 Mon Sep 17 00:00:00 2001 From: Toru Ogawa Date: Thu, 1 Mar 2018 14:28:30 +0900 Subject: [PATCH 15/18] use :func: --- chainercv/utils/iterator/apply_to_iterator.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/chainercv/utils/iterator/apply_to_iterator.py b/chainercv/utils/iterator/apply_to_iterator.py index 71b5d06222..abf6d74dc6 100644 --- a/chainercv/utils/iterator/apply_to_iterator.py +++ b/chainercv/utils/iterator/apply_to_iterator.py @@ -8,7 +8,8 @@ def apply_to_iterator(func, iterator, n_input=1, hook=None): It assumes that the iterator iterates over a collection of tuples that contain inputs to :func:`func`. - Additionally, the tuples may contain values that are not used by func. + Additionally, the tuples may contain values + that are not used by :func:`func`. For convenience, we allow the iterator to iterate over a collection of inputs that are not tuple. Here is an illustration of the expected behavior of the iterator. From 2e449a3d3fa13544de893cd6b34a346a346dba6d Mon Sep 17 00:00:00 2001 From: Toru Ogawa Date: Thu, 1 Mar 2018 14:33:46 +0900 Subject: [PATCH 16/18] do not assume chainer.Iterator --- chainercv/utils/iterator/apply_to_iterator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chainercv/utils/iterator/apply_to_iterator.py b/chainercv/utils/iterator/apply_to_iterator.py index abf6d74dc6..77f6eae9c9 100644 --- a/chainercv/utils/iterator/apply_to_iterator.py +++ b/chainercv/utils/iterator/apply_to_iterator.py @@ -72,7 +72,7 @@ def apply_to_iterator(func, iterator, n_input=1, hook=None): Args: func: A callable that takes batch(es) of input data and returns computed data. - iterator (chainer.Iterator): An iterator of batch. + iterator (iterator): An iterator of batch. The first :obj:`n_input` elements in each sample are treated as input values. They are passed to :obj:`func`. n_input (int): The number of input data. The default value is :obj:`1`. From 583ed87ebd62a6aa687556e5059f6f2500b6c097 Mon Sep 17 00:00:00 2001 From: Toru Ogawa Date: Thu, 1 Mar 2018 14:34:53 +0900 Subject: [PATCH 17/18] batch -> batches --- chainercv/utils/iterator/apply_to_iterator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chainercv/utils/iterator/apply_to_iterator.py b/chainercv/utils/iterator/apply_to_iterator.py index 77f6eae9c9..a86577cee8 100644 --- a/chainercv/utils/iterator/apply_to_iterator.py +++ b/chainercv/utils/iterator/apply_to_iterator.py @@ -72,7 +72,7 @@ def apply_to_iterator(func, iterator, n_input=1, hook=None): Args: func: A callable that takes batch(es) of input data and returns computed data. - iterator (iterator): An iterator of batch. + iterator (iterator): An iterator of batches. The first :obj:`n_input` elements in each sample are treated as input values. They are passed to :obj:`func`. n_input (int): The number of input data. The default value is :obj:`1`. From 09f7ade47f6544d43251c3d4513a2e7badcb6099 Mon Sep 17 00:00:00 2001 From: Toru Ogawa Date: Thu, 1 Mar 2018 18:13:57 +0900 Subject: [PATCH 18/18] add note --- chainercv/utils/iterator/apply_to_iterator.py | 1 + 1 file changed, 1 insertion(+) diff --git a/chainercv/utils/iterator/apply_to_iterator.py b/chainercv/utils/iterator/apply_to_iterator.py index a86577cee8..cd0073010a 100644 --- a/chainercv/utils/iterator/apply_to_iterator.py +++ b/chainercv/utils/iterator/apply_to_iterator.py @@ -13,6 +13,7 @@ def apply_to_iterator(func, iterator, n_input=1, hook=None): For convenience, we allow the iterator to iterate over a collection of inputs that are not tuple. Here is an illustration of the expected behavior of the iterator. + This behaviour is the same as :class:`chainer.Iterator`. >>> batch = next(iterator) >>> # batch: [in_val]