def create_checkpoint_decoder(args: argparse.Namespace,
                              exit_stack: ExitStack,
                              train_context: List[mx.Context]) -> Optional[checkpoint_decoder.CheckpointDecoder]:
    """
    Returns a checkpoint decoder or None.

    :param args: Arguments as returned by argparse.
    :param exit_stack: An ExitStack from contextlib.
    :param train_context: Context for training.
    :return: A CheckpointDecoder if --decode-and-evaluate != 0, else None.
    """
    sample_size = args.decode_and_evaluate
    if args.optimized_metric == C.BLEU and sample_size == 0:
        logger.info("You chose BLEU as the optimized metric, will turn on BLEU monitoring during training. "
                    "To control how many validation sentences are used for calculating bleu use "
                    "the --decode-and-evaluate argument.")
        sample_size = -1

    if sample_size == 0:
        return None

    if args.use_cpu or args.decode_and_evaluate_use_cpu:
        context = mx.cpu()
    elif args.decode_and_evaluate_device_id is not None:
        context = utils.determine_context(device_ids=args.decode_and_evaluate_device_id,
                                          use_cpu=False,
                                          disable_device_locking=args.disable_device_locking,
                                          lock_dir=args.lock_dir,
                                          exit_stack=exit_stack)[0]
    else:
        # default decode context is the last training device
        context = train_context[-1]

    return checkpoint_decoder.CheckpointDecoderImageModel(context=context,
                                                          inputs=[args.validation_source] + args.validation_source_factors,
                                                          references=args.validation_target,
                                                          model=args.output,
                                                          sample_size=sample_size,
                                                          source_image_size=args.source_image_size,
                                                          image_root=args.validation_source_root,
                                                          max_output_length=args.max_output_length,
                                                          use_feature_loader=args.image_preextracted_features)
Returns a checkpoint decoder or None.

    :param args: Arguments as returned by argparse.
    :param exit_stack: An ExitStack from contextlib.
    :param train_context: Context for training.
    :return: A CheckpointDecoder if --decode-and-evaluate != 0, else None.