[SRILM User List] dynamic Loglinear mix for lattice rescoring

Andreas Stolcke stolcke at speech.sri.com
Fri Jan 28 22:38:24 PST 2011



> 
> Hi all,
> 
> Is there a way to rescore htk lattices using dynamic log-linear
> interpolation of more than one language models, using SRILM.
> 
> Ideally, the command should look like
> 
> lattice-tool -read-htk  -in-lattice $SRC_LATTICE     -lm $LM_FILE   -order
> $LM_ORDER  -bayes 0 -lambda $LAMBDA -mix-lm $LM2_FILE -loglinear-mix
> -write-htk -out-lattice $TMP_TRG_LATTIC    -unk -map-unk $UNK_WORD
> -keep-unk
> 
> but there is no loglinear-mix option in lattice-tool, like in ngram.
> 
> Thanks in advance,

The patch below will add the -loglinear-mix option to lattice-tool.

Andreas 

Index: lattice/src/lattice-tool.cc
===================================================================
RCS file: /home/srilm/CVS/srilm/lattice/src/lattice-tool.cc,v
retrieving revision 1.154
retrieving revision 1.155
diff -c -r1.154 -r1.155
*** lattice/src/lattice-tool.cc	14 Jan 2011 01:07:54 -0000	1.154
--- lattice/src/lattice-tool.cc	29 Jan 2011 05:56:35 -0000	1.155
***************
*** 5,11 ****
  
  #ifndef lint
  static char Copyright[] = "Copyright (c) 1997-2011 SRI International.  All Rights Reserved.";
! static char RcsId[] = "@(#)$Id: lattice-tool.cc,v 1.154 2011/01/14 01:07:54 stolcke Exp $";
  #endif
  
  #ifdef PRE_ISO_CXX
--- 5,11 ----
  
  #ifndef lint
  static char Copyright[] = "Copyright (c) 1997-2011 SRI International.  All Rights Reserved.";
! static char RcsId[] = "@(#)$Id: lattice-tool.cc,v 1.155 2011/01/29 05:56:35 stolcke Exp $";
  #endif
  
  #ifdef PRE_ISO_CXX
***************
*** 43,48 ****
--- 43,49 ----
  #include "SimpleClassNgram.h"
  #include "ProductNgram.h"
  #include "BayesMix.h"
+ #include "LoglinearMix.h"
  #include "RefList.h"
  #include "LatticeLM.h"
  #include "WordMesh.h"
***************
*** 138,143 ****
--- 139,145 ----
  static double mixLambda7 = 0.0;
  static double mixLambda8 = 0.0;
  static double mixLambda9 = 0.0;
+ static int loglinearMix = 0;
  static char *inLattice = 0; 
  static char *inLattice2 = 0; 
  static char *inLatticeList = 0; 
***************
*** 231,236 ****
--- 233,239 ----
      { OPT_FLOAT, "mix-lambda8", &mixLambda8, "mixture weight for -mix-lm8" },
      { OPT_STRING, "mix-lm9", &mixFile9, "ninth LM to mix in" },
      { OPT_FLOAT, "mix-lambda9", &mixLambda9, "mixture weight for -mix-lm9" },
+     { OPT_TRUE, "loglinear-mix", &loglinearMix, "use log-linear mixture LM" },
      { OPT_INT, "order", &order, "ngram order used for expansion or bigram weight substitution" },
      { OPT_TRUE, "no-expansion", &noExpansion, "do not apply expansion with LM" },
      { OPT_STRING, "ref-list", &refList, "reference file used for computing WER (lines starting with utterance id)" }, 
***************
*** 1090,1095 ****
--- 1093,1144 ----
      }
  }
  
+ LM *
+ makeLoglinearMixLM(Array<const char *> filenames, Vocab &vocab,
+ 		   SubVocab *classVocab, unsigned order,
+ 		   LM *oldLM, Array<double> lambdas)
+ {
+     Array<LM *> allLMs;
+     allLMs[0] = oldLM;
+ 
+     for (unsigned i = 1; i < filenames.size(); i++) {
+ 	const char *filename = filenames[i];
+ 	File file(filename, "r");
+ 
+ 	/*
+ 	 * create factored LM if -factored was specified, 
+ 	 * class-ngram if -classes were specified,
+ 	 * and otherwise a regular ngram
+ 	 */
+ 	Ngram *lm = factored ?
+ 		      new ProductNgram((ProductVocab &)vocab, order) :
+ 		      (classVocab != 0) ?
+ 			(simpleClasses ?
+ 			    new SimpleClassNgram(vocab, *classVocab, order) :
+ 			    new ClassNgram(vocab, *classVocab, order)) :
+ 			new Ngram(vocab, order);
+ 	assert(lm != 0);
+ 
+ 	if (!lm->read(file, limitVocab)) {
+ 	    cerr << "format error in mix-lm file " << filename << endl;
+ 	    exit(1);
+ 	}
+ 
+ 	/*
+ 	 * Each class LM needs to read the class definitions
+ 	 */
+ 	if (classesFile != 0) {
+ 	    File file(classesFile, "r");
+ 	    ((ClassNgram *)lm)->readClasses(file);
+ 	}
+ 	allLMs[i] = lm;
+     }
+ 
+     LM *newLM = new LoglinearMix(vocab, allLMs, lambdas);
+     assert(newLM != 0);
+ 
+     return newLM;
+ }
  int 
  main (int argc, char *argv[])
  {
***************
*** 1310,1316 ****
  	useLM = ngram;
      }
  
!     if (mixFile) {
  	/*
  	 * create a Bayes mixture LM 
  	 */
--- 1359,1365 ----
  	useLM = ngram;
      }
  
!     if (mixFile && !loglinearMix) {
  	/*
  	 * create a Bayes mixture LM 
  	 */
***************
*** 1370,1375 ****
--- 1419,1476 ----
  	    useLM = makeMixLM(mixFile9, *vocab, classVocab, order, useLM,
  				mixLambda9, 1.0);
  	}
+     } else if (mixFile && loglinearMix) {
+ 	/*
+ 	 * Create log-linear mixture LM
+ 	 */
+ 	double mixLambda1 = 1.0 - mixLambda - mixLambda2 - mixLambda3
+ 			    - mixLambda4 - mixLambda5 - mixLambda6 - mixLambda7
+ 			    - mixLambda8 - mixLambda9;
+ 
+ 	Array<const char *> filenames;
+ 	Array<double> lambdas;
+ 
+ 	/* Add redundant filename entry for base LM to make filenames array 
+ 	 * symmetric with lambdas */
+ 	filenames[0] = "";
+ 	filenames[1] = mixFile;
+ 	lambdas[0] = mixLambda;
+ 	lambdas[1] = mixLambda1;
+ 
+ 	if (mixFile2) {
+ 	    filenames[2] = mixFile2;
+ 	    lambdas[2] = mixLambda2;
+ 	}
+ 	if (mixFile3) {
+ 	    filenames[3] = mixFile3;
+ 	    lambdas[3] = mixLambda3;
+ 	}
+ 	if (mixFile4) {
+ 	    filenames[4] = mixFile4;
+ 	    lambdas[4] = mixLambda4;
+ 	}
+ 	if (mixFile5) {
+ 	    filenames[5] = mixFile5;
+ 	    lambdas[5] = mixLambda5;
+ 	}
+ 	if (mixFile6) {
+ 	    filenames[6] = mixFile6;
+ 	    lambdas[6] = mixLambda6;
+ 	}
+ 	if (mixFile7) {
+ 	    filenames[7] = mixFile7;
+ 	    lambdas[7] = mixLambda7;
+ 	}
+ 	if (mixFile8) {
+ 	    filenames[8] = mixFile8;
+ 	    lambdas[8] = mixLambda8;
+ 	}
+ 	if (mixFile9) {
+ 	    filenames[9] = mixFile9;
+ 	    lambdas[9] = mixLambda9;
+ 	}
+ 	useLM = makeLoglinearMixLM(filenames, *vocab, classVocab, order,
+ 					useLM, lambdas);
      }
  
      /*


More information about the SRILM-User mailing list