Repository: OpenMined/PySyft

Issue:
Part 6 and Part 11 Tutorial - List index out of range
**Describe the bug**
Part 11 Tutorial breaks when running cell n. 5
See also related issue #2243 
**Edit** Error for torchvision >0.2.2

**To Reproduce**
Steps to reproduce the behavior:
1. Launch the Jupyter Notebook containing Part 11 - Secure Deep Learning tutorial
2. Run all cells up to the following one:

```
test_loader = torch.utils.data.DataLoader(
    datasets.MNIST('../data', train=False,
                   transform=transforms.Compose([
                       transforms.ToTensor(),
                       transforms.Normalize((0.1307,), (0.3081,))
                   ])),
    batch_size=args.test_batch_size, shuffle=True)

private_test_loader = []
for data, target in test_loader:
    private_test_loader.append((
        data.fix_precision().share(alice, bob, crypto_provider=crypto_provider),
        target.fix_precision().share(alice, bob, crypto_provider=crypto_provider)
    ))
```

3. Run that cell
4. See the error generated:

https://pastebin.com/cYfEMJ2H

**Expected behavior**
That the cell does indeed run
**Screenshots**
![image](https://user-images.githubusercontent.com/4907418/59180043-27aab480-8b64-11e9-957b-f0a0a79bae17.png)
![image](https://user-images.githubusercontent.com/4907418/59180067-3beeb180-8b64-11e9-83a3-bcfb50586b4c.png)


**Desktop (please complete the following information):**
Ubuntu 18.04 LTS
PySyft 0.1.17





Discussion:
Hello @DanyEle, 
you can see the discussion here:
https://openmined.slack.com/archives/C6EEFN3A8/p1559737323042400?thread_ts=1559737323.042400
relate to [issue 1893](https://github.com/OpenMined/PySyft/issues/1893) here.
 I encounter the same problem as you do :).
> Hello @DanyEle,
> you can see the discussion here:
> https://openmined.slack.com/archives/C6EEFN3A8/p1559737323042400?thread_ts=1559737323.042400
> relate to [issue 1893](https://github.com/OpenMined/PySyft/issues/1893) here.
> I encounter the same problem as you do :).

I confirm that issue also happens to me in Tutorial Part 6.
And i was wondering if i am just to dump to get everything right... got the same Problem on any Tutorial which uses the MNIST Dataset.
Hey, can you confirm you don't have a gpu or cuda?
I use Google Colab.
Indeed I experience the same on colab. I'm looking at it
> Hey, can you confirm you don't have a gpu or cuda?

I have a GPU and CUDA installed, but even when disabling CUDA, this still happens.
> Hey, can you confirm you don't have a gpu or cuda?

I do not have an external GPU.

Specs:
Memory: 15,4 GiB
Processor: Intel Core i7-7500U CPU @ 2.70GHz x 4
Graphics: Intel HD Graphics 620 (Kaby Lake GT2)
OS: Ubuntu 18.10 64 Bit

Completly fresh installation with Anaconda and pip. 


The error is related to the torchvision `0.3.0` version.
Will edit a fix for it

Resolving patch:
diff --git a/syft/frameworks/torch/hook/hook_args.py b/syft/frameworks/torch/hook/hook_args.py
--- a/syft/frameworks/torch/hook/hook_args.py
+++ b/syft/frameworks/torch/hook/hook_args.py
@@ -74,10 +74,12 @@
     "my_syft_tensor_type": lambda i, **kwargs: "my_syft_tensor_type(**kwargs).on(i, wrap=False)",
 }
 
-# methods that we really don't want to hook, for example because they have an arbitrary
-# number of tensors in args signature response
-exclude_methods = {"__getitem__", "_getitem_public", "view", "permute"}
-exclude_functions = {"torch.unbind", "unbind", "torch.stack", "stack", "torch.mean", "torch.sum"}
+# Functions that we really don't want to hook because they don't have tensors in their signature
+exclude_functions = {"as_tensor", "torch.as_tensor"}
+# Methods or functions whose signature changes a lot and that we don't want to "cache", because
+# they have an arbitrary number of tensors in args which can trigger unexpected behaviour
+ambiguous_methods = {"__getitem__", "_getitem_public", "view", "permute"}
+ambiguous_functions = {"torch.unbind", "unbind", "torch.stack", "stack", "torch.mean", "torch.sum"}
 
 
 def hook_method_args(attr, method_self, args, kwargs):
@@ -105,7 +107,7 @@ def hook_method_args(attr, method_self, args, kwargs):
     attr_id = type(method_self).__name__ + "." + attr
 
     try:
-        assert attr not in exclude_methods
+        assert attr not in ambiguous_methods
 
         # Load the utility function to transform the args
         hook_args = hook_method_args_functions[attr_id]
@@ -139,7 +141,10 @@ def hook_function_args(attr, args, kwargs, return_args_type=False):
         (- the type of the tensors in the arguments)
     """
     try:
-        assert attr not in exclude_functions
+        if attr in exclude_functions:
+            raise PureTorchTensorFoundError
+
+        assert attr not in ambiguous_functions
         # Load the utility function to transform the args
         # TODO rename registry or use another one than for methods
         hook_args = hook_method_args_functions[attr]
@@ -224,7 +229,7 @@ def hook_response(attr, response, wrap_type, wrap_args={}, new_self=None):
     attr_id = f"{attr}@{wrap_type.__name__}.{response_is_tuple}.{hash_wrap_args}"
 
     try:
-        assert attr not in exclude_functions
+        assert attr not in ambiguous_functions
 
         # Load the utility function to transform the args
         response_hook_function = hook_method_response_functions[attr_id]
@@ -636,7 +641,7 @@ def register_response(
     attr_id = "{}".format(attr)
 
     try:
-        assert attr not in exclude_functions
+        assert attr not in ambiguous_functions
 
         # Load the utility function to register the response and transform tensors with pointers
         register_response_function = register_response_functions[attr_id]


Test patch: