
Ce référentiel contient la dernière version de la boîte à outils Pytorch-Kaldi (Pytorch-Kaldi-V1.0). Pour jeter un coup d'œil dans la version précédente (Pytorch-Kaldi-v0.1), cliquez ici.
Si vous en utilisez ce code ou cette partie, veuillez citer le document suivant:
M. Ravanelli, T. Parcollet, Y. Bengio, "The Pytorch-Kaldi Recognition Toolkit", Arxiv
@inproceedings{pytorch-kaldi,
title = {The PyTorch-Kaldi Speech Recognition Toolkit},
author = {M. Ravanelli and T. Parcollet and Y. Bengio},
booktitle = {In Proc. of ICASSP},
year = {2019}
}
La boîte à outils est publiée sous une licence internationale Creative Commons Attribution 4.0 . Vous pouvez copier, distribuer, modifier le code à des fins de recherche, commerciales et non commerciales. Nous demandons uniquement à citer notre article référencé ci-dessus.
Pour améliorer la transparence et la réplicabilité des résultats de reconnaissance vocale, nous offrons aux utilisateurs la possibilité de publier leur modèle Pytorch-Kaldi dans ce référentiel. N'hésitez pas à nous contacter (ou à faire une demande de traction) pour cela. De plus, si votre article utilise Pytorch-Kaldi, il est également possible de le faire annoncer dans ce référentiel.
Voir une courte vidéo d'introduction sur la boîte à outils Pytorch-Kaldi
Nous sommes heureux d'annoncer que le projet SpeechBrain (https://speechbrain.github.io/) est maintenant public! Nous encourageons fortement les utilisateurs à migrer vers SpeechBrain. Il s'agit d'un bien meilleur projet qui soutient déjà plusieurs tâches de traitement de la parole, telles que la reconnaissance de la parole, la reconnaissance des conférenciers, le SLU, l'amélioration de la parole, la séparation de la parole, le traitement du signal multi-microphone et bien d'autres.
L'objectif est de développer une boîte à outils unique , flexible et conviviale qui peut être utilisée pour développer facilement des systèmes de parole de pointe pour la reconnaissance de la parole (à la fois de bout en bout et HMM-DNN), la reconnaissance des haut-parleurs, la séparation de la parole, le traitement du signal multi-microphone (par exemple, la formation de faisceau), l'apprentissage auto-supervisé et bien d'autres.
Le projet sera dirigé par Mila et est parrainé par Samsung, Nvidia, Dolby. SpeechBrain bénéficiera également de la collaboration et de l'expertise d'autres sociétés telles que Facebook / Pytorch, IbMresearch, Fluentai.
Nous recherchons activement des collaborateurs. N'hésitez pas à nous contacter à [email protected] si vous souhaitez collaborer.
Grâce à nos sponsors, nous sommes également en mesure d'embaucher des stagiaires travaillant chez Mila sur le projet SpeechBrain. Le candidat idéal est un doctorant avec de l'expérience sur Pytorch et les technologies de la parole (envoyez votre CV à [email protected])
Le développement de SpeechBrain nécessitera quelques mois avant d'avoir un référentiel de travail. Pendant ce temps, nous continuerons à fournir un soutien au projet Pytorch-Kaldi.
Restez à l'écoute!
Le projet Pytorch-Kaldi vise à combler l'écart entre le Kaldi et les boîtes à outils Pytorch, essayant de hériter de l'efficacité de Kaldi et de la flexibilité du pytorch. Pytorch-Kaldi n'est pas seulement une interface simple entre ces boîtes à outils, mais il intègre plusieurs fonctionnalités utiles pour développer des reconnaissances de la parole modernes. Par exemple, le code est spécifiquement conçu pour les modèles acoustiques naturellement plug-in-définis par l'utilisateur. Comme alternative, les utilisateurs peuvent exploiter plusieurs réseaux de neurones pré-implémentés qui peuvent être personnalisés à l'aide de fichiers de configuration intuitifs. Pytorch-Kaldi prend en charge plusieurs flux de fonctionnalités et d'étiquettes ainsi que des combinaisons de réseaux de neurones, permettant l'utilisation d'architectures neuronales complexes. La boîte à outils est publiée publiquement avec une documentation riche et est conçue pour fonctionner correctement localement ou sur des clusters HPC.
Quelques fonctionnalités de la nouvelle version de la boîte à outils Pytorch-Kaldi:
export KALDI_ROOT=/home/mirco/kaldi-trunk
PATH=$PATH:$KALDI_ROOT/tools/openfst
PATH=$PATH:$KALDI_ROOT/src/featbin
PATH=$PATH:$KALDI_ROOT/src/gmmbin
PATH=$PATH:$KALDI_ROOT/src/bin
PATH=$PATH:$KALDI_ROOT//src/nnetbin
export PATH
N'oubliez pas de modifier la variable Kaldi_root en utilisant votre chemin. En tant que premier test pour vérifier l'installation, ouvrez un shell bash, tapez "Copy-Feats" ou "Hmm-Info" et assurez-vous qu'aucune erreur n'apparaît.
Si ce n'est pas déjà fait, installez Pytorch (http://pytorch.org/). Nous avons testé nos codes sur Pytorch 1.0 et Pytorch 0.4. Une ancienne version de Pytorch est susceptible d'augmenter les erreurs. Pour vérifier votre installation, tapez «Python» et, une fois entré dans la console, tapez «Importer la torche» et assurez-vous qu'aucune erreur n'apparaît.
Nous vous recommandons d'exécuter le code sur une machine GPU. Assurez-vous que les bibliothèques CUDA (https://developer.nvidia.com/cuda-downloads) sont installées et fonctionnent correctement. Nous avons testé notre système sur CUDA 9.0, 9.1 et 8.0. Assurez-vous que Python est installé (le code est testé avec Python 2.7 et Python 3.7). Même s'il n'est pas obligatoire, nous suggérons d'utiliser Anaconda (https://anaconda.org/anaconda/python).
19 février 2019: Mises à jour:
batch_size_train = 128*12 | 64*10 | 32*2
La ligne ci-dessus signifie: Faites 12 époques avec 128 lots, 10 époques avec 64 lots et 2 époques avec 32 lots. Un formalisme similaire peut être utilisé pour le taux d'apprentissage et la planification de décrochage. Voir cette section pour plus d'informations.
5 février 2019: Mises à jour:
Remarques sur la version suivante: Dans la version suivante, nous prévoyons d'étendre davantage les fonctionnalités de notre boîte à outils, en prenant en charge plus de modèles et de formats de fonctionnalités. L'objectif est de rendre notre boîte à outils adaptée à d'autres tâches liées à la parole telles que la reconnaissance de la parole de bout en bout, l'identification des orateurs, les taches de mots clés, la séparation de la parole, la détection des activités de la parole, l'amélioration de la parole, etc. Si vous souhaitez proposer de nouvelles fonctionnalités, veuillez nous donner vos commentaires en remplissant cette enquête.
Pour installer Pytorch-Kaldi, effectuez les étapes suivantes:
git clone https://github.com/mravanelli/pytorch-kaldi
pip install -r requirements.txt
Dans ce qui suit, nous fournissons un court tutoriel de la boîte à outils Pytorch-Kaldi basée sur l'ensemble de données TIMIT populaire.
Assurez-vous d'avoir l'ensemble de données TIMIT. Sinon, il peut être téléchargé à partir du site Web LDC (https://catalog.ldc.upenn.edu/ldc93s1).
Assurez-vous que les installations Kaldi et Pytorch sont bien. Assurez-vous également que vos chemins Kaldi fonctionnent actuellement (vous devez ajouter les chemins Kaldi dans le .Bashrc comme indiqué dans la section "Prérequis"). Par exemple, tapez "Copy-FEATS" et "HMM-Info" et assurez-vous qu'aucune erreur n'apparaît.
Exécutez la base de référence de Kaldi S5 de Timit. Cette étape est nécessaire pour calculer les fonctionnalités et les étiquettes utilisées plus tard pour former le réseau neuronal Pytorch. Nous vous recommandons d'exécuter la recette complète de Timit S5 (y compris la formation DNN):
cd kaldi/egs/timit/s5
./run.sh
./local/nnet/run_dnn.sh
De cette façon, tous les fichiers nécessaires sont créés et l'utilisateur peut comparer directement les résultats obtenus par Kaldi avec celui réalisé avec notre boîte à outils.
steps/align_fmllr.sh --nj 4 data/dev data/lang exp/tri3 exp/tri3_ali_dev
steps/align_fmllr.sh --nj 4 data/test data/lang exp/tri3 exp/tri3_ali_test
Si vous souhaitez utiliser les alignements DNN (comme suggéré), tapez:
steps/nnet/align.sh --nj 4 data-fmllr-tri3/train data/lang exp/dnn4_pretrain-dbn_dnn exp/dnn4_pretrain-dbn_dnn_ali
steps/nnet/align.sh --nj 4 data-fmllr-tri3/dev data/lang exp/dnn4_pretrain-dbn_dnn exp/dnn4_pretrain-dbn_dnn_ali_dev
steps/nnet/align.sh --nj 4 data-fmllr-tri3/test data/lang exp/dnn4_pretrain-dbn_dnn exp/dnn4_pretrain-dbn_dnn_ali_test
Nous commençons ce tutoriel avec un réseau MLP très simple formé sur les fonctionnalités MFCC. Avant de lancer l'expérience, jetez un œil au fichier de configuration CFG / TIMIT_BASELINES / TIMIT_MLP_MFCC_BASIC.CFG . Voir la description des fichiers de configuration pour une description détaillée de tous ses champs.
Modifiez le fichier de configuration en fonction de vos chemins. En particulier:
Pour éviter les erreurs, assurez-vous que tous les chemins du fichier CFG existent. Veuillez éviter d'utiliser des chemins contenant des variables de bash car les chemins sont lus littéralement et ne sont pas automatiquement élargis (par exemple, utilisation / home / mirco / kaldi-trunk / egs / timit / s5 / exp / dnn4_pretrain-dbn_dnn_ali
python run_exp.py cfg/TIMIT_baselines/TIMIT_MLP_mfcc_basic.cfg
Ce script démarre une expérience ASR complète et effectue des étapes de formation, de validation, d'avant et de décodage. Une barre de progrès montre l'évolution de toutes les phases susmentionnées. Le script run_exp.py crée progressivement les fichiers suivants dans le répertoire de sortie:
Notez que vous pouvez arrêter l'expérience à tout moment. Si vous exécutez à nouveau le script, il commencera automatiquement à partir du dernier morceau correctement traité. La formation pourrait prendre quelques heures, selon le GPU disponible. Notez également que si vous souhaitez modifier certains paramètres du fichier de configuration (par exemple, n_chunks =, fea_lst =, batch_size_train =, ..) Vous devez spécifier un dossier de sortie différent (output_folder =).
Débogage: Si vous rencontrez des erreurs, nous vous suggérons de faire les vérifications suivantes:
Jetez un œil à la sortie standard.
Si cela n'est pas utile, jetez un œil au fichier log.log.
Jetez un œil à la fonction run_nn dans la bibliothèque Core.py. Ajoutez quelques impressions dans les différentes parties de la fonction pour isoler le problème et déterminer le problème.
À la fin de la formation, le taux d'erreur du téléphone (par%) est ajouté dans le fichier res.res. Pour voir plus de détails sur les résultats du décodage, vous pouvez entrer dans «Decoding_Test» dans le dossier de sortie et jeter un œil aux différents fichiers créés. Pour cet exemple spécifique, nous avons obtenu le fichier res.res suivant:
ep=000 tr=['TIMIT_tr'] loss=3.398 err=0.721 valid=TIMIT_dev loss=2.268 err=0.591 lr_architecture1=0.080000 time(s)=86
ep=001 tr=['TIMIT_tr'] loss=2.137 err=0.570 valid=TIMIT_dev loss=1.990 err=0.541 lr_architecture1=0.080000 time(s)=87
ep=002 tr=['TIMIT_tr'] loss=1.896 err=0.524 valid=TIMIT_dev loss=1.874 err=0.516 lr_architecture1=0.080000 time(s)=87
ep=003 tr=['TIMIT_tr'] loss=1.751 err=0.494 valid=TIMIT_dev loss=1.819 err=0.504 lr_architecture1=0.080000 time(s)=88
ep=004 tr=['TIMIT_tr'] loss=1.645 err=0.472 valid=TIMIT_dev loss=1.775 err=0.494 lr_architecture1=0.080000 time(s)=89
ep=005 tr=['TIMIT_tr'] loss=1.560 err=0.453 valid=TIMIT_dev loss=1.773 err=0.493 lr_architecture1=0.080000 time(s)=88
.........
ep=020 tr=['TIMIT_tr'] loss=0.968 err=0.304 valid=TIMIT_dev loss=1.648 err=0.446 lr_architecture1=0.002500 time(s)=89
ep=021 tr=['TIMIT_tr'] loss=0.965 err=0.304 valid=TIMIT_dev loss=1.649 err=0.446 lr_architecture1=0.002500 time(s)=90
ep=022 tr=['TIMIT_tr'] loss=0.960 err=0.302 valid=TIMIT_dev loss=1.652 err=0.447 lr_architecture1=0.001250 time(s)=88
ep=023 tr=['TIMIT_tr'] loss=0.959 err=0.301 valid=TIMIT_dev loss=1.651 err=0.446 lr_architecture1=0.000625 time(s)=88
%WER 18.1 | 192 7215 | 84.0 11.9 4.2 2.1 18.1 99.5 | -0.583 | /home/mirco/pytorch-kaldi-new/exp/TIMIT_MLP_basic5/decode_TIMIT_test_out_dnn1/score_6/ctm_39phn.filt.sys
Le perçu par (%) est de 18,1%. Notez qu'il pourrait y avoir une certaine variabilité dans les résultats, en raison de différentes initialisations sur différentes machines. Nous pensons que la moyenne des performances obtenues avec différentes graines d'initialisation (c'est-à-dire modifier les graines de champ dans le fichier de configuration) est cruciale pour TIMIT, car la variabilité des performances naturelles pourrait masquer complètement les preuves expérimentales. Nous avons remarqué un écart-type d'environ 0,2% pour les expériences TIMIT.
Si vous souhaitez modifier les fonctionnalités, vous devez d'abord les calculer avec la boîte à outils Kaldi. Pour calculer les fonctionnalités FBANK, vous devez ouvrir $ kaldi_root / egs / timit / s5 / run.sh et les calculer avec les lignes suivantes:
feadir=fbank
for x in train dev test; do
steps/make_fbank.sh --cmd "$train_cmd" --nj $feats_nj data/$x exp/make_fbank/$x $feadir
steps/compute_cmvn_stats.sh data/$x exp/make_fbank/$x $feadir
done
Ensuite, modifiez le fichier de configuration susmentionné avec la nouvelle liste de fonctionnalités. Si vous avez déjà exécuté la recette complète de Timit Kaldi, vous pouvez trouver directement les fonctionnalités FMLLR dans $ kaldi_root / egs / timit / s5 / data-fmllr-tri3 . Si vous nourrissez le réseau neuronal avec de telles fonctionnalités, vous devez vous attendre à une amélioration substantielle des performances, en raison de l'adoption de l'adaptation des orateurs.
Dans le dossier TIMIT_BASELING, nous proposons plusieurs autres exemples de lignes de base TIMIT possibles. De façon similaire à l'exemple précédent, vous pouvez les exécuter en tapant simplement:
python run_exp.py $cfg_file
Il existe quelques exemples avec récurrent (timit_rnn *, timit_lstm *, timit_gru *, timit_ligru *) et architectures CNN (TIMIT_CNN *). Nous proposons également un modèle plus avancé (TIMIT_DNN_LIGRU_DNN_MFCC + FBANK + FMLLR.CFG) où nous avons utilisé une combinaison de réseaux de neurones à alimentation et récurrents nourris par une concaténation des caractéristiques MFCC, FBANK et FMLLR. Notez que ces derniers fichiers de configuration correspondent à la meilleure architecture décrite dans le document de référence. Comme vous pouvez le voir à partir des fichiers de configuration susmentionnés, nous améliorons les performances de l'ASR en incluant certaines astuces telles que la régularisation monophone (c'est-à-dire que nous estimons conjointement les cibles dépendant du contexte et indépendantes du contexte). Le tableau suivant rapporte les résultats obtenus en exécutant ces derniers systèmes (moyenne par%):
| Modèle | MFCC | fbank | fmllr |
|---|---|---|---|
| Kaldi dnn de base | ----- | ------ | 18.5 |
| MLP | 18.2 | 18.7 | 16.7 |
| RNN | 17.7 | 17.2 | 15.9 |
| SRU | ----- | 16.6 | ----- |
| LSTM | 15.1 | 14.3 | 14.5 |
| Gru | 16.0 | 15.2 | 14.9 |
| li-gru | 15.5 | 14.9 | 14.2 |
Les résultats montrent que, comme prévu, les fonctionnalités FMLLR surpassent les coefficients MFCCS et FBANKS, grâce au processus d'adaptation des haut-parleurs. Les modèles récurrents surpassent considérablement le MLP standard, en particulier lors de l'utilisation de l'architecture LSTM, GRU et LI-GRU, qui abordent efficacement la fuite du gradient par des portes multiplicatives. Le meilleur résultat par = 14,2 $% est obtenu avec le modèle Li-Gru [2,3], qui est basé sur une seule porte et économise donc 33% des calculs sur un GRU standard.
Les meilleurs résultats sont en fait obtenus avec une architecture plus complexe qui combine des fonctionnalités MFCC, FBANK et FMLLR (voir CFG / TIMI_BASELINES / TIMIT_MFCC_FBANK_FMLLR_LIGU_BEST.CFG ). Au meilleur de nos connaissances, le PER = 13,8% obtenu par ce dernier système donne les performances les mieux publiées sur l'ensemble de test TIMIT.
Les unités récurrentes simples (SRU) sont un modèle récurrent efficace et très parallélisable. Ses performances sur ASR sont pires que les modèles LSTM, GRU et Li-Gru standard, mais il est nettement plus rapide. SRU est implémenté ici et décrit dans l'article suivant:
T. Lei, Y. Zhang, Si Wang, H. Dai, Y. Artzi, "Unités récurrentes simples pour une récidive hautement parallélisable, Proc. Of EMNLP 2018. Arxiv
Pour effectuer des expériences avec ce modèle, utilisez le fichier de configuration CFG / TIMIT_BASELINES / TIMIT_SRU_FBANK.CFG . Avant de devoir installer le modèle à l'aide pip install sru et vous devez décommer "Importer SRU" dans neural_networks.py .
Vous pouvez comparer directement vos résultats avec les nôtres en allant ici. Dans ce référentiel externe, vous pouvez trouver tous les dossiers contenant les fichiers générés.
Les étapes pour exécuter Pytorch-Kaldi sur l'ensemble de données LibrisEech sont similaires à celles rapportées ci-dessus pour TIMIT. Le tutoriel suivant est basé sur le sous-ensemble 100h , mais il peut être facilement étendu à l'ensemble de données complet (960h).
mkdir exp/tri4b/decode_tgsmall_train_clean_100 && cp exp/tri4b/trans.* exp/tri4b/decode_tgsmall_train_clean_100/
. ./cmd.sh ## You'll want to change cmd.sh to something that will work on your system.
. ./path.sh ## Source the tools/utils (import the queue.pl)
gmmdir=exp/tri4b
for chunk in train_clean_100 dev_clean test_clean; do
dir=fmllr/$chunk
steps/nnet/make_fmllr_feats.sh --nj 10 --cmd "$train_cmd"
--transform-dir $gmmdir/decode_tgsmall_$chunk
$dir data/$chunk $gmmdir $dir/log $dir/data || exit 1
compute-cmvn-stats --spk2utt=ark:data/$chunk/spk2utt scp:fmllr/$chunk/feats.scp ark:$dir/data/cmvn_speaker.ark
done
# aligments on dev_clean and test_clean
steps/align_fmllr.sh --nj 30 data/train_clean_100 data/lang exp/tri4b exp/tri4b_ali_clean_100
steps/align_fmllr.sh --nj 10 data/dev_clean data/lang exp/tri4b exp/tri4b_ali_dev_clean_100
steps/align_fmllr.sh --nj 10 data/test_clean data/lang exp/tri4b exp/tri4b_ali_test_clean_100
python run_exp.py cfg/Librispeech_baselines/libri_MLP_fmllr.cfg
Si vous souhaitez utiliser un modèle récurrent, vous pouvez utiliser libri_rnn_fmllr.cfg , libri_lstm_fmllr.cfg , libri_gru_fmllr.cfg , ou libri_ligru_fmllr.cfg . La formation des modèles récurrents pourrait prendre quelques jours (selon le GPU adopté). Les performances obtenues avec le graphique TGSMALL sont rapportées dans le tableau suivant:
| Modèle | Wer% |
|---|---|
| MLP | 9.6 |
| LSTM | 8.6 |
| Gru | 8.6 |
| li-gru | 8.6 |
Ces résultats sont obtenus sans ajouter de sauvetage en réseau (c'est-à-dire en utilisant uniquement le graphique TGSMall ). Vous pouvez améliorer les performances en ajoutant du sauvetage de réseau de cette manière (exécutez-le à partir du dossier kaldi_decoding_script de pytorch-kaldi):
data_dir=/data/milatmp1/ravanelm/librispeech/s5/data/
dec_dir=/u/ravanelm/pytorch-Kaldi-new/exp/libri_fmllr/decode_test_clean_out_dnn1/
out_dir=/u/ravanelm/pytorch-kaldi-new/exp/libri_fmllr/
steps/lmrescore_const_arpa.sh $data_dir/lang_test_{tgsmall,fglarge}
$data_dir/test_clean $dec_dir $out_dir/decode_test_clean_fglarge || exit 1;
Les résultats finaux obtenus à l'aide de la sauvetage ( FGLARGE ) sont rapportés dans le tableau suivant:
| Modèle | Wer% |
|---|---|
| MLP | 6.5 |
| LSTM | 6.4 |
| Gru | 6.3 |
| li-gru | 6.2 |
Vous pouvez jeter un coup d'œil aux résultats obtenus ici.
Le script principal pour exécuter une expérience ASR est run_exp.py . Ce script Python effectue des étapes de formation, de validation, de transfert et de décodage. La formation est effectuée sur plusieurs époques, qui traitent progressivement tout le matériel de formation avec le réseau neuronal considéré. Après chaque époque d'entraînement, une étape de validation est effectuée pour surveiller les performances du système sur les données de maintien . À la fin de la formation, la phase avant est effectuée en calculant les probabilités postérieures de l'ensemble de données de test spécifié. Les probabilités postérieures sont normalisées par leurs priors (à l'aide d'un fichier de comptage) et stockées dans un fichier ARK. Une étape de décodage est ensuite effectuée pour récupérer la séquence finale de mots prononcée par le haut-parleur dans les phrases de test.
Le script run_exp.py prend en entrée un fichier de configuration global (par exemple, cfg / timit_mlp_mfcc.cfg ) qui spécifie toutes les options nécessaires pour exécuter une expérience complète. Le code run_exp.py appelle une autre fonction run_nn (voir la bibliothèque Core.py) qui effectue une formation, une validation et des opérations à terme sur chaque morceau de données. La fonction RUN_NN prend en entrée un fichier de configuration spécifique à un morceau (par exemple, exp / timit_mlp_mfcc / exp_files / train_timit_tr + timit_dev_ep000_ck00.cfg *) qui spécifie tous les paramètres nécessaires pour exécuter une expérience à un seul coup. La fonction RUN_NN sort quelques remplissages d'informations (par exemple, exp / timit_mlp_mfcc / exp_files / trains_timit_tr + timit_dev_ep000_ck00.info ) qui résument les pertes et les erreurs du morceau traité.
Les résultats sont résumés dans les fichiers res.res , tandis que les erreurs et les avertissements sont redirigées dans le fichier log.log .
Il existe deux types de fichiers de configuration (fichiers CFG globaux et spécifiques à des morceaux). Ils sont à la fois au format INI et sont lus, traités et modifiés avec la bibliothèque ConfigParser de Python. Le fichier global contient plusieurs sections, qui spécifient toutes les étapes principales d'une expérience de reconnaissance vocale (formation, validation, avant et décodage). La structure du fichier de configuration est décrite dans un fichier prototype (voir par exemple proto / global.proto ) qui non seulement répertorie toutes les sections et champs requis, mais spécifie également le type de chaque champ possible. Par exemple, n_ep = int (1, inf) signifie que les champs N_EP (c'est-à-dire, le nombre d'époches de formation) doivent être un entier allant de 1 à Inf. De même, lr = float (0, inf) signifie que le champ LR (c'est-à-dire le taux d'apprentissage) doit être un flotteur allant de 0 à Inf. Toute tentative d'écriture d'un fichier de configuration non conforme à ces spécifications augmentera une erreur.
Essayons maintenant d'ouvrir un fichier de configuration (par exemple, CFG / TIMIT_BASELINES / TIMIT_MLP_MFCC_BASIC.CFG ) et décrivons les sections principales:
[cfg_proto]
cfg_proto = proto/global.proto
cfg_proto_chunk = proto/global_chunk.proto
La version actuelle du fichier de configuration spécifie d'abord les chemins des fichiers de prototypes globaux et spécifiques à un morceau dans la section [cfg_proto] .
[exp]
cmd =
run_nn_script = run_nn
out_folder = exp/TIMIT_MLP_basic5
seed = 1234
use_cuda = True
multi_gpu = False
save_gpumem = False
n_epochs_tr = 24
La section [EXP] contient des champs importants, tels que le dossier de sortie ( OUT_FOLDER ) et le chemin du chemin du script de traitement spécifique au morceau Run_nn (par défaut, cette fonction doit être implémentée dans la bibliothèque Core.py). Le champ N_EPOCHS_TR Spécifie le nombre sélectionné d'époches de formation. D'autres options sur l'utilisation_cuda, le multi_gpu et la sauvegarde_gpumem peuvent être activées par l'utilisateur. Le CMD de champ peut être utilisé pour ajouter une commande pour exécuter le script sur un cluster HPC.
[dataset1]
data_name = TIMIT_tr
fea = fea_name=mfcc
fea_lst=quick_test/data/train/feats_mfcc.scp
fea_opts=apply-cmvn --utt2spk=ark:quick_test/data/train/utt2spk ark:quick_test/mfcc/train_cmvn_speaker.ark ark:- ark:- | add-deltas --delta-order=2 ark:- ark:- |
cw_left=5
cw_right=5
lab = lab_name=lab_cd
lab_folder=quick_test/dnn4_pretrain-dbn_dnn_ali
lab_opts=ali-to-pdf
lab_count_file=auto
lab_data_folder=quick_test/data/train/
lab_graph=quick_test/graph
n_chunks = 5
[dataset2]
data_name = TIMIT_dev
fea = fea_name=mfcc
fea_lst=quick_test/data/dev/feats_mfcc.scp
fea_opts=apply-cmvn --utt2spk=ark:quick_test/data/dev/utt2spk ark:quick_test/mfcc/dev_cmvn_speaker.ark ark:- ark:- | add-deltas --delta-order=2 ark:- ark:- |
cw_left=5
cw_right=5
lab = lab_name=lab_cd
lab_folder=quick_test/dnn4_pretrain-dbn_dnn_ali_dev
lab_opts=ali-to-pdf
lab_count_file=auto
lab_data_folder=quick_test/data/dev/
lab_graph=quick_test/graph
n_chunks = 1
[dataset3]
data_name = TIMIT_test
fea = fea_name=mfcc
fea_lst=quick_test/data/test/feats_mfcc.scp
fea_opts=apply-cmvn --utt2spk=ark:quick_test/data/test/utt2spk ark:quick_test/mfcc/test_cmvn_speaker.ark ark:- ark:- | add-deltas --delta-order=2 ark:- ark:- |
cw_left=5
cw_right=5
lab = lab_name=lab_cd
lab_folder=quick_test/dnn4_pretrain-dbn_dnn_ali_test
lab_opts=ali-to-pdf
lab_count_file=auto
lab_data_folder=quick_test/data/test/
lab_graph=quick_test/graph
n_chunks = 1
Le fichier de configuration contient un certain nombre de sections ( [DataSet1] , [DataSet2] , [DataSet3] , ...) qui décrivent toutes les corpus utilisés pour l'expérience ASR. Les champs de la section [Dataset *] décrivent toutes les caractéristiques et étiquettes considérées dans l'expérience. Les fonctionnalités, par exemple, sont spécifiées dans le champ FEA:, où FEA_NAME contient le nom donné à la fonctionnalité, FEA_LST est la liste des fonctionnalités (au format SCP Kaldi), FEA_OPTS permet aux utilisateurs de spécifier comment traiter les fonctionnalités (par exemple, faire CMVN ou ajouter les dérivés), tandis que CW_LEFT et CW_RIGH ajouter). Notez que la version actuelle de la boîte à outils Pytorch-Kaldi prend en charge la définition de plusieurs flux de fonctionnalités. En effet, comme indiqué dans CFG / TIMIT_BASELINES / TIMIT_MFCC_FBANK_FMLLR_LIGRU_BEST.CFG, plusieurs flux de fonctionnalités (par exemple, MFCC, FBANK, FMLLR) sont utilisés.
De même, la section de laboratoire contient certains sous-champs. Par exemple, Lab_Name fait référence au nom donné à l'étiquette, tandis que Lab_Folder contient le dossier où les alignements générés par la recette de Kaldi sont stockés. LAB_OPTTS permet à l'utilisateur de spécifier certaines options sur les alignements considérés. Par exemple, lab_opts = "Ali-to-PDF" extrait les étiquettes standard-dépendant du contexte, tandis que Lab_OPTS = Ali-To-Phones --per-Frame = True peut être utilisé pour extraire des cibles monophones. LAB_COUNT_FILE est utilisé pour spécifier le fichier qui contient les comptes des états de téléphone considérés. Ces dénombrements sont importants dans la phase directe, où les probabilités postérieures calculées par le réseau neuronal sont divisées par leurs priors. Pytorch-Kaldi permet aux utilisateurs de spécifier un fichier de comptage externe ou de le récupérer automatiquement (à l'aide de Lab_count_file = Auto ). Les utilisateurs peuvent également spécifier Lab_count_file = Aucun Si le fichier de nombre n'est pas strictement nécessaire, par exemple, lorsque les étiquettes correspondent à une sortie non utilisée pour générer les probabilités postérieures utilisées dans la phase avant (voir par exemple les cibles monophone dans CFG / TIMIT_BASELINES / TIMIT_MLP_MFCC.CFG ). LAB_DATA_FOLDER , à la place, correspond au dossier de données créé lors de la préparation des données Kaldi. Il contient plusieurs fichiers, y compris le fichier texte finalement utilisé pour le calcul du WER final. Le dernier sous-champ Lab_Graph est le chemin du graphique Kaldi utilisé pour générer les étiquettes.
L'ensemble de données complet est généralement grand et ne peut pas s'adapter à la mémoire GPU / RAM. Il doit donc être divisé en plusieurs morceaux. Pytorch-Kaldi divise automatiquement l'ensemble de données dans le nombre de morceaux spécifiés dans n_chunks . Le nombre de morceaux peut dépendre de l'ensemble de données spécifique. En général, nous suggérons de traiter des morceaux de parole d'environ 1 ou 2 heures (selon la mémoire disponible).
[data_use]
train_with = TIMIT_tr
valid_with = TIMIT_dev
forward_with = TIMIT_test
Cette section indique comment les données répertoriées dans les sections [ensembles de données *] sont utilisées dans le script run_exp.py . La première ligne signifie que nous effectuons une formation avec les données appelées timit_tr . Notez que ce nom de l'ensemble de données doit apparaître dans l'une des sections de jeu de données, sinon l'analyseur de configuration augmentera une erreur. De même, les deuxième et troisième lignes spécifient respectivement les données utilisées pour la validation et les phases avant.
[batches]
batch_size_train = 128
max_seq_length_train = 1000
increase_seq_length_train = False
start_seq_len_train = 100
multply_factor_seq_len_train = 2
batch_size_valid = 128
max_seq_length_valid = 1000
Batch_size_train est utilisé pour définir le nombre d'exemples de formation dans le mini-lot. Les champs max_seq_length_train tronquent les phrases plus longtemps que la valeur spécifiée. Lors de la formation de modèles récurrents sur de très longues phrases, des problèmes hors mémoire pourraient survenir. Avec cette option, nous permettons aux utilisateurs d'atténuer ces problèmes de mémoire en tronquant les phrases longues. De plus, il est possible d'augmenter progressivement la longueur maximale de phrase pendant la formation en définissant Auggmente_SEQ_LENGTH_TRAIN = TRUE . Si vous êtes activé, la formation commence par une longueur maximale de phrase spécifiée dans start_seq_len_train (par exemple, start_seq_len_train = 100 ). Après chaque époque, la longueur de phrase maximale est multipliée par le mulply_factor_seq_len_train (par exemple mulply_factor_seq_len_train = 2 ). Nous avons observé que cette stratégie simple améliore généralement les performances du système car elle encourage le modèle à se concentrer d'abord sur les dépendances à court terme et à n'en apprendre à plus long terme qu'à un stade ultérieur.
De même, Batch_size_valid et Max_SEQ_LENGTH_VALID Spécifiez le nombre d'exemples dans les mini-lots et la longueur maximale pour l'ensemble de données Dev.
[architecture1]
arch_name = MLP_layers1
arch_proto = proto/MLP.proto
arch_library = neural_networks
arch_class = MLP
arch_pretrain_file = none
arch_freeze = False
arch_seq_model = False
dnn_lay = 1024,1024,1024,1024,N_out_lab_cd
dnn_drop = 0.15,0.15,0.15,0.15,0.0
dnn_use_laynorm_inp = False
dnn_use_batchnorm_inp = False
dnn_use_batchnorm = True,True,True,True,False
dnn_use_laynorm = False,False,False,False,False
dnn_act = relu,relu,relu,relu,softmax
arch_lr = 0.08
arch_halving_factor = 0.5
arch_improvement_threshold = 0.001
arch_opt = sgd
opt_momentum = 0.0
opt_weight_decay = 0.0
opt_dampening = 0.0
opt_nesterov = False
Les sections [architecture *] sont utilisées pour spécifier les architectures des réseaux de neurones impliqués dans les expériences ASR. Le champ Arch_name spécifie le nom de l'architecture. Étant donné que différents réseaux de neurones peuvent dépendre d'un ensemble différent d'hyperparamètres, l'utilisateur doit ajouter le chemin d'accès d'un fichier Proto qui contient la liste des hyperparamètres dans le champ Proto . Par exemple, le fichier prototype d'un modèle MLP standard contient les champs suivants:
[proto]
library=path
class=MLP
dnn_lay=str_list
dnn_drop=float_list(0.0,1.0)
dnn_use_laynorm_inp=bool
dnn_use_batchnorm_inp=bool
dnn_use_batchnorm=bool_list
dnn_use_laynorm=bool_list
dnn_act=str_list
De façon similaire aux autres fichiers prototypes, chaque ligne définit un hyperparamètre avec le type de valeur associé. Tous les hyperparamètres définis dans le fichier Proto doivent apparaître dans le fichier de configuration globale dans la section [Architecture *] correspondante. Le champ Arch_Library spécifie où le modèle est codé (par exemple neural_nets.py ), tandis que arch_class indique le nom de la classe où l'architecture est implémentée (par exemple si nous définissons la classe = MLP, nous ferons à partir de neural_nets.py import MLP ).
Le champ Arch_pretrain_file peut être utilisé pour pré-entraîner le réseau neuronal avec une architecture précédemment formée, tandis que Arch_freeze peut être réglé sur False si vous souhaitez former les paramètres de l'architecture pendant la formation et devrait être défini sur TRUE , garder les paramètres fixes (c'est-à-dire gelés) pendant la formation. La section ARCH_SEQ_MODEL indique si l'architecture est séquentielle (par exemple RNNS) ou non séquentielle (par exemple, un MLP ou CNN pour les aliments pour animation). La façon dont Pytorch-Kaldi traite les lots d'entrée est différent dans les deux cas. Pour les réseaux de neurones récurrents ( arch_seq_model = true ), la séquence des fonctionnalités n'est pas randomisée (pour préserver les éléments des séquences), tandis que pour les modèles de restauration ( arch_seq_model = false ), nous randomions les fonctionnalités (cela contribue généralement à améliorer les performances). Dans le cas de plusieurs architectures, le traitement séquentiel est utilisé si au moins une des architectures employées est marquée comme séquentielle ( arch_seq_model = true ).
Notez que les hyperparamètres commençant par "Arch_" et "Opt_" sont obligatoires et doivent être présents dans toute l'architecture spécifiée dans le fichier de configuration. Les autres hyperparamètres (par exemple, dnn_ *,) sont spécifiques de l'architecture considérée (ils dépendent de la façon dont la classe MLP est réellement implémentée par l'utilisateur) et peut définir le nombre et la typologie des couches cachées, des normalisations par lots et des calques et d'autres paramètres. D'autres paramètres importants sont liés à l'optimisation de l'architecture considérée. Par exemple, Arch_lr est le taux d'apprentissage, tandis que Arch_halving_factor est utilisé pour implémenter le recuit du taux d'apprentissage. En particulier, lorsque l'amélioration relative des performances sur le Dev-Set entre deux époques consécutives est plus petite que celle spécifiée dans l' arch_improvement_threshold (par exemple, arch_improvement_threshold), nous multiplions le taux d'apprentissage par le arch_halving_factor (par exemple, arch_halving_factor = 0,5 ). Le champ Arch_opt spécifie le type d'algorithme d'optimisation. Nous soutenons actuellement SGD, Adam et RMSProp. Les autres paramètres sont spécifiques à l'algorithme d'optimisation considéré (voir la documentation Pytorch pour une signification exacte de tous les hyperparamètres spécifiques à l'optimisation). Notez que les différentes architectures définies dans [Archirictucture *] peuvent avoir différentes hyperparamètres d'optimisation et ils peuvent même utiliser un algorithme d'optimisation différent.
[model]
model_proto = proto/model.proto
model = out_dnn1=compute(MLP_layers1,mfcc)
loss_final=cost_nll(out_dnn1,lab_cd)
err_final=cost_err(out_dnn1,lab_cd)
La façon dont toutes les différentes fonctionnalités et architectures sont combinées est spécifiée dans cette section avec une méta-langage très simple et intuitive. Le modèle de champ: décrit comment les fonctionnalités et les architectures sont connectées pour générer en tant que sortie d'un ensemble de probabilités postérieures. La ligne out_dnn1 = calcul (mlp_layers, mfcc) signifie " alimenter l'architecture appelée mlp_layers1 avec les fonctionnalités appelées mfcc et stocker la sortie dans la variable out_dn1 ". À partir de la sortie du réseau neural OUT_DNN1, l'erreur et les fonctions de perte sont calculées à l'aide des étiquettes appelées lab_cd , qui doivent être précédemment définies dans les sections [de données *] . Les champs ERR_FINAL et Loss_Final sont des sous-champs obligatoires qui définissent la sortie finale du modèle.
Un exemple beaucoup plus complexe (discuté ici juste pour mettre en évidence la potentialité de la boîte à outils) est signalé dans CFG / TIMIT_BASELINES / TIMIT_MFCC_FBANK_FMLLR_LIGRU_BEST.CFG :
[model]
model_proto=proto/model.proto
model:conc1=concatenate(mfcc,fbank)
conc2=concatenate(conc1,fmllr)
out_dnn1=compute(MLP_layers_first,conc2)
out_dnn2=compute(liGRU_layers,out_dnn1)
out_dnn3=compute(MLP_layers_second,out_dnn2)
out_dnn4=compute(MLP_layers_last,out_dnn3)
out_dnn5=compute(MLP_layers_last2,out_dnn3)
loss_mono=cost_nll(out_dnn5,lab_mono)
loss_mono_w=mult_constant(loss_mono,1.0)
loss_cd=cost_nll(out_dnn4,lab_cd)
loss_final=sum(loss_cd,loss_mono_w)
err_final=cost_err(out_dnn4,lab_cd)
Dans ce cas, nous concatenons d'abord les fonctionnalités MFCC, FBANK et FMLLR et nous nourrissons ensuite un MLP. La sortie du MLP est introduite dans le réseau neuronal récurrent (en particulier un modèle li-gru). Nous avons ensuite une autre couche MLP ( MLP_LAYERS_SECOND ) suivie de deux classificateurs SoftMax (c'est-à-dire MLP_LAYERS_LAST , MLP_LAYERS_LAST2 ). Le premier estime les états standard dépendants du contexte, tandis que le second estime les cibles monophones. La fonction de coût final est une somme pondérée entre ces deux prédictions. De cette façon, nous mettons en œuvre la régularisation monophone, qui s'est avérée utile pour améliorer les performances de l'ASR.
Le modèle complet peut être considéré comme un seul grand graphique de calcul, où toutes les architectures de base utilisées dans la section [modèle] sont formées conjointement. Pour chaque mini-lot, les fonctionnalités d'entrée sont propagées via le modèle complet et le Cost_final est calculé à l'aide des étiquettes spécifiées. Le gradient de la fonction de coût par rapport à tous les paramètres apprenables de l'architecture est ensuite calculé. Tous les paramètres des architectures employés sont ensuite mis à jour avec l'algorithme spécifié dans les sections [Architecture *] .
[forward]
forward_out = out_dnn1
normalize_posteriors = True
normalize_with_counts_from = lab_cd
save_out_file = True
require_decoding = True
La section vers l'avant définit d'abord qui est la sortie à transmettre (elle doit être définie dans la section du modèle). Si Normalize_posteriors = True , ces postérieurs sont normalisés par leurs prieurs (en utilisant un fichier de comptage). Si Save_out_file = true , le fichier postérieur (généralement un très gros fichier ark) est stocké, tandis que si Save_out_file = false, ce fichier est supprimé lorsqu'il n'est plus nécessaire. Le requis_decoding est un booléen qui spécifie si nous devons décoder la sortie spécifiée. Le champ Normalize_With_Couts_From SET qui compte pour normaliser les probabilités postérieures.
[decoding]
decoding_script_folder = kaldi_decoding_scripts/
decoding_script = decode_dnn.sh
decoding_proto = proto/decoding.proto
min_active = 200
max_active = 7000
max_mem = 50000000
beam = 13.0
latbeam = 8.0
acwt = 0.2
max_arcs = -1
skip_scoring = false
scoring_script = local/score.sh
scoring_opts = "--min-lmwt 1 --max-lmwt 10"
norm_vars = False
La section de décodage rapporte des paramètres sur le décodage, c'est-à-dire les étapes qui permettent de passer d'une séquence des probabilités dépendantes du contexte fournies par le DNN dans une séquence de mots. Le champ decoding_script_folder spécifie le dossier où le script de décodage est stocké. The decoding script field is the script used for decoding (eg, decode_dnn.sh ) that should be in the decoding_script_folder specified before. The field decoding_proto reports all the parameters needed for the considered decoding script.
To make the code more flexible, the config parameters can also be specified within the command line. For example, you can run:
python run_exp.py quick_test/example_newcode.cfg --optimization,lr=0.01 --batches,batch_size=4
The script will replace the learning rate in the specified cfg file with the specified lr value. The modified config file is then stored into out_folder/config.cfg .
The script run_exp.py automatically creates chunk-specific config files, that are used by the run_nn function to perform a single chunk training. The structure of chunk-specific cfg files is very similar to that of the global one. The main difference is a field to_do={train, valid, forward} that specifies the type of processing to on the features chunk specified in the field fea .
Why proto files? Different neural networks, optimization algorithms, and HMM decoders might depend on a different set of hyperparameters. To address this issue, our current solution is based on the definition of some prototype files (for global, chunk, architecture config files). In general, this approach allows a more transparent check of the fields specified into the global config file. Moreover, it allows users to easily add new parameters without changing any line of the python code. For instance, to add a user-defined model, a new proto file (eg, user-model.prot o) that specifies the hyperparameter must be written. Then, the user should only write a class (eg, user-model in neural_networks.py ) that implements the architecture).
The toolkit is designed to allow users to easily plug-in their own acoustic models. To add a customized neural model do the following steps:
[proto]
dnn_lay=str_list
dnn_drop=float_list(0.0,1.0)
dnn_use_laynorm_inp=bool
dnn_use_batchnorm_inp=bool
dnn_use_batchnorm=bool_list
dnn_use_laynorm=bool_list
dnn_act=str_list
The parameter dnn_lay must be a list of string, dnn_drop (ie, the dropout factors for each layer) is a list of float ranging from 0.0 and 1.0, dnn_use_laynorm_inp and dnn_use_batchnorm_inp are booleans that enable or disable batch or layer normalization of the input. dnn_use_batchnorm and dnn_use_laynorm are a list of boolean that decide layer by layer if batch/layer normalization has to be used. The parameter dnn_act is again a list of string that sets the activation function of each layer. Since every model is based on its own set of hyperparameters, different models have a different prototype file. For instance, you can take a look into GRU.proto and see that the hyperparameter list is different from that of a standard MLP. Similarly to the previous examples, you should add here your list of hyperparameters and save the file.
Write a PyTorch class implementing your model. Open the library neural_networks.py and look at some of the models already implemented. For simplicity, you can start taking a look into the class MLP. The classes have two mandatory methods: init and forward . The first one is used to initialize the architecture, the second specifies the list of computations to do. The method init takes in input two variables that are automatically computed within the run_nn function. inp_dim is simply the dimensionality of the neural network input, while options is a dictionary containing all the parameters specified into the section architecture of the configuration file.
For instance, you can access to the DNN activations of the various layers in this way: options['dnn_lay'].split(',') . As you might see from the MLP class, the initialization method defines and initializes all the parameters of the neural network. The forward method takes in input a tensor x (ie, the input data) and outputs another vector containing x. If your model is a sequence model (ie, if there is at least one architecture with arch_seq_model=true in the cfg file), x is a tensor with (time_steps, batches, N_in), otherwise is a (batches, N_in) matrix. The class forward defines the list of computations to transform the input tensor into a corresponding output tensor. The output must have the sequential format (time_steps, batches, N_out) for recurrent models and the non-sequential format (batches, N_out) for feed-forward models. Similarly to the already-implemented models the user should write a new class (eg, myDNN) that implements the customized model:
class myDNN(nn.Module):
def __init__(self, options,inp_dim):
super(myDNN, self).__init__()
// initialize the parameters
def forward(self, x):
// do some computations out=f(x)
return out
[architecture1]
arch_name= mynetwork (this is a name you would like to use to refer to this architecture within the following model section)
arch_proto=proto/myDNN.proto (here is the name of the proto file defined before)
arch_library=neural_networks (this is the name of the library where myDNN is implemented)
arch_class=myDNN (This must be the name of the class you have implemented)
arch_pretrain_file=none (With this you can specify if you want to pre-train your model)
arch_freeze=False (set False if you want to update the parameters of your model)
arch_seq_model=False (set False for feed-forward models, True for recurrent models)
Then, you have to specify proper values for all the hyperparameters specified in proto/myDNN.proto . For the MLP.proto , we have:
dnn_lay=1024,1024,1024,1024,1024,N_out_lab_cd
dnn_drop=0.15,0.15,0.15,0.15,0.15,0.0
dnn_use_laynorm_inp=False
dnn_use_batchnorm_inp=False
dnn_use_batchnorm=True,True,True,True,True,False
dnn_use_laynorm=False,False,False,False,False,False
dnn_act=relu,relu,relu,relu,relu,softmax
Then, add the following parameters related to the optimization of your own architecture. You can use here standard sdg, adam, or rmsprop (see cfg/TIMIT_baselines/TIMIT_LSTM_mfcc.cfg for an example with rmsprop):
arch_lr=0.08
arch_halving_factor=0.5
arch_improvement_threshold=0.001
arch_opt=sgd
opt_momentum=0.0
opt_weight_decay=0.0
opt_dampening=0.0
opt_nesterov=False
Save the configuration file into the cfg folder (eg, cfg/myDNN_exp.cfg ).
Run the experiment with:
python run_exp.py cfg/myDNN_exp.cfg
When implementing a new model, an important debug test consists of doing an overfitting experiment (to make sure that the model is able to overfit a tiny dataset). If the model is not able to overfit, it means that there is a major bug to solve.
A hyperparameter tuning is often needed in deep learning to search for proper neural architectures. To help tuning the hyperparameters within PyTorch-Kaldi, we have implemented a simple utility that implements a random search. In particular, the script tune_hyperparameters.py generates a set of random configuration files and can be run in this way:
python tune_hyperparameters.py cfg/TIMIT_MLP_mfcc.cfg exp/TIMIT_MLP_mfcc_tuning 10 arch_lr=randfloat(0.001,0.01) batch_size_train=randint(32,256) dnn_act=choose_str{relu,relu,relu,relu,softmax|tanh,tanh,tanh,tanh,softmax}
The first parameter is the reference cfg file that we would like to modify, while the second one is the folder where the random configuration files are saved. The third parameter is the number of the random config file that we would like to generate. There is then the list of all the hyperparameters that we want to change. For instance, arch_lr=randfloat(0.001,0.01) will replace the field arch_lr with a random float ranging from 0.001 to 0.01. batch_size_train=randint(32,256) will replace batch_size_train with a random integer between 32 and 256 and so on. Once the config files are created, they can be run sequentially or in parallel with:
python run_exp.py $cfg_file
PyTorch-Kaldi can be used with any speech dataset. To use your own dataset, the steps to take are similar to those discussed in the TIMIT/Librispeech tutorials. In general, what you have to do is the following:
python run_exp.py $cfg_file . The current version of PyTorch-Kaldi supports input features stored with the Kaldi ark format. If the user wants to perform experiments with customized features, the latter must be converted into the ark format. Take a look into the Kaldi-io-for-python git repository (https://github.com/vesis84/kaldi-io-for-python) for a detailed description about converting numpy arrays into ark files. Moreover, you can take a look into our utility called save_raw_fea.py. This script generates Kaldi ark files containing raw features, that are later used to train neural networks fed by the raw waveform directly (see the section about processing audio with SincNet).
The current version of Pytorch-Kaldi supports the standard production process of using a Pytorch-Kaldi pre-trained acoustic model to transcript one or multiples .wav files. It is important to understand that you must have a trained Pytorch-Kaldi model. While you don't need labels or alignments anymore, Pytorch-Kaldi still needs many files to transcript a new audio file:
Once you have all these files, you can start adding your dataset section to the global configuration file. The easiest way is to copy the cfg file used to train your acoustic model and just modify by adding a new [dataset] :
[dataset4]
data_name = myWavFile
fea = fea_name=fbank
fea_lst=myWavFilePath/data/feats.scp
fea_opts=apply-cmvn --utt2spk=ark:myWavFilePath/data//utt2spk ark:myWavFilePath/cmvn_test.ark ark:- ark:- | add-deltas --delta-order=0 ark:- ark:- |
cw_left=5
cw_right=5
lab = lab_name=none
lab_data_folder=myWavFilePath/data/
lab_graph=myWavFilePath/exp/tri3/graph
n_chunks=1
[data_use]
train_with = TIMIT_tr
valid_with = TIMIT_dev
forward_with = myWavFile
The key string for your audio file transcription is lab_name=none . The none tag asks Pytorch-Kaldi to enter a production mode that only does the forward propagation and decoding without any labels. You don't need TIMIT_tr and TIMIT_dev to be on your production server since Pytorch-Kaldi will skip this information to directly go to the forward phase of the dataset given in the forward_with field. As you can see, the global fea field requires the exact same parameters than standard training or testing dataset, while the lab field only requires two parameters. Please, note that lab_data_folder is nothing more than the same path as fea_lst . Finally, you still need to specify the number of chunks you want to create to process this file (1 hour = 1 chunk).
WARNINGS
In your standard .cfg, you might have used keywords such as N_out_lab_cd that can not be used anymore. Indeed, in a production scenario, you don't want to have the training data on your machine. Therefore, all the variables that were on your .cfg file must be replaced by their true values. To replace all the N_out_{mono,lab_cd} you can take a look at the output of:
hmm-info /path/to/the/final.mdl/used/to/generate/the/training/ali
Then, if you normalize posteriors as (check in your .cfg Section forward):
normalize_posteriors = True
normalize_with_counts_from = lab_cd
You must replace lab_cd by:
normalize_posteriors = True
normalize_with_counts_from = /path/to/ali_train_pdf.counts
This normalization step is crucial for HMM-DNN speech recognition. DNNs, in fact, provide posterior probabilities, while HMMs are generative models that work with likelihoods. To derive the required likelihoods, one can simply divide the posteriors by the prior probabilities. To create this ali_train_pdf.counts file you can follow:
alidir=/path/to/the/exp/tri_ali (change it with your path to the exp with the ali)
num_pdf=$(hmm-info $alidir/final.mdl | awk '/pdfs/{print $4}')
labels_tr_pdf="ark:ali-to-pdf $alidir/final.mdl "ark:gunzip -c $alidir/ali.*.gz |" ark:- |"
analyze-counts --verbose=1 --binary=false --counts-dim=$num_pdf "$labels_tr_pdf" ali_train_pdf.counts
et voilà ! In a production scenario, you might need to transcript a huge number of audio files, and you don't want to create as much as needed .cfg file. In this extent, and after creating this initial production .cfg file (you can leave the path blank), you can call the run_exp.py script with specific arguments referring to your different.wav features:
python run_exp.py cfg/TIMIT_baselines/TIMIT_MLP_fbank_prod.cfg --dataset4,fea,0,fea_lst="myWavFilePath/data/feats.scp" --dataset4,lab,0,lab_data_folder="myWavFilePath/data/" --dataset4,lab,0,lab_graph="myWavFilePath/exp/tri3/graph/"
This command will internally alter the configuration file with your specified paths, and run and your defined features! Note that passing long arguments to the run_exp.py script requires a specific notation. --dataset4 specifies the name of the created section, fea is the name of the higher level field, fea_lst or lab_graph are the name of the lowest level field you want to change. The 0 is here to indicate which lowest level field you want to alter, indeed some configuration files may contain multiple lab_graph per dataset! Therefore, 0 indicates the first occurrence, 1 the second ... Paths MUST be encapsulated by " " to be interpreted as full strings! Note that you need to alter the data_name and forward_with fields if you don't want different .wav files transcriptions to erase each other (decoding files are stored accordingly to the field data_name ). --dataset4,data_name=MyNewName --data_use,forward_with=MyNewName .
In order to give users more flexibility, the latest version of PyTorch-Kaldi supports scheduling of the batch size, max_seq_length_train, learning rate, and dropout factor. This means that it is now possible to change these values during training. To support this feature, we implemented the following formalisms within the config files:
batch_size_train = 128*12 | 64*10 | 32*2
In this case, our batch size will be 128 for the first 12 epochs, 64 for the following 10 epochs, and 32 for the last two epochs. By default "*" means "for N times", while "|" is used to indicate a change of the batch size. Note that if the user simply sets batch_size_train = 128 , the batch size is kept fixed during all the training epochs by default.
A similar formalism can be used to perform learning rate scheduling:
arch_lr = 0.08*10|0.04*5|0.02*3|0.01*2|0.005*2|0.0025*2
In this case, if the user simply sets arch_lr = 0.08 the learning rate is annealed with the new-bob procedure used in the previous version of the toolkit. In practice, we start from the specified learning rate and we multiply it by a halving factor every time that the improvement on the validation dataset is smaller than the threshold specified in the field arch_improvement_threshold .
Also the dropout factor can now be changed during training with the following formalism:
dnn_drop = 0.15*12|0.20*12,0.15,0.15*10|0.20*14,0.15,0.0
With the line before we can set a different dropout rate for different layers and for different epochs. For instance, the first hidden layer will have a dropout rate of 0.15 for the first 12 epochs, and 0.20 for the other 12. The dropout factor of the second layer, instead, will remain constant to 0.15 over all the training. The same formalism is used for all the layers. Note that "|" indicates a change in the dropout factor within the same layer, while "," indicates a different layer.
You can take a look here into a config file where batch sizes, learning rates, and dropout factors are changed here:
cfg/TIMIT_baselines/TIMIT_mfcc_basic_flex.cfg
or here:
cfg/TIMIT_baselines/TIMIT_liGRU_fmllr_lr_schedule.cfg
The project is still in its initial phase and we invite all potential contributors to participate. We hope to build a community of developers larger enough to progressively maintain, improve, and expand the functionalities of our current toolkit. For instance, it could be helpful to report any bug or any suggestion to improve the current version of the code. People can also contribute by adding additional neural models, that can eventually make richer the set of currently-implemented architectures.
Jetez un œil à notre vidéo Introduction à Sincnet
SincNet is a convolutional neural network recently proposed to process raw audio waveforms. In particular, SincNet encourages the first layer to discover more meaningful filters by exploiting parametrized sinc functions. In contrast to standard CNNs, which learn all the elements of each filter, only low and high cutoff frequencies of band-pass filters are directly learned from data. This inductive bias offers a very compact way to derive a customized filter-bank front-end, that only depends on some parameters with a clear physical meaning.
For a more detailed description of the SincNet model, please refer to the following papers:
M. Ravanelli, Y. Bengio, "Speaker Recognition from raw waveform with SincNet", in Proc. of SLT 2018 ArXiv
M. Ravanelli, Y.Bengio, "Interpretable Convolutional Filters with SincNet", in Proc. of NIPS@IRASL 2018 ArXiv
To use this model for speech recognition on TIMIT, to the following steps:
python ./run_exp.py cfg/TIMIT_baselines/TIMIT_SincNet_raw.cfg
In the following table, we compare the result of SincNet with other feed-forward neural network:
| Modèle | WER(%) |
|---|---|
| MLP -fbank | 18.7 |
| MLP -mfcc | 18.2 |
| CNN -raw | 18.1 |
| SincNet -raw | 17.2 |
In this section, we show how to use PyTorch-Kaldi to jointly train a cascade between a speech enhancement and a speech recognition neural networks. The speech enhancement has the goal of improving the quality of the speech signal by minimizing the MSE between clean and noisy features. The enhanced features then feed another neural network that predicts context-dependent phone states.
In the following, we report a toy-task example based on a reverberated version of TIMIT, that is only intended to show how users should set the config file to train such a combination of neural networks. Even though some implementation details (and the adopted datasets) are different, this tutorial is inspired by this paper:
To run the system do the following steps:
1- Make sure you have the standard clean version of TIMIT available.
2- Run the Kaldi s5 baseline of TIMIT. This step is necessary to compute the clean features (that will be the labels of the speech enhancement system) and the alignments (that will be the labels of the speech recognition system). We recommend running the full timit s5 recipe (including the DNN training).
3- The standard TIMIT recipe uses MFCCs features. In this tutorial, instead, we use FBANK features. To compute FBANK features run the following script in $KALDI_ROOT/egs/TIMIT/s5 :
feadir=fbank
for x in train dev test; do
steps/make_fbank.sh --cmd "$train_cmd" --nj $feats_nj data/$x exp/make_fbank/$x $feadir
steps/compute_cmvn_stats.sh data/$x exp/make_fbank/$x $feadir
done
Note that we use 40 FBANKS here, while Kaldi uses by default 23 FBANKs. To compute 40-dimensional features go into "$KALDI_ROOT/egs/TIMIT/conf/fbank.conf" and change the number of considered output filters.
4- Go to this external repository and follow the steps to generate a reverberated version of TIMIT starting from the clean one. Note that this is just a toy task that is only helpful to show how setting up a joint-training system.
5- Compute the FBANK features for the TIMIT_rev dataset. To do it, you can copy the scripts in $KALDI_ROOT/egs/TIMIT/ into $KALDI_ROOT/egs/TIMIT_rev/ . Please, copy also the data folder. Note that the audio files in the TIMIT_rev folders are saved with the standard WAV format, while TIMIT is released with the SPHERE format. To bypass this issue, open the files data/train/wav.scp , data/dev/wav.scp , data/test/wav.scp and delete the part about SPHERE reading (eg, /home/mirco/kaldi-trunk/tools/sph2pipe_v2.5/sph2pipe -f wav ). You also have to change the paths from the standard TIMIT to the reverberated one (eg replace /TIMIT/ with /TIMIT_rev/). Remind to remove the final pipeline symbol“ |”. Save the changes and run the computation of the fbank features in this way:
feadir=fbank
for x in train dev test; do
steps/make_fbank.sh --cmd "$train_cmd" --nj $feats_nj data/$x exp/make_fbank/$x $feadir
steps/compute_cmvn_stats.sh data/$x exp/make_fbank/$x $feadir
done
Remember to change the $KALDI_ROOT/egs/TIMIT_rev/conf/fbank.conf file in order to compute 40 features rather than the 23 FBANKS of the default configuration.
6- Once features are computed, open the following config file:
cfg/TIMIT_baselines/TIMIT_rev/TIMIT_joint_training_liGRU_fbank.cfg
Remember to change the paths according to where data are stored in your machine. As you can see, we consider two types of features. The fbank_rev features are computed from the TIMIT_rev dataset, while the fbank_clean features are derived from the standard TIMIT dataset and are used as targets for the speech enhancement neural network. As you can see in the [model] section of the config file, we have the cascade between networks doing speech enhancement and speech recognition. The speech recognition architecture jointly estimates both context-dependent and monophone targets (thus using the so-called monophone regularization). To run an experiment type the following command:
python run_exp.py cfg/TIMIT_baselines/TIMIT_rev/TIMIT_joint_training_liGRU_fbank.cfg
7- Results With this configuration file, you should obtain a Phone Error Rate (PER)=28.1% . Note that some oscillations around this performance are more than natural and are due to different initialization of the neural parameters.
You can take a closer look into our results here
In this tutorial, we use the DIRHA-English dataset to perform a distant speech recognition experiment. The DIRHA English Dataset is a multi-microphone speech corpus being developed under the EC project DIRHA. The corpus is composed of both real and simulated sequences recorded with 32 sample-synchronized microphones in a domestic environment. The database contains signals of different characteristics in terms of noise and reverberation making it suitable for various multi-microphone signal processing and distant speech recognition tasks. The part of the dataset currently released is composed of 6 native US speakers (3 Males, 3 Females) uttering 409 wall-street journal sentences. The training data have been created using a realistic data contamination approach, that is based on contaminating the clean speech wsj-5k sentences with high-quality multi-microphone impulse responses measured in the targeted environment. For more details on this dataset, please refer to the following papers:
M. Ravanelli, L. Cristoforetti, R. Gretter, M. Pellin, A. Sosi, M. Omologo, "The DIRHA-English corpus and related tasks for distant-speech recognition in domestic environments", in Proceedings of ASRU 2015. ArXiv
M. Ravanelli, P. Svaizer, M. Omologo, "Realistic Multi-Microphone Data Simulation for Distant Speech Recognition", in Proceedings of Interspeech 2016. ArXiv
In this tutorial, we use the aforementioned simulated data for training (using LA6 microphone), while test is performed using the real recordings (LA6). This task is very realistic, but also very challenging. The speech signals are characterized by a reverberation time of about 0.7 seconds. Non-stationary domestic noises (such as vacuum cleaner, steps, phone rings, etc.) are also present in the real recordings.
Let's start now with the practical tutorial.
1- If not available, download the DIRHA dataset from the LDC website. LDC releases the full dataset for a small fee.
2- Go this external reposotory. As reported in this repository, you have to generate the contaminated WSJ dataset with the provided MATLAB script. Then, you can run the proposed KALDI baseline to have features and labels ready for our pytorch-kaldi toolkit.
3- Open the following configuration file:
cfg/DIRHA_baselines/DIRHA_liGRU_fmllr.cfg
The latter configuration file implements a simple RNN model based on a Light Gated Recurrent Unit (Li-GRU). We used fMLLR as input features. Change the paths and run the following command:
python run_exp.py cfg/DIRHA_baselines/DIRHA_liGRU_fmllr.cfg
4- Results: The aforementioned system should provide Word Error Rate (WER%)=23.2% . You can find the results obtained by us here.
Using the other configuration files in the cfg/DIRHA_baselines folder you can perform experiments with different setups. With the provided configuration files you can obtain the following results:
| Modèle | WER(%) |
|---|---|
| MLP | 26.1 |
| Gru | 25.3 |
| Li-GRU | 23.8 |
The current version of the repository is mainly designed for speech recognition experiments. We are actively working a new version, which is much more flexible and can manage input/output different from Kaldi features/labels. Even with the current version, however, it is possible to implement other systems, such as an autoencoder.
An autoencoder is a neural network whose inputs and outputs are the same. The middle layer normally contains a bottleneck that forces our representations to compress the information of the input. In this tutorial, we provide a toy example based on the TIMIT dataset. For instance, see the following configuration file:
cfg/TIMIT_baselines/TIMIT_MLP_fbank_autoencoder.cfg
Our inputs are the standard 40-dimensional fbank coefficients that are gathered using a context windows of 11 frames (ie, the total dimensionality of our input is 440). A feed-forward neural network (called MLP_encoder) encodes our features into a 100-dimensional representation. The decoder (called MLP_decoder) is fed by the learned representations and tries to reconstruct the output. The system is trained with Mean Squared Error (MSE) metric. Note that in the [Model] section we added this line “err_final=cost_err(dec_out,lab_cd)” at the end. The current version of the model, in fact, by default needs that at least one label is specified (we will remove this limit in the next version).
You can train the system running the following command:
python run_exp.py cfg/TIMIT_baselines/TIMIT_MLP_fbank_autoencoder.cfg
The results should look like this:
ep=000 tr=['TIMIT_tr'] loss=0.139 err=0.999 valid=TIMIT_dev loss=0.076 err=1.000 lr_architecture1=0.080000 lr_architecture2=0.080000 time(s)=41
ep=001 tr=['TIMIT_tr'] loss=0.098 err=0.999 valid=TIMIT_dev loss=0.062 err=1.000 lr_architecture1=0.080000 lr_architecture2=0.080000 time(s)=39
ep=002 tr=['TIMIT_tr'] loss=0.091 err=0.999 valid=TIMIT_dev loss=0.058 err=1.000 lr_architecture1=0.040000 lr_architecture2=0.040000 time(s)=39
ep=003 tr=['TIMIT_tr'] loss=0.088 err=0.999 valid=TIMIT_dev loss=0.056 err=1.000 lr_architecture1=0.020000 lr_architecture2=0.020000 time(s)=38
ep=004 tr=['TIMIT_tr'] loss=0.087 err=0.999 valid=TIMIT_dev loss=0.055 err=0.999 lr_architecture1=0.010000 lr_architecture2=0.010000 time(s)=39
ep=005 tr=['TIMIT_tr'] loss=0.086 err=0.999 valid=TIMIT_dev loss=0.054 err=1.000 lr_architecture1=0.005000 lr_architecture2=0.005000 time(s)=39
ep=006 tr=['TIMIT_tr'] loss=0.086 err=0.999 valid=TIMIT_dev loss=0.054 err=1.000 lr_architecture1=0.002500 lr_architecture2=0.002500 time(s)=39
ep=007 tr=['TIMIT_tr'] loss=0.086 err=0.999 valid=TIMIT_dev loss=0.054 err=1.000 lr_architecture1=0.001250 lr_architecture2=0.001250 time(s)=39
ep=008 tr=['TIMIT_tr'] loss=0.086 err=0.999 valid=TIMIT_dev loss=0.054 err=0.999 lr_architecture1=0.000625 lr_architecture2=0.000625 time(s)=41
ep=009 tr=['TIMIT_tr'] loss=0.086 err=0.999 valid=TIMIT_dev loss=0.054 err=0.999 lr_architecture1=0.000313 lr_architecture2=0.000313 time(s)=38
You should only consider the field "loss=". The filed "err=" only contains not useuful information in this case (for the aforementioned reason). You can take a look into the generated features typing the following command:
copy-feats ark:exp/TIMIT_MLP_fbank_autoencoder/exp_files/forward_TIMIT_test_ep009_ck00_enc_out.ark ark,t:- | more
[1] M. Ravanelli, T. Parcollet, Y. Bengio, "The PyTorch-Kaldi Speech Recognition Toolkit", ArxIv
[2] M. Ravanelli, P. Brakel, M. Omologo, Y. Bengio, "Improving speech recognition by revising gated recurrent units", in Proceedings of Interspeech 2017. ArXiv
[3] M. Ravanelli, P. Brakel, M. Omologo, Y. Bengio, "Light Gated Recurrent Units for Speech Recognition", in IEEE Transactions on Emerging Topics in Computational Intelligence. ArXiv
[4] M. Ravanelli, "Deep Learning for Distant Speech Recognition", PhD Thesis, Unitn 2017. ArXiv
[5] T. Parcollet, M. Ravanelli, M. Morchid, G. Linarès, C. Trabelsi, R. De Mori, Y. Bengio, "Quaternion Recurrent Neural Networks", in Proceedings of ICLR 2019 ArXiv
[6] T. Parcollet, M. Morchid, G. Linarès, R. De Mori, "Bidirectional Quaternion Long-Short Term Memory Recurrent Neural Networks for Speech Recognition", in Proceedings of ICASSP 2019 ArXiv