Ejemplo n.º 1
0
    def test_jasper_eval(self):
        with open(
                os.path.abspath(
                    os.path.join(
                        os.path.dirname(__file__),
                        "../data/quartznet_speech_recognition.yaml"))) as file:
            jasper_model_definition = self.yaml.load(file)
        dl = nemo_asr.AudioToSpeechLabelDataLayer(
            manifest_filepath=self.manifest_filepath,
            labels=self.labels,
            batch_size=2,
        )
        pre_process_params = {
            'frame_splicing': 1,
            'features': 64,
            'window_size': 0.02,
            'n_fft': 512,
            'dither': 1e-05,
            'window': 'hann',
            'sample_rate': 16000,
            'normalize': 'per_feature',
            'window_stride': 0.01,
        }
        preprocessing = nemo_asr.AudioToMelSpectrogramPreprocessor(
            **pre_process_params)
        jasper_encoder = nemo_asr.JasperEncoder(
            **jasper_model_definition['JasperEncoder'], )
        jasper_decoder = nemo_asr.JasperDecoderForClassification(
            feat_in=jasper_model_definition['JasperEncoder']['jasper'][-1]
            ['filters'],
            num_classes=len(self.labels))
        ce_loss = nemo_asr.CrossEntropyLossNM()

        # DAG
        audio_signal, a_sig_length, targets, targets_len = dl()
        processed_signal, p_length = preprocessing(input_signal=audio_signal,
                                                   length=a_sig_length)

        encoded, encoded_len = jasper_encoder(audio_signal=processed_signal,
                                              length=p_length)
        # logging.info(jasper_encoder)
        logits = jasper_decoder(encoder_output=encoded)
        loss = ce_loss(
            logits=logits,
            labels=targets,
        )

        from nemo.collections.asr.helpers import (
            process_classification_evaluation_batch,
            process_classification_evaluation_epoch,
        )

        eval_callback = nemo.core.EvaluatorCallback(
            eval_tensors=[loss, logits, targets],
            user_iter_callback=lambda x, y:
            process_classification_evaluation_batch(x, y, top_k=[1]),
            user_epochs_done_callback=process_classification_evaluation_epoch,
        )
        # Instantiate an optimizer to perform `train` action
        self.nf.eval(callbacks=[eval_callback])
Ejemplo n.º 2
0
    def test_stft_conv(self):
        with open(
                os.path.abspath(
                    os.path.join(
                        os.path.dirname(__file__),
                        "../data/quartznet_speech_recognition.yaml"))) as file:
            jasper_model_definition = self.yaml.load(file)
        dl = nemo_asr.AudioToSpeechLabelDataLayer(
            manifest_filepath=self.manifest_filepath,
            labels=self.labels,
            batch_size=2,
        )
        pre_process_params = {
            'frame_splicing': 1,
            'features': 64,
            'window_size': 0.02,
            'n_fft': 512,
            'dither': 1e-05,
            'window': 'hann',
            'sample_rate': 16000,
            'normalize': 'per_feature',
            'window_stride': 0.01,
            'stft_conv': True,
        }
        preprocessing = nemo_asr.AudioToMelSpectrogramPreprocessor(
            **pre_process_params)
        jasper_encoder = nemo_asr.JasperEncoder(
            **jasper_model_definition['JasperEncoder'], )
        jasper_decoder = nemo_asr.JasperDecoderForClassification(
            feat_in=jasper_model_definition['JasperEncoder']['jasper'][-1]
            ['filters'],
            num_classes=len(self.labels))

        ce_loss = nemo_asr.CrossEntropyLossNM()

        # DAG
        audio_signal, a_sig_length, targets, targets_len = dl()
        processed_signal, p_length = preprocessing(input_signal=audio_signal,
                                                   length=a_sig_length)

        encoded, encoded_len = jasper_encoder(audio_signal=processed_signal,
                                              length=p_length)
        # logging.info(jasper_encoder)
        logits = jasper_decoder(encoder_output=encoded)
        loss = ce_loss(logits=logits, labels=targets)

        callback = nemo.core.SimpleLossLoggerCallback(
            tensors=[loss],
            print_func=lambda x: logging.info(str(x[0].item())))
        # Instantiate an optimizer to perform `train` action
        optimizer = nemo.backends.pytorch.actions.PtActions()
        optimizer.train(
            [loss],
            callbacks=[callback],
            optimizer="sgd",
            optimization_params={
                "num_epochs": 10,
                "lr": 0.0003
            },
        )
Ejemplo n.º 3
0
    def test_quartznet_vad_training(self):
        """Integtaion test that instantiates a small QuartzNet model for vad and tests training with the
        sample vad data.
        Training is run for 3 forward and backward steps and asserts that loss after 3 steps is smaller than the loss
        at the first step.
        """
        with open(os.path.abspath(os.path.join(os.path.dirname(__file__), "../data/quartznet_vad.yaml"))) as file:
            jasper_model_definition = self.yaml.load(file)
        dl = nemo_asr.AudioToSpeechLabelDataLayer(
            # featurizer_config=self.featurizer_config,
            manifest_filepath=self.manifest_filepath,
            labels=self.labels,
            batch_size=6,
        )
        pre_process_params = pre_process_params = {
            'frame_splicing': 1,
            'features': 64,
            'window_size': 0.02,
            'n_fft': 512,
            'dither': 1e-05,
            'window': 'hann',
            'sample_rate': 16000,
            'normalize': 'per_feature',
            'window_stride': 0.01,
        }
        #         preprocessing = nemo_asr.AudioToMFCCPreprocessor(**pre_process_params)
        preprocessing = nemo_asr.AudioToMelSpectrogramPreprocessor(**pre_process_params)
        jasper_encoder = nemo_asr.JasperEncoder(**jasper_model_definition['JasperEncoder'])
        jasper_decoder = nemo_asr.JasperDecoderForClassification(
            feat_in=jasper_model_definition['JasperEncoder']['jasper'][-1]['filters'], num_classes=len(self.labels)
        )
        ce_loss = nemo_asr.CrossEntropyLossNM()

        # DAG
        audio_signal, a_sig_length, targets, targets_len = dl()
        processed_signal, p_length = preprocessing(input_signal=audio_signal, length=a_sig_length)

        encoded, encoded_len = jasper_encoder(audio_signal=processed_signal, length=p_length)
        # logging.info(jasper_encoder)
        log_probs = jasper_decoder(encoder_output=encoded)
        loss = ce_loss(logits=log_probs, labels=targets)

        loss_list = []
        callback = nemo.core.SimpleLossLoggerCallback(
            tensors=[loss], print_func=partial(self.print_and_log_loss, loss_log_list=loss_list), step_freq=1
        )

        self.nf.train(
            [loss], callbacks=[callback], optimizer="sgd", optimization_params={"max_steps": 3, "lr": 0.003},
        )
        self.nf.reset_trainer()

        # Assert that training loss went down
        assert loss_list[-1] < loss_list[0]
Ejemplo n.º 4
0
def create_all_dags(args, neural_factory):
    yaml = YAML(typ="safe")
    with open(args.model_config) as f:
        jasper_params = yaml.load(f)

    labels = jasper_params['labels']  # Vocab of tokens
    sample_rate = jasper_params['sample_rate']

    # Calculate num_workers for dataloader
    total_cpus = os.cpu_count()
    cpu_per_traindl = max(int(total_cpus / neural_factory.world_size), 1)

    # perturb_config = jasper_params.get('perturb', None)
    train_dl_params = copy.deepcopy(
        jasper_params["AudioToSpeechLabelDataLayer"])
    train_dl_params.update(
        jasper_params["AudioToSpeechLabelDataLayer"]["train"])
    del train_dl_params["train"]
    del train_dl_params["eval"]
    # del train_dl_params["normalize_transcripts"]

    # Look for augmentations
    audio_augmentor = jasper_params.get('AudioAugmentor', None)

    data_layer = nemo_asr.AudioToSpeechLabelDataLayer(
        manifest_filepath=args.train_dataset,
        labels=labels,
        sample_rate=sample_rate,
        batch_size=args.batch_size,
        num_workers=cpu_per_traindl,
        augmentor=audio_augmentor,
        **train_dl_params,
    )

    crop_pad_augmentation = nemo_asr.CropOrPadSpectrogramAugmentation(
        audio_length=128)

    N = len(data_layer)
    steps_per_epoch = math.ceil(
        N / (args.batch_size * args.iter_per_step * args.num_gpus))
    logging.info('Steps per epoch : {0}'.format(steps_per_epoch))
    logging.info('Have {0} examples to train on.'.format(N))

    data_preprocessor = nemo_asr.AudioToMFCCPreprocessor(
        sample_rate=sample_rate,
        **jasper_params["AudioToMFCCPreprocessor"],
    )

    spectr_augment_config = jasper_params.get('SpectrogramAugmentation', None)
    if spectr_augment_config:
        data_spectr_augmentation = nemo_asr.SpectrogramAugmentation(
            **spectr_augment_config)

    eval_dl_params = copy.deepcopy(
        jasper_params["AudioToSpeechLabelDataLayer"])
    eval_dl_params.update(jasper_params["AudioToSpeechLabelDataLayer"]["eval"])
    del eval_dl_params["train"]
    del eval_dl_params["eval"]
    data_layers_eval = []

    if args.eval_datasets:
        for eval_datasets in args.eval_datasets:
            data_layer_eval = nemo_asr.AudioToSpeechLabelDataLayer(
                manifest_filepath=eval_datasets,
                sample_rate=sample_rate,
                labels=labels,
                batch_size=args.eval_batch_size,
                num_workers=cpu_per_traindl,
                **eval_dl_params,
            )

            data_layers_eval.append(data_layer_eval)
    else:
        logging.warning("There were no val datasets passed")

    jasper_encoder = nemo_asr.JasperEncoder(**jasper_params["JasperEncoder"], )

    jasper_decoder = nemo_asr.JasperDecoderForClassification(
        feat_in=jasper_params["JasperEncoder"]["jasper"][-1]["filters"],
        num_classes=len(labels),
        **jasper_params['JasperDecoderForClassification'],
    )

    ce_loss = nemo_asr.CrossEntropyLossNM()

    logging.info('================================')
    logging.info(
        f"Number of parameters in encoder: {jasper_encoder.num_weights}")
    logging.info(
        f"Number of parameters in decoder: {jasper_decoder.num_weights}")
    logging.info(f"Total number of parameters in model: "
                 f"{jasper_decoder.num_weights + jasper_encoder.num_weights}")
    logging.info('================================')

    # Train DAG
    # --- Assemble Training DAG --- #
    audio_signal, audio_signal_len, commands, command_len = data_layer()

    processed_signal, processed_signal_len = data_preprocessor(
        input_signal=audio_signal, length=audio_signal_len)

    processed_signal, processed_signal_len = crop_pad_augmentation(
        input_signal=processed_signal, length=audio_signal_len)

    if spectr_augment_config:
        processed_signal = data_spectr_augmentation(
            input_spec=processed_signal)

    encoded, encoded_len = jasper_encoder(audio_signal=processed_signal,
                                          length=processed_signal_len)

    decoded = jasper_decoder(encoder_output=encoded)

    loss = ce_loss(logits=decoded, labels=commands)

    # Callbacks needed to print info to console and Tensorboard
    train_callback = nemo.core.SimpleLossLoggerCallback(
        # Notice that we pass in loss, predictions, and the labels (commands).
        # Of course we would like to see our training loss, but we need the
        # other arguments to calculate the accuracy.
        tensors=[loss, decoded, commands],
        # The print_func defines what gets printed.
        print_func=partial(monitor_classification_training_progress,
                           eval_metric=None),
        get_tb_values=lambda x: [("loss", x[0])],
        tb_writer=neural_factory.tb_writer,
    )

    chpt_callback = nemo.core.CheckpointCallback(
        folder=neural_factory.checkpoint_dir,
        load_from_folder=args.load_dir,
        step_freq=args.checkpoint_save_freq,
    )

    callbacks = [train_callback, chpt_callback]

    # assemble eval DAGs
    for i, eval_dl in enumerate(data_layers_eval):
        # --- Assemble Training DAG --- #
        test_audio_signal, test_audio_signal_len, test_commands, test_command_len = eval_dl(
        )

        test_processed_signal, test_processed_signal_len = data_preprocessor(
            input_signal=test_audio_signal, length=test_audio_signal_len)

        test_processed_signal, test_processed_signal_len = crop_pad_augmentation(
            input_signal=test_processed_signal,
            length=test_processed_signal_len)

        test_encoded, test_encoded_len = jasper_encoder(
            audio_signal=test_processed_signal,
            length=test_processed_signal_len)

        test_decoded = jasper_decoder(encoder_output=test_encoded)

        test_loss = ce_loss(logits=test_decoded, labels=test_commands)

        # create corresponding eval callback
        tagname = os.path.basename(args.eval_datasets[i]).split(".")[0]
        eval_callback = nemo.core.EvaluatorCallback(
            eval_tensors=[test_loss, test_decoded, test_commands],
            user_iter_callback=partial(process_classification_evaluation_batch,
                                       top_k=1),
            user_epochs_done_callback=partial(
                process_classification_evaluation_epoch,
                eval_metric=1,
                tag=tagname),
            eval_step=args.
            eval_freq,  # How often we evaluate the model on the test set
            tb_writer=neural_factory.tb_writer,
        )

        callbacks.append(eval_callback)
    return loss, callbacks, steps_per_epoch
Ejemplo n.º 5
0
def main(
    config_file,
    nn_encoder,
    nn_decoder,
    nn_onnx_encoder,
    nn_onnx_decoder,
    pre_v09_model=False,
    batch_size=1,
    time_steps=256,
    decoder_type='ctc',
):
    yaml = YAML(typ="safe")

    logging.info("Loading config file...")
    with open(config_file) as f:
        jasper_model_definition = yaml.load(f)

    logging.info("Determining model shape...")
    num_encoder_input_features = 64
    decoder_params = jasper_model_definition['init_params']['decoder_params']['init_params']
    num_decoder_input_features = decoder_params['feat_in']
    logging.info("  Num encoder input features: {}".format(num_encoder_input_features))
    logging.info("  Num decoder input features: {}".format(num_decoder_input_features))

    nf = nemo.core.NeuralModuleFactory(create_tb_writer=False)

    logging.info("Initializing models...")
    jasper_encoder = nemo_asr.JasperEncoder(**jasper_model_definition['init_params']['encoder_params']['init_params'])

    if decoder_type == 'ctc':
        jasper_decoder = nemo_asr.JasperDecoderForCTC(
            feat_in=num_decoder_input_features,
            num_classes=decoder_params['num_classes'],
            vocabulary=decoder_params['vocabulary'],
        )
    elif decoder_type == 'classification':
        if 'labels' in jasper_model_definition:
            num_classes = len(jasper_model_definition['labels'])
        else:
            raise ValueError("List of class labels must be defined in model config file with key 'labels'")

        jasper_decoder = nemo_asr.JasperDecoderForClassification(
            feat_in=num_decoder_input_features, num_classes=num_classes
        )
    else:
        raise ValueError("`decoder_type` must be one of ['ctc', 'classification']")

    # This is necessary if you are using checkpoints trained with NeMo
    # version before 0.9
    logging.info("Loading checkpoints...")
    if pre_v09_model:
        logging.info("  Converting pre v0.9 checkpoint...")
        ckpt = torch.load(nn_encoder)
        new_ckpt = {}
        for k, v in ckpt.items():
            new_k = k.replace('.conv.', '.mconv.')
            if len(v.shape) == 3:
                new_k = new_k.replace('.weight', '.conv.weight')
            new_ckpt[new_k] = v
        jasper_encoder.load_state_dict(new_ckpt)
    else:
        jasper_encoder.restore_from(nn_encoder)
    jasper_decoder.restore_from(nn_decoder)

    # Create export directories if they don't already exist
    base_export_dir, export_fn = os.path.split(nn_onnx_encoder)
    if base_export_dir and not os.path.exists(base_export_dir):
        os.makedirs(base_export_dir)

    base_export_dir, export_fn = os.path.split(nn_onnx_decoder)
    if base_export_dir and not os.path.exists(base_export_dir):
        os.makedirs(base_export_dir)

    logging.info("Exporting encoder...")
    nf.deployment_export(
        jasper_encoder,
        nn_onnx_encoder,
        nemo.core.neural_factory.DeploymentFormat.ONNX,
        torch.zeros(batch_size, num_encoder_input_features, time_steps, dtype=torch.float, device="cuda:0",),
    )
    del jasper_encoder
    logging.info("Exporting decoder...")
    nf.deployment_export(
        jasper_decoder,
        nn_onnx_decoder,
        nemo.core.neural_factory.DeploymentFormat.ONNX,
        (torch.zeros(batch_size, num_decoder_input_features, time_steps // 2, dtype=torch.float, device="cuda:0",)),
    )
    del jasper_decoder
    logging.info("Export completed successfully.")