Rauschunterdrückung bei CMU-Sphinx

    Wir können mit Sicherheit sagen, dass CMU Sphinx heute zu einem führenden Anbieter von Software für die freie Spracherkennung geworden ist. Pocketsphinx wird mit Ubuntu ausgeliefert , das vielversprechende Simon- Projekt ist weitgehend nutzbar, und die Voxforge-Paketstruktur weist darauf hin, dass es für Sphinxtrain erstellt wurde.

    Trotz der rasanten Entwicklung von Sphinx selbst und der Spracherkennungsmethoden im Allgemeinen weiß jeder, der versucht hat, es in der Praxis anzuwenden, wie schwierig es ist, selbst bei einfachen Aufgaben ein vernünftiges Ergebnis zu erzielen. Und das alles, weil Sie nicht nur die Standardmodelle anschließen können und erwarten, dass das System Sie versteht. Es ist notwendig, die Akustik anzupassen, ein relevantes Sprachmodell zu erstellen, die optimalen Parameter und die Konfiguration des Motors zu finden - im Allgemeinen müssen Sie Wochen Zeit aufwenden, um den Fehler akribisch prozentual zu reduzieren. Als eine Person, die genau diese Wochen verbracht hat, kann ich Ihnen versichern, dass in diesem Fall nichts garantiert ist. Dies gilt insbesondere dann, wenn Sie Sprache erkennen möchten, die nicht über das Headset, sondern über das eingebaute Mikrofon des Laptops aufgezeichnet wurde, wie dies häufig der Fall ist.

    Im Allgemeinen ist der Hauptgrund für eine schlechte Erkennung die Nichtübereinstimmung zwischen den Trainings- und Testbedingungen (ein bisschen ein Verfolgungsmuster mit nicht übereinstimmenden Bedingungen). Alles kann dort zugeschrieben werden: ungewohnte Ansager, nicht übereinstimmende Kanalmerkmale, unangemessenes Sprachmodell und sogar die Manifestation von Emotionen, die wir nicht vom Benutzer erwartet hatten. Bei einem Laptop-Mikrofon treten verschiedene additive Geräusche und Echos auf, die sich nicht in der Trainingsbasis befanden und die Erkennungsgenauigkeit erheblich verringern können.

    Hintergrund


    Die Umsetzung der Rauschunterdrückung in der CMU Sphinx begann genau vor einem Jahr mit diesem Beitrag von Nikolay Shmyrev (übrigens für alles eine tiefe Verbeugung): Rund um lärmresistente PNCC-Features . Zwei Monate später wurde eine Zusage gemacht , aber die erste Erwähnung in der FAQ erschien erst am 10. Juni 2014. Bis zu diesem Moment wurde vorgeschlagen, dass wir mit Lärm umgehen, indem wir uns an den Kanal anpassen (sehr praktische Ratschläge, die übrigens niemand stornierte). Für Experimente benötigen Sie daher für heute die neueste Version 0.8.

    Eine Beschreibung des Algorithmus selbst findet sich in einem grundlegenden Artikelund in der Post von Nicholas. Kurz gesagt, der Algorithmus ist dem MFCC sehr ähnlich, und die Modifikationen sind auf Studien im Bereich des menschlichen Gehörs zurückzuführen. Rauschunterdrückung in Spracherkennungssystemen ist ein sehr umfangreiches Gebiet, auf das ich nicht eingehen werde, weil ich nicht stöbere. Ich sage Ihnen nur, wie Sie es in die Praxis umsetzen können. Dieser Beitrag ist eine Verallgemeinerung der Informationen, die ich in Artikeln und Foren gefunden habe. Sie müssen sich mit der Sphinx vertraut machen. Ansonsten willkommen im Wiki .

    Lärmreduzierung in der Praxis


    Wenn es sich bei PNCCs lediglich um neue Features handelt, ist es logisch anzunehmen, dass sie verwendet werden können, indem der entsprechende Wert für angegeben wird -feat. Nein haha In diesem Fall ist die Implementierung eine Modifikation eines vorhandenen Merkmalsextraktionsmechanismus. Und bei pocketsphinx und Sphinx4 sieht es ein bisschen anders aus. Aber nehmen wir es in Ordnung.

    Akustische Modelle erstellen

    Bevor wir mit der Erkennung fortfahren können, benötigen wir akustische Modelle. Bestehende Modelle sind für uns nicht geeignet, da sie auf die übliche Weise erhalten wurden, was bedeutet, dass der Versuch, sie in einem geräuschresistenten System zu verwenden, zu einer sehr grundlegenden Fehlanpassung führt. Daher müssen die Modelle neu trainiert werden. Dazu benötigen Sie jeweils ein Gehäuse und installierte Sphinxbase und Sphinxtrain. Als Fall empfehle ich voxforge , das leicht modifiziert werden muss.

    Hier kommen wir zum Wichtigsten. Wie Sie wahrscheinlich wissen, wird sphinxtrain von der allgemeinen Konfiguration (sphinx_train.cfg) gesteuert, in der alle Parameter für das Training (und Testen) von Modellen festgelegt werden. Ab Version 0.8 haben einige Sphinx-Dienstprogramme zusätzliche Parameter erhalten, die für die Rauschunterdrückung verantwortlich sind. Nämlich -remove_noiseund -lifter. Für müssen -remove_noiseSie einen Wert festlegen yes(dies ist jedoch der Standardwert), und der übliche Wert des Parameters -lifterist 22. Wenn Sie ihn in der Hauptkonfiguration festlegen:
    $CFG_LIFTER = "22"; # Cepstrum lifter is smoothing to improve recognition
    

    dann können Sie es von dort lesen:
    -lifter __CFG_LIFTER__
    


    Ein weiterer wichtiger Parameter für uns ist dies -transform. Sein Standardwert legacy, aber wir brauchen dct. Um lärmresistente Modelle zu trainieren, müssen wir in feat.params drei Parameter festlegen:
    -transform dct
    -remove_noise yes
    -lifter 22
    


    Es ist jedoch besser, sie in die Datei sphinx_train.cfg zu übertragen, wie dies bei anderen Parametern der Fall ist:

    $CFG_TRANSFORM = "dct"; # Previously legacy transform is used, but dct is more accurate
    $CFG_LIFTER = "22"; # Cepstrum lifter is smoothing to improve recognition
    

    feat.params:
    -transform __CFG_TRANSFORM__
    -remove_noise yes
    -lifter __CFG_LIFTER__
    


    Sie müssen verstehen, dass sphinxtrain nur ein Script-Wrapper für einzelne Dienstprogramme wie z. B. ist. Wenn Sie sie also separat aufrufen, sollten Sie diese Parameter (falls vorhanden) immer festlegen.

    Hier ist ein Beispiel meiner Konfiguration für voxforge-en:

    sphinx_train.cfg:
    # Configuration script for sphinx trainer                  -*-mode:Perl-*-
    $CFG_VERBOSE = 1;		# Determines how much goes to the screen.
    # These are filled in at configuration time
    $CFG_DB_NAME = "voxforge_en";
    # Experiment name, will be used to name model files and log files
    $CFG_EXPTNAME = "$CFG_DB_NAME";
    # Directory containing SphinxTrain binaries
    $CFG_BASE_DIR = "/home/speechdat/voxforge-en";
    $CFG_SPHINXTRAIN_DIR = "/usr/local/lib/sphinxtrain";
    $CFG_BIN_DIR = "/usr/local/libexec/sphinxtrain";
    $CFG_SCRIPT_DIR = "/usr/local/lib/sphinxtrain/scripts";
    # Audio waveform and feature file information
    $CFG_WAVFILES_DIR = "$CFG_BASE_DIR/wav";
    $CFG_WAVFILE_EXTENSION = 'wav';
    $CFG_WAVFILE_TYPE = 'mswav'; # one of nist, mswav, raw
    $CFG_FEATFILES_DIR = "$CFG_BASE_DIR/feat";
    $CFG_FEATFILE_EXTENSION = 'mfc';
    $CFG_VECTOR_LENGTH = 13;
    # Feature extraction parameters
    $CFG_WAVFILE_SRATE = 16000.0;
    $CFG_NUM_FILT = 40; # For wideband speech it's 40, for telephone 8khz reasonable value is 31
    $CFG_LO_FILT = 133.33334; # For telephone 8kHz speech value is 200
    $CFG_HI_FILT = 6855.4976; # For telephone 8kHz speech value is 3500
    $CFG_TRANSFORM = "dct"; # Previously legacy transform is used, but dct is more accurate
    $CFG_LIFTER = "22"; # Cepstrum lifter is smoothing to improve recognition
    $CFG_MIN_ITERATIONS = 1;  # BW Iterate at least this many times
    $CFG_MAX_ITERATIONS = 10; # BW Don't iterate more than this, somethings likely wrong.
    # (none/max) Type of AGC to apply to input files
    $CFG_AGC = 'none';
    # (current/none) Type of cepstral mean subtraction/normalization
    # to apply to input files
    $CFG_CMN = 'current';
    $CFG_CMNINIT = 10.0;
    # (yes/no) Normalize variance of input files to 1.0
    $CFG_VARNORM = 'no';
    # (yes/no) Train full covariance matrices
    $CFG_FULLVAR = 'no';
    # (yes/no) Use diagonals only of full covariance matrices for
    # Forward-Backward evaluation (recommended if CFG_FULLVAR is yes)
    $CFG_DIAGFULL = 'no';
    # (yes/no) Perform vocal tract length normalization in training.  This
    # will result in a "normalized" model which requires VTLN to be done
    # during decoding as well.
    $CFG_VTLN = 'no';
    # Starting warp factor for VTLN
    $CFG_VTLN_START = 0.80;
    # Ending warp factor for VTLN
    $CFG_VTLN_END = 1.40;
    # Step size of warping factors
    $CFG_VTLN_STEP = 0.05;
    # Directory to write queue manager logs to
    $CFG_QMGR_DIR = "$CFG_BASE_DIR/qmanager";
    # Directory to write training logs to
    $CFG_LOG_DIR = "$CFG_BASE_DIR/logdir";
    # Directory for re-estimation counts
    $CFG_BWACCUM_DIR = "$CFG_BASE_DIR/bwaccumdir";
    # Directory to write model parameter files to
    $CFG_MODEL_DIR = "$CFG_BASE_DIR/model_parameters";
    # Directory containing transcripts and control files for
    # speaker-adaptive training
    $CFG_LIST_DIR = "$CFG_BASE_DIR/etc";
    # Decoding variables for MMIE training
    $CFG_LANGUAGEWEIGHT = "11.5";
    $CFG_BEAMWIDTH      = "1e-100";
    $CFG_WORDBEAM       = "1e-80";
    $CFG_LANGUAGEMODEL  = "$CFG_LIST_DIR/${CFG_DB_NAME}_full.lm.DMP";
    $CFG_WORDPENALTY    = "0.2";
    # Lattice pruning variables
    $CFG_ABEAM              = "1e-50";
    $CFG_NBEAM              = "1e-10";
    $CFG_PRUNED_DENLAT_DIR  = "$CFG_BASE_DIR/pruned_denlat";
    # MMIE training related variables
    $CFG_MMIE = "no";
    $CFG_MMIE_MAX_ITERATIONS = 5;
    $CFG_LATTICE_DIR = "$CFG_BASE_DIR/lattice";
    $CFG_MMIE_TYPE   = "best"; # Valid values are "rand", "best" or "ci"
    $CFG_MMIE_CONSTE = "3.0";
    $CFG_NUMLAT_DIR  = "$CFG_BASE_DIR/numlat";
    $CFG_DENLAT_DIR  = "$CFG_BASE_DIR/denlat";
    # Variables used in main training of models
    $CFG_DICTIONARY     = "$CFG_LIST_DIR/$CFG_DB_NAME.dict";
    $CFG_RAWPHONEFILE   = "$CFG_LIST_DIR/$CFG_DB_NAME.phone";
    $CFG_FILLERDICT     = "$CFG_LIST_DIR/$CFG_DB_NAME.filler";
    $CFG_LISTOFFILES    = "$CFG_LIST_DIR/${CFG_DB_NAME}_full.fileids";
    $CFG_TRANSCRIPTFILE = "$CFG_LIST_DIR/${CFG_DB_NAME}_full.transcription";
    $CFG_FEATPARAMS     = "$CFG_LIST_DIR/feat.params";
    # Variables used in characterizing models
    $CFG_HMM_TYPE = '.cont.'; # Sphinx 4, PocketSphinx
    #$CFG_HMM_TYPE  = '.semi.'; # PocketSphinx
    #$CFG_HMM_TYPE  = '.ptm.'; # PocketSphinx (larger data sets)
    if (($CFG_HMM_TYPE ne ".semi.")
        and ($CFG_HMM_TYPE ne ".ptm.")
        and ($CFG_HMM_TYPE ne ".cont.")) {
      die "Please choose one CFG_HMM_TYPE out of '.cont.', '.ptm.', or '.semi.', " .
        "currently $CFG_HMM_TYPE\n";
    }
    # This configuration is fastest and best for most acoustic models in
    # PocketSphinx and Sphinx-III.  See below for Sphinx-II.
    $CFG_STATESPERHMM = 3;
    $CFG_SKIPSTATE = 'no';
    if ($CFG_HMM_TYPE eq '.semi.') {
      $CFG_DIRLABEL = 'semi';
    # Four stream features for PocketSphinx
      $CFG_FEATURE = "s2_4x";
      $CFG_NUM_STREAMS = 4;
      $CFG_INITIAL_NUM_DENSITIES = 256;
      $CFG_FINAL_NUM_DENSITIES = 256;
      die "For semi continuous models, the initial and final models have the same density" 
        if ($CFG_INITIAL_NUM_DENSITIES != $CFG_FINAL_NUM_DENSITIES);
    } elsif ($CFG_HMM_TYPE eq '.ptm.') {
      $CFG_DIRLABEL = 'ptm';
    # Four stream features for PocketSphinx
      $CFG_FEATURE = "s2_4x";
      $CFG_NUM_STREAMS = 4;
      $CFG_INITIAL_NUM_DENSITIES = 64;
      $CFG_FINAL_NUM_DENSITIES = 64;
      die "For phonetically tied models, the initial and final models have the same density" 
        if ($CFG_INITIAL_NUM_DENSITIES != $CFG_FINAL_NUM_DENSITIES);
    } elsif ($CFG_HMM_TYPE eq '.cont.') {
      $CFG_DIRLABEL = 'cont';
    # Single stream features - Sphinx 3
      $CFG_FEATURE = "1s_c_d_dd";
      $CFG_NUM_STREAMS = 1;
      $CFG_INITIAL_NUM_DENSITIES = 1;
      $CFG_FINAL_NUM_DENSITIES = 32;
      die "The initial has to be less than the final number of densities" 
        if ($CFG_INITIAL_NUM_DENSITIES > $CFG_FINAL_NUM_DENSITIES);
    }
    # Number of top gaussians to score a frame. A little bit less accurate computations
    # make training significantly faster. Uncomment to apply this during the training
    # For good accuracy make sure you are using the same setting in decoder
    # In theory this can be different for various training stages. For example 4 for
    # CI stage and 16 for CD stage
    # $CFG_CI_TOPN = 4;
    # $CFG_CD_TOPN = 16;
    # (yes/no) Train multiple-gaussian context-independent models (useful
    # for alignment, use 'no' otherwise) in the models created
    # specifically for forced alignment
    $CFG_FALIGN_CI_MGAU = 'no';
    # (yes/no) Train multiple-gaussian context-independent models (useful
    # for alignment, use 'no' otherwise)
    $CFG_CI_MGAU = 'no';
    # Number of tied states (senones) to create in decision-tree clustering
    $CFG_N_TIED_STATES = 3000;
    # How many parts to run Forward-Backward estimatinon in
    $CFG_NPART = 1;
    # (yes/no) Train a single decision tree for all phones (actually one
    # per state) (useful for grapheme-based models, use 'no' otherwise)
    $CFG_CROSS_PHONE_TREES = 'no';
    # Use force-aligned transcripts (if available) as input to training
    $CFG_FORCEDALIGN = 'no';
    # Use a specific set of models for force alignment.  If not defined,
    # context-independent models for the current experiment will be used.
    $CFG_FORCE_ALIGN_MDEF = "$CFG_BASE_DIR/model_architecture/$CFG_EXPTNAME.falign_ci.mdef";
    $CFG_FORCE_ALIGN_MODELDIR = "$CFG_MODEL_DIR/$CFG_EXPTNAME.falign_ci_$CFG_DIRLABEL";
    # Use a specific dictionary and filler dictionary for force alignment.
    # If these are not defined, a dictionary and filler dictionary will be
    # created from $CFG_DICTIONARY and $CFG_FILLERDICT, with noise words
    # removed from the filler dictionary and added to the dictionary (this
    # is because the force alignment is not very good at inserting them)
    # $CFG_FORCE_ALIGN_DICTIONARY = "$ST::CFG_BASE_DIR/falignout$ST::CFG_EXPTNAME.falign.dict";;
    # $CFG_FORCE_ALIGN_FILLERDICT = "$ST::CFG_BASE_DIR/falignout/$ST::CFG_EXPTNAME.falign.fdict";;
    # Use a particular beam width for force alignment.  The wider
    # (i.e. smaller numerically) the beam, the fewer sentences will be
    # rejected for bad alignment.
    $CFG_FORCE_ALIGN_BEAM = 1e-60;
    # Calculate an LDA/MLLT transform?
    $CFG_LDA_MLLT = 'yes';
    # Dimensionality of LDA/MLLT output
    $CFG_LDA_DIMENSION = 29;
    # This is actually just a difference in log space (it doesn't make
    # sense otherwise, because different feature parameters have very
    # different likelihoods)
    $CFG_CONVERGENCE_RATIO = 0.1;
    # Queue::POSIX for multiple CPUs on a local machine
    # Queue::PBS to use a PBS/TORQUE queue
    $CFG_QUEUE_TYPE = "Queue::POSIX";
    # Name of queue to use for PBS/TORQUE
    $CFG_QUEUE_NAME = "workq";
    # (yes/no) Build questions for decision tree clustering automatically
    $CFG_MAKE_QUESTS = "yes";
    # If CFG_MAKE_QUESTS is yes, questions are written to this file.
    # If CFG_MAKE_QUESTS is no, questions are read from this file.
    $CFG_QUESTION_SET = "${CFG_BASE_DIR}/model_architecture/${CFG_EXPTNAME}.tree_questions";
    #$CFG_QUESTION_SET = "${CFG_BASE_DIR}/linguistic_questions";
    $CFG_CP_OPERATION = "${CFG_BASE_DIR}/model_architecture/${CFG_EXPTNAME}.cpmeanvar";
    # This variable has to be defined, otherwise utils.pl will not load.
    $CFG_DONE = 1;
    return 1;
    



    feat.params:
    -alpha 0.97
    -dither yes
    -doublebw no
    -nfilt __CFG_NUM_FILT__
    -ncep __CFG_VECTOR_LENGTH__
    -lowerf __CFG_LO_FILT__
    -upperf __CFG_HI_FILT__
    -samprate __CFG_WAVFILE_SRATE__
    -nfft 512
    -wlen 0.0256
    -transform __CFG_TRANSFORM__
    -feat __CFG_FEATURE__
    -agc __CFG_AGC__
    -cmn __CFG_CMN__
    -varnorm __CFG_VARNORM__
    -remove_noise yes
    -lifter __CFG_LIFTER__
    



    Natürlich ist das Training von Akustikmodellen diese Art von Hämorrhoiden . Zusätzlich zu spezifischem Wissen erfordert es die Installation von Sphinxbase und Sphinxtrain und dauert ungefähr einen Tag. Daher teilte ich meine Modelle, die auf voxforge-en nach dem obigen Rezept trainiert wurden: dropbox .

    Akustische Modelle verwenden

    Mit Modellen können wir endlich frei atmen und sie mit unserem System verbinden. Hier variieren die Rezepte je nachdem, ob Sie Pocketsphinx oder Sphinx4 verwenden. Mit pocket einfach: Sie müssen nur die Parameter des Trios setzen -transform, -remove_noiseund -lifter. Und wenn wir Sphinx4 verwenden möchten, müssen wir die Denoise- Komponente in das Frontend aufnehmen und das Frontend selbst leicht ändern. Die entsprechende Pipeline sieht ungefähr so ​​aus:

    1. AudioFileDataSource
    2. Dithering
    3. Preemphasizer
    4. RaisedCosineWindower
    5. DiscreteFourierTransform
    6. MelFrequencyFilterBank
    7. Denoise
    8. DiscreteCosineTransform2
    9. Heber
    10. Batchcmn
    11. DeltasFeatureExtractor
    12. FeatureTransform

    NB: featureTransform wird nur benötigt, wenn Sie im Modelltraining LDA / MLLT verwendet haben.

    Drei fett gedruckte Komponenten zeigen die Rauschunterdrückung an.

    In XML sieht der entsprechende Teil der Konfiguration folgendermaßen aus:

    config.xml
    audioFileDataSourceditherpreemphasizerwindowerfftmelFilterBankdenoisedctlifterbatchCMNfeatureExtractionfeatureTransform



    Funktioniert es


    Ganz. Für meine Aufgabe erhielt ich eine Erhöhung der Erkennungsgenauigkeit um 6,5%: von 74,65% auf 81,38%. Trotzdem lohnt sich die Anpassung an den Kanal. Und seien Sie vorsichtig, wenn Sie diesen Mechanismus anwenden: Bei reinem Audio kann dies das Ergebnis verschlechtern.

    Jetzt auch beliebt: