Repository: OpenNMT/OpenNMT-py

Issue:
Ensemble decoding is broken
@flauted 
Ensemble decoding is not tested I think and it is broken on master.
onmt/decoders/ensemble.py", line 133, in load_test_model
    if field is not None and 'vocab' in field.__dict__:
AttributeError: 'list' object has no attribute '__dict__'

To replicate, just run the translate command with the same model twice in argument -model x x

Thanks.


Discussion:

Resolving patch:
diff --git a/onmt/decoders/ensemble.py b/onmt/decoders/ensemble.py
--- a/onmt/decoders/ensemble.py
+++ b/onmt/decoders/ensemble.py
@@ -58,7 +58,8 @@ def forward(self, tgt, memory_bank, memory_lengths=None, step=None):
         # of the input.
         dec_outs, attns = zip(*[
             model_decoder(
-                tgt, memory_bank[i], memory_lengths, step=step)
+                tgt, memory_bank[i],
+                memory_lengths=memory_lengths, step=step)
             for i, model_decoder in enumerate(self.model_decoders)])
         mean_attns = self.combine_attns(attns)
         return EnsembleDecoderOutput(dec_outs), mean_attns
@@ -130,9 +131,25 @@ def load_test_model(opt, dummy_opt):
             shared_fields = fields
         else:
             for key, field in fields.items():
-                if field is not None and 'vocab' in field.__dict__:
-                    assert field.vocab.stoi == shared_fields[key].vocab.stoi, \
-                        'Ensemble models must use the same preprocessed data'
+                assert len(field) == 1
+                n, f = field[0]
+                try:
+                    f_iter = iter(f)
+                except TypeError:
+                    f_iter = [(n, f)]
+                for sn, sf in f_iter:
+                    if sf is not None and 'vocab' in sf.__dict__:
+                        sh_field = shared_fields[key]
+                        assert len(sh_field) == 1
+                        sh_n, sh_f = sh_field[0]
+                        try:
+                            sh_f_iter = iter(sh_f)
+                        except TypeError:
+                            sh_f_iter = [(sh_n, sh_f)]
+                        sh_f_dict = dict(sh_f_iter)
+                        assert sf.vocab.stoi == sh_f_dict[sn].vocab.stoi, \
+                            "Ensemble models must use the same " \
+                            "preprocessed data"
         models.append(model)
         if shared_model_opt is None:
             shared_model_opt = model_opt


Test patch:
diff --git a/onmt/tests/pull_request_chk.sh b/onmt/tests/pull_request_chk.sh
--- a/onmt/tests/pull_request_chk.sh
+++ b/onmt/tests/pull_request_chk.sh
@@ -149,6 +149,13 @@ ${PYTHON} translate.py -model ${TEST_DIR}/test_model.pt -src /tmp/src-test.txt -
 [ "$?" -eq 0 ] || error_exit
 echo "Succeeded" | tee -a ${LOG_FILE}
 
+echo -n "  [+] Testing NMT ensemble translation..."
+head ${DATA_DIR}/src-test.txt > /tmp/src-test.txt
+${PYTHON} translate.py -model ${TEST_DIR}/test_model.pt ${TEST_DIR}/test_model.pt \
+            -src /tmp/src-test.txt -verbose >> ${LOG_FILE} 2>&1
+[ "$?" -eq 0 ] || error_exit
+echo "Succeeded" | tee -a ${LOG_FILE}
+
 echo -n "  [+] Testing img2text translation..."
 head /tmp/im2text/src-val.txt > /tmp/im2text/src-val-head.txt
 head /tmp/im2text/tgt-val.txt > /tmp/im2text/tgt-val-head.txt