Repository: pytorch/vision

Issue:
`DataLoader` doesn't respond to `set_default_tensor_type`
If you have a question or would like help and support, please ask at our
[forums](https://discuss.pytorch.org/).

If you are submitting a feature request, please preface the title with [feature request].
If you are submitting a bug report, please fill in the following details.

## Issue description

If I set default tensor to double, `DataLoader` still yields float tensors.

## Code example

```python
import torch
import torch as th
import torch.utils.data as tdata
from torch import nn
from torchvision import datasets, transforms

# you can comment out any one of the following two lines and the result will still be the same
th.set_default_dtype(torch.float64)
th.set_default_tensor_type(torch.DoubleTensor)

train_data = datasets.CIFAR10('../data', train=True, download=True, transform=transforms.ToTensor())
train_loader = tdata.DataLoader(train_data, batch_size=1000, shuffle=True)

next(iter(train_loader))[0].dtype
```
output
```
torch.float32
```
## System Info
Please copy and paste the output from our
[environment collection script](https://raw.githubusercontent.com/pytorch/pytorch/master/torch/utils/collect_env.py)
(or fill out the checklist below manually).

You can get the script and run it with:
```
wget https://raw.githubusercontent.com/pytorch/pytorch/master/torch/utils/collect_env.py
# For security purposes, please check the contents of collect_env.py before running it.
python collect_env.py
```
PyTorch version: 0.4.1
Is debug build: No
CUDA used to build PyTorch: 9.0.176

OS: Ubuntu 16.04.4 LTS
GCC version: (Ubuntu 5.4.0-6ubuntu1~16.04.10) 5.4.0 20160609
CMake version: version 3.5.1

Python version: 2.7
Is CUDA available: Yes
CUDA runtime version: Could not collect
GPU models and configuration: GPU 0: Tesla P100-PCIE-16GB
Nvidia driver version: 390.12
cuDNN version: Probably one of the following:
/usr/lib/x86_64-linux-gnu/libcudnn.so.7.1.2

Versions of relevant libraries:
[pip] numpy (1.14.3)
[pip] numpydoc (0.8.0)
[pip] torch (0.4.1)
[pip] torchvision (0.2.1)
[conda] pytorch                   0.4.1           py27_cuda9.0.176_cudnn7.1.2_1    pytorch
[conda] torchvision               0.2.1                    py27_1    pytorch


cc @fmassa @vfdev-5 @SsnL @VitalyFedyunin @ejguan


Discussion:
I don't think this is an issue. datasets.CIFAR10 loads up the data into a numpy array (https://github.com/pytorch/vision/blob/master/torchvision/datasets/cifar.py#L95). The default collate functionality for collating numpy arrays is simply to use torch.from_numpy() which preserves type (as it should).
```

if elem_type.__name__ == 'ndarray':
            # array of string classes and object
            if re.search('[SaUO]', elem.dtype.str) is not None:
                raise TypeError(error_msg.format(elem.dtype))

            return torch.stack([torch.from_numpy(b) for b in batch], 0)
```


Don't know if this issue still exists. 
Can confirm the inconsistent behavior, but the problem comes from `torchvision.transform.ToTensor()`
https://github.com/pytorch/vision/blob/af97ec2f4c9daac091b9a87355c4f22d37488004/torchvision/transforms/functional.py#L133-L140
```py
import numpy as np
import torch
from PIL import Image
from torchvision import transforms


np_arr = np.random.randint(0, 255, (32,32,3), dtype=np.uint8)
img = Image.fromarray(np_arr)
trans = transforms.ToTensor()
res = trans(img)
print(res.dtype) # torch.float32
```
cc: @fmassa 

Resolving patch:
diff --git a/torchvision/transforms/functional.py b/torchvision/transforms/functional.py
--- a/torchvision/transforms/functional.py
+++ b/torchvision/transforms/functional.py
@@ -104,6 +104,8 @@ def to_tensor(pic):
     if _is_numpy(pic) and not _is_numpy_image(pic):
         raise ValueError('pic should be 2/3 dimensional. Got {} dimensions.'.format(pic.ndim))
 
+    default_float_dtype = torch.get_default_dtype()
+
     if isinstance(pic, np.ndarray):
         # handle numpy array
         if pic.ndim == 2:
@@ -112,12 +114,12 @@ def to_tensor(pic):
         img = torch.from_numpy(pic.transpose((2, 0, 1))).contiguous()
         # backward compatibility
         if isinstance(img, torch.ByteTensor):
-            return img.float().div(255)
+            return img.to(dtype=default_float_dtype).div(255)
         else:
             return img
 
     if accimage is not None and isinstance(pic, accimage.Image):
-        nppic = np.zeros([pic.channels, pic.height, pic.width], dtype=np.float32)
+        nppic = np.zeros([pic.channels, pic.height, pic.width], dtype=default_float_dtype)
         pic.copyto(nppic)
         return torch.from_numpy(nppic)
 
@@ -137,7 +139,7 @@ def to_tensor(pic):
     # put it from HWC to CHW format
     img = img.permute((2, 0, 1)).contiguous()
     if isinstance(img, torch.ByteTensor):
-        return img.float().div(255)
+        return img.to(dtype=default_float_dtype).div(255)
     else:
         return img
 


Test patch:
diff --git a/test/test_transforms.py b/test/test_transforms.py
--- a/test/test_transforms.py
+++ b/test/test_transforms.py
@@ -620,6 +620,20 @@ def test_to_tensor(self):
         output = trans(img)
         self.assertTrue(np.allclose(input_data.numpy(), output.numpy()))
 
+    def test_to_tensor_with_other_default_dtypes(self):
+        current_def_dtype = torch.get_default_dtype()
+
+        t = transforms.ToTensor()
+        np_arr = np.random.randint(0, 255, (32, 32, 3), dtype=np.uint8)
+        img = Image.fromarray(np_arr)
+
+        for dtype in [torch.float16, torch.float, torch.double]:
+            torch.set_default_dtype(dtype)
+            res = t(img)
+            self.assertTrue(res.dtype == dtype, msg=f"{res.dtype} vs {dtype}")
+
+        torch.set_default_dtype(current_def_dtype)
+
     def test_max_value(self):
         for dtype in int_dtypes():
             self.assertEqual(F_t._max_value(dtype), torch.iinfo(dtype).max)