Repository: espnet/espnet

Issue:
Multi encoder integration test is dead but not reported in CI
https://travis-ci.org/espnet/espnet/jobs/620043261#L14985

I'm afraid that this line does not work well.
https://github.com/espnet/espnet/blob/2b9e8476b357eee78c0d5896833eeaeb0d1d5efe/ci/test_integration.sh#L8


Discussion:
The following shell script returns 0, so the ci never stop excluding the last block.

```bash
( set -e; return 1; ) 
( set -e; return 0; ) 
```

Is there reason you use subshell? How about simply executing these commands in the main shell?

```bash
set -e
return 1; 
return 0; 
```

Or,

```bash
set -e
( set -e; return 1; )   # Stops here because the subshell also returns 1
( set -e; return 0; ) 
```

Thanks! Just shellcheck asked me to use sub when I do cd. I will turn off
the warning here.

2019年12月14日(土) 8:26 Naoyuki Kamo <notifications@github.com>:

> The following shell script returns 0, so the ci never stop excluding the
> last block.
>
> ( set -e; return 1; )
> ( set -e; return 0; )
>
> Is there reason you use subshell? How about simply executing these
> commands in the main shell?
>
> set -ereturn 1; return 0;
>
> Or,
>
> set -e
> ( set -e; return 1; )   # Stops here because the subshell also returns 1
> ( set -e; return 0; )
>
> —
> You are receiving this because you authored the thread.
> Reply to this email directly, view it on GitHub
> <https://github.com/espnet/espnet/issues/1405?email_source=notifications&email_token=ABTOZ3R56SSXCZ2OAVWDYBLQYQRZ3A5CNFSM4JUZ2PD2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEG3ULSQ#issuecomment-565659082>,
> or unsubscribe
> <https://github.com/notifications/unsubscribe-auth/ABTOZ3WU2EJHUZQVRXDQAADQYQRZ3ANCNFSM4JUZ2PDQ>
> .
>


Resolving patch:
diff --git a/espnet/asr/pytorch_backend/asr.py b/espnet/asr/pytorch_backend/asr.py
--- a/espnet/asr/pytorch_backend/asr.py
+++ b/espnet/asr/pytorch_backend/asr.py
@@ -65,6 +65,14 @@
     from itertools import zip_longest as zip_longest
 
 
+def _recursive_to(xs, device):
+    if torch.is_tensor(xs):
+        return xs.to(device)
+    if isinstance(xs, tuple):
+        return tuple(_recursive_to(x, device) for x in xs)
+    return xs
+
+
 class CustomEvaluator(BaseEvaluator):
     """Custom Evaluator for Pytorch.
 
@@ -111,8 +119,7 @@ def evaluate(self):
         self.model.eval()
         with torch.no_grad():
             for batch in it:
-                x = tuple(arr.to(self.device) if arr is not None else None
-                          for arr in batch)
+                x = _recursive_to(batch, self.device)
                 observation = {}
                 with reporter_module.report_scope(observation):
                     # read scp files
@@ -170,8 +177,7 @@ def update_core(self):
         # Get the next batch (a list of json files)
         batch = train_iter.next()
         # self.iteration += 1 # Increase may result in early report, which is done in other place automatically.
-        x = tuple(arr.to(self.device) if arr is not None else None
-                  for arr in batch)
+        x = _recursive_to(batch, self.device)
         is_new_epoch = train_iter.epoch != epoch
         # When the last minibatch in the current epoch is given,
         # gradient accumulation is turned off in order to evaluate the model
@@ -297,7 +303,7 @@ def __init__(self, subsamping_factors=[1, 1], dtype=torch.float32):
         self.dtype = dtype
         self.num_encs = len(subsamping_factors)
 
-    def __call__(self, batch, device):
+    def __call__(self, batch, device=torch.device('cpu')):
         """Transform a batch and send it to a device.
 
         Args:


Test patch:
diff --git a/ci/test_integration.sh b/ci/test_integration.sh
--- a/ci/test_integration.sh
+++ b/ci/test_integration.sh
@@ -1,36 +1,31 @@
 #!/usr/bin/env bash
 
 # test asr recipe
-(
-    cd ./egs/mini_an4/asr1 || exit 1
-    . path.sh  # source here to avoid undefined variable errors
+cd ./egs/mini_an4/asr1 || exit 1
+. path.sh  # source here to avoid undefined variable errors
 
-    set -euo pipefail
+set -euo pipefail
+
+echo "==== ASR (backend=pytorch) ==="
+./run.sh
+echo "==== ASR (backend=pytorch, dtype=float64) ==="
+./run.sh --stage 3 --train-config "$(change_yaml.py conf/train.yaml -a train-dtype=float64)" --decode-config "$(change_yaml.py conf/decode.yaml -a api=v2 -a dtype=float64)"
+echo "==== ASR (backend=chainer) ==="
+./run.sh --stage 3 --backend chainer
+echo "==== ASR (backend=pytorch num-encs 2) ==="
+./run.sh --stage 2 --train-config ./conf/train_mulenc2.yaml --decode-config ./conf/decode_mulenc2.yaml --mulenc true
+cd -
 
-    echo "==== ASR (backend=pytorch) ==="
-    ./run.sh
-    echo "==== ASR (backend=pytorch, dtype=float64) ==="
-    ./run.sh --stage 3 --train-config "$(change_yaml.py conf/train.yaml -a train-dtype=float64)" --decode-config "$(change_yaml.py conf/decode.yaml -a api=v2 -a dtype=float64)"
-    echo "==== ASR (backend=chainer) ==="
-    ./run.sh --stage 3 --backend chainer
-    echo "==== ASR (backend=pytorch num-encs 2) ==="
-    ./run.sh --stage 2 --train-config ./conf/train_mulenc2.yaml --decode-config ./conf/decode_mulenc2.yaml --mulenc true
-)
 # test asr_mix recipe
-(
-    set -euo pipefail
+cd ./egs/mini_an4/asr_mix1 || exit 1
+echo "==== ASR Mix (backend=pytorch) ==="
+./run.sh
+cd -
 
-    cd ./egs/mini_an4/asr_mix1 || exit 1
-    echo "==== ASR Mix (backend=pytorch) ==="
-    ./run.sh
-)
 # test tts recipe
-(
-    set -euo pipefail
-
-    cd ./egs/mini_an4/tts1 || exit 1
-    echo "==== TTS (backend=pytorch) ==="
-    ./run.sh
-)
+cd ./egs/mini_an4/tts1 || exit 1
+echo "==== TTS (backend=pytorch) ==="
+./run.sh
+cd -
 
 # TODO(karita): test mt, st?