Repository: espnet/espnet

Issue:
Conversion of AttributeDict with vars() returns unexpected results
I found a bug. 
In training phase, `train_args` is `argparse.Namespace`.
So `vars(train_args)` convert into dict as follows.

```python
(Pdb) train_args
Namespace(aconv_chans=10, aconv_filts=100, adim=320, aheads=4, asr_model=False, atype='location', awin=5, backend='pytorch', batch_size=30, beam_size=4, char_list=['<blank>', '<unk>', '<space>', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '<eos>'], criterion='acc', ctc_type='warpctc', ctc_weight=0.3, debugdir='exp/train_nodev_pytorch_blstmp_e4_subsample1_2_2_1_1_unit320_proj320_d1_unit300_location_aconvc10_aconvf100_mtlalpha0.5_adadelta_sampprob0.0_bs30_mli800_mlo150', debugmode=1, dict='data/lang_1char/train_nodev_units.txt', dlayers=1, dropout_rate=0.0, dropout_rate_decoder=0.0, dtype='lstm', dunits=300, early_stop_criterion='validation/main/acc', elayers=4, elayers_sd=4, epochs=20, eprojs=320, eps=1e-08, eps_decay=0.01, etype='blstmp', eunits=320, grad_clip=5, lm_weight=0.1, lsm_type='', lsm_weight=0.0, maxlen_in=800, maxlen_out=150, maxlenratio=0.0, minibatches=0, minlenratio=0.0, mt_model=False, mtlalpha=0.5, n_iter_processes=0, nbest=1, ngpu=1, num_save_attention=3, num_spkrs=1, opt='adadelta', outdir='exp/train_nodev_pytorch_blstmp_e4_subsample1_2_2_1_1_unit320_proj320_d1_unit300_location_aconvc10_aconvf100_mtlalpha0.5_adadelta_sampprob0.0_bs30_mli800_mlo150/results', patience=3, penalty=0.0, preprocess_conf=None, report_cer=False, report_wer=False, resume=None, rnnlm=None, rnnlm_conf=None, sampling_probability=0.0, seed=1, sortagrad=0, spa=False, subsample='1_2_2_1_1', sym_blank='<blank>', sym_space='<space>', tensorboard_dir='tensorboard/train_nodev_pytorch_blstmp_e4_subsample1_2_2_1_1_unit320_proj320_d1_unit300_location_aconvc10_aconvf100_mtlalpha0.5_adadelta_sampprob0.0_bs30_mli800_mlo150', threshold=0.0001, train_json='dump/train_nodev/deltafalse/data.json', valid_json='dump/train_dev/deltafalse/data.json', verbose=1, weight_decay=0.0)


(Pdb) vars(train_args)
{'aconv_chans': 10, 'aconv_filts': 100, 'adim': 320, 'aheads': 4, 'asr_model': False, 'atype': 'location', 'awin': 5, 'backend': 'pytorch', 'batch_size': 30, 'beam_size': 4, 'char_list': ['<blank>', '<unk>', '<space>', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '<eos>'], 'criterion': 'acc', 'ctc_type': 'warpctc', 'ctc_weight': 0.3, 'debugdir': 'exp/train_nodev_pytorch_blstmp_e4_subsample1_2_2_1_1_unit320_proj320_d1_unit300_location_aconvc10_aconvf100_mtlalpha0.5_adadelta_sampprob0.0_bs30_mli800_mlo150', 'debugmode': 1, 'dict': 'data/lang_1char/train_nodev_units.txt', 'dlayers': 1, 'dropout_rate': 0.0, 'dropout_rate_decoder': 0.0, 'dtype': 'lstm', 'dunits': 300, 'early_stop_criterion': 'validation/main/acc', 'elayers': 4, 'elayers_sd': 4, 'epochs': 20, 'eprojs': 320, 'eps': 1e-08, 'eps_decay': 0.01, 'etype': 'blstmp', 'eunits': 320, 'grad_clip': 5, 'lm_weight': 0.1, 'lsm_type': '', 'lsm_weight': 0.0, 'maxlen_in': 800, 'maxlen_out': 150, 'maxlenratio': 0.0, 'minibatches': 0, 'minlenratio': 0.0, 'mt_model': False, 'mtlalpha': 0.5, 'n_iter_processes': 0, 'nbest': 1, 'ngpu': 1, 'num_save_attention': 3, 'num_spkrs': 1, 'opt': 'adadelta', 'outdir': 'exp/train_nodev_pytorch_blstmp_e4_subsample1_2_2_1_1_unit320_proj320_d1_unit300_location_aconvc10_aconvf100_mtlalpha0.5_adadelta_sampprob0.0_bs30_mli800_mlo150/results', 'patience': 3, 'penalty': 0.0, 'preprocess_conf': None, 'report_cer': False, 'report_wer': False, 'resume': None, 'rnnlm': None, 'rnnlm_conf': None, 'sampling_probability': 0.0, 'seed': 1, 'sortagrad': 0, 'spa': False, 'subsample': '1_2_2_1_1', 'sym_blank': '<blank>', 'sym_space': '<space>', 'tensorboard_dir': 'tensorboard/train_nodev_pytorch_blstmp_e4_subsample1_2_2_1_1_unit320_proj320_d1_unit300_location_aconvc10_aconvf100_mtlalpha0.5_adadelta_sampprob0.0_bs30_mli800_mlo150', 'threshold': 0.0001, 'train_json': 'dump/train_nodev/deltafalse/data.json', 'valid_json': 'dump/train_dev/deltafalse/data.json', 'verbose': 1, 'weight_decay': 0.0}
```

However, in the testing phase, loaded `train_args` is `AttributeDict`.
Therefore, `vars(train_args)` return different results.
```python
(Pdb) train_args
<espnet.asr.asr_utils.AttributeDict object at 0x7f2323130a58>

(Pdb) vars(train_args)
{'obj': {'aconv_chans': 10, 'aconv_filts': 100, 'adim': 320, 'aheads': 4, 'asr_model': False, 'atype': 'location', 'awin': 5, 'backend': 'pytorch', 'batch_size': 30, 'beam_size': 4, 'char_list': ['<blank>', '<unk>', '<space>', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '<eos>'], 'criterion': 'acc', 'ctc_type': 'warpctc', 'ctc_weight': 0.3, 'debugdir': 'exp/train_nodev_pytorch_blstmp_e4_subsample1_2_2_1_1_unit320_proj320_d1_unit300_location_aconvc10_aconvf100_mtlalpha0.5_adadelta_sampprob0.0_bs30_mli800_mlo150', 'debugmode': 1, 'dict': 'data/lang_1char/train_nodev_units.txt', 'dlayers': 1, 'dropout_rate': 0.0, 'dropout_rate_decoder': 0.0, 'dtype': 'lstm', 'dunits': 300, 'early_stop_criterion': 'validation/main/acc', 'elayers': 4, 'elayers_sd': 4, 'epochs': 20, 'eprojs': 320, 'eps': 1e-08, 'eps_decay': 0.01, 'etype': 'blstmp', 'eunits': 320, 'grad_clip': 5, 'lm_weight': 0.1, 'lsm_type': '', 'lsm_weight': 0.0, 'maxlen_in': 800, 'maxlen_out': 150, 'maxlenratio': 0.0, 'minibatches': 0, 'minlenratio': 0.0, 'mt_model': False, 'mtlalpha': 0.5, 'n_iter_processes': 0, 'nbest': 1, 'ngpu': 1, 'num_save_attention': 3, 'num_spkrs': 1, 'opt': 'adadelta', 'outdir': 'exp/train_nodev_pytorch_blstmp_e4_subsample1_2_2_1_1_unit320_proj320_d1_unit300_location_aconvc10_aconvf100_mtlalpha0.5_adadelta_sampprob0.0_bs30_mli800_mlo150/results', 'patience': 3, 'penalty': 0.0, 'preprocess_conf': None, 'report_cer': False, 'report_wer': False, 'resume': None, 'rnnlm': None, 'rnnlm_conf': None, 'sampling_probability': 0.0, 'seed': 1, 'sortagrad': 0, 'spa': False, 'subsample': '1_2_2_1_1', 'sym_blank': '<blank>', 'sym_space': '<space>', 'tensorboard_dir': 'tensorboard/train_nodev_pytorch_blstmp_e4_subsample1_2_2_1_1_unit320_proj320_d1_unit300_location_aconvc10_aconvf100_mtlalpha0.5_adadelta_sampprob0.0_bs30_mli800_mlo150', 'threshold': 0.0001, 'train_json': 'dump/train_nodev/deltafalse/data.json', 'valid_json': 'dump/train_dev/deltafalse/data.json', 'verbose': 1, 'weight_decay': 0.0}}
```

This causes unexpected behavior in following line.
https://github.com/espnet/espnet/blob/fb1cbd605c5fefc6e82c829cafc01840918c90c4/espnet/nets/pytorch_backend/ctc.py#L116

`vars(train_args).get(“ctc_type”)` always return `None`, so `vars(train_args).get(“ctc_type”, “builtin”)` will always return `“builtin”`. 

@gtache Is there any reason why using `vars(train_args).get(“ctc_type”)` instead of `train_args.ctc_type`?

@sw005320 What is your intension of using `AttributeDict` in loading a config file? 


Discussion:
Well it looks like it is @simploier [code](https://github.com/espnet/espnet/commit/86cd16bd05934ee8791698906ed7a38624e486c4), so I can't really answer that. But given that we have access to `args` here `args.ctc_type` makes more sense to me yes.
Oh sorry, @gtache. 
@simpleoier Do you any idea?
My bad, it's @kamo-naoyuki [in fact](https://github.com/espnet/espnet/commit/95dec2c6d167cd289f51d054f4b610681175f3a8), @simpleoier only merged it I think
I see. It may not necessary to use `get()`, I'll fix it.

So, I found that my previous result at #553 is not correct for this bug. 
(Using warpctc at training phase,  while using pytorch.CTC at test phase.)

Resolving patch:
diff --git a/espnet/nets/pytorch_backend/ctc.py b/espnet/nets/pytorch_backend/ctc.py
--- a/espnet/nets/pytorch_backend/ctc.py
+++ b/espnet/nets/pytorch_backend/ctc.py
@@ -113,4 +113,4 @@ def ctc_for(args, odim, reduce=True):
     :return: the corresponding CTC module
     """
     return CTC(odim, args.eprojs, args.dropout_rate,
-               ctc_type=vars(args).get('ctc_type', 'builtin'), reduce=reduce)
+               ctc_type=args.ctc_type, reduce=reduce)


Test patch: