@torch.no_grad()
def main():
    parser = get_parser()
    LibriSpeechAsrDataModule.add_arguments(parser)
    args = parser.parse_args()
    args.exp_dir = Path(args.exp_dir)
    args.lang_dir = Path(args.lang_dir)
    params = get_params()
    params.update(vars(args))
    setup_logger(f'{params.exp_dir}/log-{params.method}/log-decode')
    logging.info('Decoding started')
    logging.info(params)
    lexicon = Lexicon(params.lang_dir)
    max_token_id = max(lexicon.tokens)
    num_classes = (max_token_id + 1)
    device = torch.device('cpu')
    if torch.cuda.is_available():
        device = torch.device('cuda', 0)
    logging.info(f'device: {device}')
    graph_compiler = BpeCtcTrainingGraphCompiler(params.lang_dir, device=device, sos_token='<sos/eos>', eos_token='<sos/eos>')
    sos_id = graph_compiler.sos_id
    eos_id = graph_compiler.eos_id
    if (params.method == 'ctc-decoding'):
        HLG = None
        H = k2.ctc_topo(max_token=max_token_id, modified=False, device=device)
        bpe_model = spm.SentencePieceProcessor()
        bpe_model.load(str((params.lang_dir / 'bpe.model')))
    else:
        H = None
        bpe_model = None
        HLG = k2.Fsa.from_dict(torch.load(f'{params.lang_dir}/HLG.pt', map_location='cpu'))
        HLG = HLG.to(device)
        assert (HLG.requires_grad is False)
        if (not hasattr(HLG, 'lm_scores')):
            HLG.lm_scores = HLG.scores.clone()
    if (params.method in ('nbest-rescoring', 'whole-lattice-rescoring', 'attention-decoder')):
        if (not (params.lm_dir / 'G_4_gram.pt').is_file()):
            logging.info('Loading G_4_gram.fst.txt')
            logging.warning('It may take 8 minutes.')
            with open((params.lm_dir / 'G_4_gram.fst.txt')) as f:
                first_word_disambig_id = lexicon.word_table['#0']
                G = k2.Fsa.from_openfst(f.read(), acceptor=False)
                del G.aux_labels
                G.labels[(G.labels >= first_word_disambig_id)] = 0
                G = k2.Fsa.from_fsas([G]).to(device)
                G = k2.arc_sort(G)
                torch.save(G.as_dict(), (params.lm_dir / 'G_4_gram.pt'))
        else:
            logging.info('Loading pre-compiled G_4_gram.pt')
            d = torch.load((params.lm_dir / 'G_4_gram.pt'), map_location='cpu')
            G = k2.Fsa.from_dict(d).to(device)
        if (params.method in ['whole-lattice-rescoring', 'attention-decoder']):
            G = k2.add_epsilon_self_loops(G)
            G = k2.arc_sort(G)
            G = G.to(device)
        G.lm_scores = G.scores.clone()
    else:
        G = None
    model = Conformer(num_features=params.feature_dim, nhead=params.nhead, d_model=params.attention_dim, num_classes=num_classes, subsampling_factor=params.subsampling_factor, num_decoder_layers=params.num_decoder_layers, vgg_frontend=params.vgg_frontend, use_feat_batchnorm=params.use_feat_batchnorm)
    if (params.avg == 1):
        load_checkpoint(f'{params.exp_dir}/epoch-{params.epoch}.pt', model)
    else:
        start = ((params.epoch - params.avg) + 1)
        filenames = []
        for i in range(start, (params.epoch + 1)):
            if (start >= 0):
                filenames.append(f'{params.exp_dir}/epoch-{i}.pt')
        logging.info(f'averaging {filenames}')
        model.load_state_dict(average_checkpoints(filenames))
    if params.export:
        logging.info(f'Export averaged model to {params.exp_dir}/pretrained.pt')
        torch.save({'model': model.state_dict()}, f'{params.exp_dir}/pretrained.pt')
        return
    model.to(device)
    model.eval()
    num_param = sum([p.numel() for p in model.parameters()])
    logging.info(f'Number of model parameters: {num_param}')
    librispeech = LibriSpeechAsrDataModule(args)
    test_sets = ['test-clean', 'test-other']
    for (test_set, test_dl) in zip(test_sets, librispeech.test_dataloaders()):
        results_dict = decode_dataset(dl=test_dl, params=params, model=model, HLG=HLG, H=H, bpe_model=bpe_model, word_table=lexicon.word_table, G=G, sos_id=sos_id, eos_id=eos_id)
        save_results(params=params, test_set_name=test_set, results_dict=results_dict)
    logging.info('Done!')
@torch.no_grad()
def main():
    parser = get_parser()
    LibriSpeechAsrDataModule.add_arguments(parser)
    args = parser.parse_args()
    args.exp_dir = Path(args.exp_dir)
    args.lang_dir = Path(args.lang_dir)
    params = get_params()
    params.update(vars(args))
    setup_logger(f'{params.exp_dir}/log-{params.method}/log-decode')
    logging.info('Decoding started')
    logging.info(params)
    lexicon = Lexicon(params.lang_dir)
    max_token_id = max(lexicon.tokens)
    num_classes = (max_token_id + 1)
    device = torch.device('cpu')
    if torch.cuda.is_available():
        device = torch.device('cuda', 0)
    logging.info(f'device: {device}')
    graph_compiler = BpeCtcTrainingGraphCompiler(params.lang_dir, device=device, sos_token='<sos/eos>', eos_token='<sos/eos>')
    sos_id = graph_compiler.sos_id
    eos_id = graph_compiler.eos_id
    if (params.method == 'ctc-decoding'):
        HLG = None
        H = k2.ctc_topo(max_token=max_token_id, modified=False, device=device)
        bpe_model = spm.SentencePieceProcessor()
        bpe_model.load(str((params.lang_dir / 'bpe.model')))
    else:
        H = None
        bpe_model = None
        HLG = k2.Fsa.from_dict(torch.load(f'{params.lang_dir}/HLG.pt', map_location='cpu'))
        HLG = HLG.to(device)
        assert (HLG.requires_grad is False)
        if (not hasattr(HLG, 'lm_scores')):
            HLG.lm_scores = HLG.scores.clone()
    if (params.method in ('nbest-rescoring', 'whole-lattice-rescoring', 'attention-decoder')):
        if (not (params.lm_dir / 'G_4_gram.pt').is_file()):
            logging.info('Loading G_4_gram.fst.txt')
            logging.warning('It may take 8 minutes.')
            with open((params.lm_dir / 'G_4_gram.fst.txt')) as f:
                first_word_disambig_id = lexicon.word_table['#0']
                G = k2.Fsa.from_openfst(f.read(), acceptor=False)
                del G.aux_labels
                G.labels[(G.labels >= first_word_disambig_id)] = 0
                G = k2.Fsa.from_fsas([G]).to(device)
                G = k2.arc_sort(G)
                torch.save(G.as_dict(), (params.lm_dir / 'G_4_gram.pt'))
        else:
            logging.info('Loading pre-compiled G_4_gram.pt')
            d = torch.load((params.lm_dir / 'G_4_gram.pt'), map_location='cpu')
            G = k2.Fsa.from_dict(d).to(device)
        if (params.method in ['whole-lattice-rescoring', 'attention-decoder']):
            G = k2.add_epsilon_self_loops(G)
            G = k2.arc_sort(G)
            G = G.to(device)
        G.lm_scores = G.scores.clone()
    else:
        G = None
    model = Conformer(num_features=params.feature_dim, nhead=params.nhead, d_model=params.attention_dim, num_classes=num_classes, subsampling_factor=params.subsampling_factor, num_decoder_layers=params.num_decoder_layers, vgg_frontend=params.vgg_frontend, use_feat_batchnorm=params.use_feat_batchnorm)
    if (params.avg == 1):
        load_checkpoint(f'{params.exp_dir}/epoch-{params.epoch}.pt', model)
    else:
        start = ((params.epoch - params.avg) + 1)
        filenames = []
        for i in range(start, (params.epoch + 1)):
            if (start >= 0):
                filenames.append(f'{params.exp_dir}/epoch-{i}.pt')
        logging.info(f'averaging {filenames}')
        model.load_state_dict(average_checkpoints(filenames))
    if params.export:
        logging.info(f'Export averaged model to {params.exp_dir}/pretrained.pt')
        torch.save({'model': model.state_dict()}, f'{params.exp_dir}/pretrained.pt')
        return
    model.to(device)
    model.eval()
    num_param = sum([p.numel() for p in model.parameters()])
    logging.info(f'Number of model parameters: {num_param}')
    librispeech = LibriSpeechAsrDataModule(args)
    test_sets = ['test-clean', 'test-other']
    for (test_set, test_dl) in zip(test_sets, librispeech.test_dataloaders()):
        results_dict = decode_dataset(dl=test_dl, params=params, model=model, HLG=HLG, H=H, bpe_model=bpe_model, word_table=lexicon.word_table, G=G, sos_id=sos_id, eos_id=eos_id)
        save_results(params=params, test_set_name=test_set, results_dict=results_dict)
    logging.info('Done!')