Reconnaissance vocale avec des outils d'apprentissage automatique

Dans mon travail, j'ai été confronté à la nécessité de vérifier les enregistrements d'appels pour la conformité des employés avec le script de conversation avec les clients. Habituellement, un employé est affecté à cela, qui passe beaucoup de temps à écouter les enregistrements de conversations. Nous nous sommes donné pour mission de réduire le temps consacré à la vérification à l'aide d'outils de reconnaissance automatique de la parole (ASR). Nous examinerons de plus près l'un de ces outils.





Nvidia NeMo est un  ensemble d'outils d'apprentissage automatique permettant de créer et de former des modèles alimentés par GPU.





Les modèles de NeMo utilisent une approche moderne de la reconnaissance vocale - Connectionist Time Classification (CTC).





Avant la CTC, une approche était utilisée dans laquelle le fichier audio d'entrée était divisé en segments de parole séparés et des jetons étaient prédits à partir d'eux. Ensuite, les jetons ont été combinés, les jetons répétés ont été regroupés en un seul, et le résultat a été transmis à la sortie du modèle.





Dans ce cas, la précision de la reconnaissance a souffert, car un mot avec des lettres répétées n'était pas considéré comme correctement reconnu à 100%. Par exemple, "coOperation" a été réduit à "coOperation".





Avec CTC, vous pouvez toujours prédire un jeton par segment de temps de la parole et utiliser en plus un jeton vide pour déterminer où plier les jetons en double. L'apparition d'un jeton vide permet de séparer les lettres en double qui ne doivent pas être pliées.





Pour ma tâche, j'ai pris l'un des modèles (Jasper 10 × 5) et je l'ai formé à partir de zéro. Pour la formation, un ensemble de données publiques de conversations téléphoniques a été choisi, contenant des enregistrements audio coupés et leurs transcriptions.





Pour entraîner le modèle, vous devez préparer un fichier manifeste contenant des informations sur le fichier audio et la transcription de ce fichier. Le fichier manifeste a son propre format:





{{"audio_filepath": "path/to/audio.wav", "duration": 3.45, "text": "sometext"}…{"audio_filepath": "path/to/audio.wav", "duration": 3.45, "text": "sometext"}}
      
      



Le modèle accepte uniquement les fichiers audio au format * .wav. Il est nécessaire de parcourir la liste complète des fichiers audio et d'utiliser l'utilitaire de console pour recoder les fichiers audio avec une résolution autre que celle requise:





def convertToWav(self, ext):
        if not os.path.exists(self.datadir + '/dataset'):
            tar = tarfile.open(self.an4Path);
            tar.extractall(path=self.datadir);
        sphList = glob.glob(self.datadir + '/dataset/**/*' + ext, recursive=True);
        for sph in sphList:
            wav = sph[:-4] + '.wav';
            cmd = ["sox", sph, wav];
            subprocess.run(cmd);
            print('renamed ' + ext + ' to ' + wav);
      
      



, getduration(filename=audiopath) Librosa, :





def buildManifest(self, transcript_path, manifest_path, wav_path):
        with open(transcript_paths, 'r') as fin:
            with open(manifest_path, 'w') as fout:
                for line in fin:
                    transcript = line[: line.find('(')-1].lower();
                    transcript = transcript.replace('<s>', '').replace('</s>', '');
                    transcript = transcript.strip();
                    file_id = line[line.find('(')+1 : -2];
                    audio_path = os.path.join(self.datadir, wav_paths, file_id[file_id.find('-')+1 : file_id.rfind('-')], file_id +'.wav');
                    duration = librosa.core.get_duration(filename=audio_path);
                    metadata = {
                        "audio_filepath": audio_path,
                        "duration": duration,
                        "text": transcript
                    }
                    print(metadata);
                    json.dump(metadata, fout);
                    fout.write('\n');
      
      



, :





config.yaml:
name: &name "Jasper10x5"
model:
  sample_rate: &sample_rate 16000
  labels: &labels [" ", "a", "", "", "", "", "", "", "", "", "", "", "", "",
                   "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "'"]
 preprocessor:
    _target_: nemo.collections.asr.modules.AudioToMelSpectrogramPreprocessor
    normalize: "per_feature"
    sample_rate: *sample_rate
    features: &n_mels 64
    n_fft: 512
    frame_splicing: 1
    dither: 0.00001
    stft_conv: false
      
      



. pytorch_lighting :





import nemo;
class NemoASR:
    def __init__(self, dataDir):
        self.datadir = dataDir;
        self.CONF_PATH = './config.yaml';
        yaml = YAML(typ="safe");
        with open(self.CONF_PATH) as f:
            self.CONFIG = yaml.load(f);

    def train(self, transcriptionPATH, manifestPATH, wavPATH, testTranscriptionPATH, testManifestPATH, testWavPATH):
        print("begin train");
        train_transcripts = self.datadir + transcriptionPATH;
        train_manifest = self.datadir + manifestPATH;
        if not os.path.isfile(train_manifest):
            self.buildManifest(train_transcripts, train_manifest, wavPATH);
        test_transcripts = self.datadir + testTranscriptionPATH;
        test_manifest = self.datadir + testManifestPATH;
        if not os.path.isfile(test_manifest):
            self.buildManifest(test_transcripts, test_manifest, testWavPATH);
        # params from ./config.yaml
        self.CONFIG['model']['train_ds']['manifest_filepath'] = train_manifest;
        self.CONFIG['model']['validation_ds']['manifest_filepath'] = test_manifest;
        trainer = pl.Trainer(max_epochs=500, gpus=1);
        self.model = nemo_asr.models.EncDecCTCModel(cfg=DictConfig(self.CONFIG['model']), trainer=trainer);
        trainer.fit(self.model);
        print("end train");
#-------------------------------------------------------------
nemoASR = NemoASR('.');
if (nemoASR.checkExistsDataSet()):
    print('dataset loaded');
    nemoASR.train('./dataset/etc/train.transcription',  './dataset/train_manifest.json','./dataset/wav/an4_clstk', './dataset/etc/test.transcription', './dataset/test_manifest.json', './dataset/wav/an4test_clstk');
    nemoASR.model.save_to('./model.sbc');
      
      



:





files = ['./an4/wav/an4_clstk/mgah/cen2-mgah-b.wav'];
    for fname, transcription in zip(files, nemoASR.model.transcribe(paths2audio_files=files)):
        print(f"Audio in {fname} was recognized as: {transcription}");
      
      



, .





NeMo   :





  • GPU;





  • , ;





  • .





  , , -.





ASR . .





, (TTS) (speaker recognition).








All Articles