Repository: chainer/chainer

Issue:
Need to update documentation for `Chainer.datasets.TransformDataset`
When using `Chainer.datasets.TransformDataset` with `Chainer.training.Evaluator`, if you set the trigger for the `Evaluator` to be, e.g., `(100, 'iteration')`, it will cause the performance to significantly drops (at least for the value computed by the evaluator). 

For an example code to reproduce the problem, see https://gist.github.com/jinjiren/b70ce3516d2790923f9f0ea4d9a18250
Sample results:
![image](https://user-images.githubusercontent.com/8536399/38946456-77e820ba-4374-11e8-8f56-3a67df1c3a73.png)

If you comment out the code related to `TransformDataset`, then it will behave normally:
![image](https://user-images.githubusercontent.com/8536399/38946515-a3f3919e-4374-11e8-9139-9f0f2c470904.png)

If you change the interval for the trigger of `Evaluator`, the behavior will also change:
When changed to `(1, 'epoch')` (default value), result becomes:
![image](https://user-images.githubusercontent.com/8536399/38946732-589090d4-4375-11e8-9e5d-6f9af0d90b14.png)
Seems OK but actually is worse than no `TransformDataset`.

This is a bug confused me for long. And it took me several hours to identify the problem. Currently I found that `Evaluator` with `Transform Dataset` seems to affect the performance, and the more frequently you use the `Evaluator`, the worse performance you get.  


Discussion:
In your code, `transform` function breaks the original data.
https://gist.github.com/jinjiren/b70ce3516d2790923f9f0ea4d9a18250#file-train_mnist-py-L74
```python
    def transform(in_data):
        img, label = in_data
        img -= 0.5  # original data is broken here
        return img, label
```

Replacing `img -= 0.5` with `img = img - 0.5` will be OK.

You can confirm it by the following code.

```python
import numpy as np
import chainer

x = np.arange(4).reshape(-1, 1)
print(x)  # x[0] is 0

ds = chainer.datasets.TupleDataset(x)

def transform(in_data):
    x, = in_data
    x -= 10
    return x,

transform_ds = chainer.datasets.TransformDataset(ds, transform)

transform_ds[0]

print(x)  # x[0] is -10

transform_ds[0]

print(x)  # x[0] is -20
```
@ronekko, thanks. It seems that this documentation should be updated: https://docs.chainer.org/en/stable/reference/generated/chainer.datasets.TransformDataset.html#chainer.datasets.TransformDataset
Thank you for the issue. I'll make a PR to update the documentation.

Resolving patch:
diff --git a/chainer/datasets/transform_dataset.py b/chainer/datasets/transform_dataset.py
--- a/chainer/datasets/transform_dataset.py
+++ b/chainer/datasets/transform_dataset.py
@@ -14,14 +14,19 @@ class TransformDataset(dataset_mixin.DatasetMixin):
 
     The function :obj:`transform` takes, as an argument, :obj:`in_data`, which
     is the output of the base dataset's :meth:`__getitem__`, and returns
-    the transformed arrays as output. Please see the following example.
+    the transformed arrays as output. Please see the following example. Since
+    :obj:`in_data` directly refers to the item in the dataset, take care that
+    :obj:`transform` not modify it. For example, note that the line
+    `img = img - 0.5` bellow is correct since it makes a copy of `img`.
+    However, it would be incorrect to use `img -= 0.5` since that would update
+    the contents of the item in the dataset in place, corrupting it.
 
     >>> from chainer.datasets import get_mnist
     >>> from chainer.datasets import TransformDataset
     >>> dataset, _ = get_mnist()
     >>> def transform(in_data):
     ...     img, label = in_data
-    ...     img -= 0.5  # scale to [-0.5, -0.5]
+    ...     img = img - 0.5  # scale to [-0.5, -0.5]
     ...     return img, label
     >>> dataset = TransformDataset(dataset, transform)
 


Test patch: