2
## ====================================================================
4
## Copyright (c) 1996-2000 Carnegie Mellon University. All rights
7
## Redistribution and use in source and binary forms, with or without
8
## modification, are permitted provided that the following conditions
11
## 1. Redistributions of source code must retain the above copyright
12
## notice, this list of conditions and the following disclaimer.
14
## 2. Redistributions in binary form must reproduce the above copyright
15
## notice, this list of conditions and the following disclaimer in
16
## the documentation and/or other materials provided with the
19
## This work was supported in part by funding from the Defense Advanced
20
## Research Projects Agency and the National Science Foundation of the
21
## United States of America, and the CMU Sphinx Speech Consortium.
23
## THIS SOFTWARE IS PROVIDED BY CARNEGIE MELLON UNIVERSITY ``AS IS'' AND
24
## ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
25
## THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26
## PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY
27
## NOR ITS EMPLOYEES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35
## ====================================================================
37
## Author: Ricky Houghton
38
## Author: David Huggins-Daines
44
use File::Spec::Functions;
47
use lib catdir(dirname($0), updir(), 'lib');
48
use SphinxTrain::Config;
49
use SphinxTrain::Util;
51
#***************************************************************************
52
# This script launches all the ci - continuous training jobs in the proper
53
# order. First it cleans up the directories, then launches the
54
# flat initialization, and the baum-welch and norm jobs for the required
55
# number of iterations. Within each iteration it launches as many baumwelch
56
# jobs as the number of parts we wish to split the training into.
57
#***************************************************************************
59
my ($iter, $n_parts, $n_gau) = @ARGV;
60
$iter = 1 unless defined $iter;
61
$n_parts = (defined($ST::CFG_NPART) ? $ST::CFG_NPART : 1) unless defined $n_parts;
62
$n_gau = $ST::CFG_INITIAL_NUM_DENSITIES unless defined $n_gau;
64
my $modeldir = "$ST::CFG_BASE_DIR/model_parameters";
65
mkdir ($modeldir,0777);
67
$| = 1; # Turn on autoflushing
68
my $logdir = "$ST::CFG_LOG_DIR/20.ci_hmm";
71
use vars qw($MLLT_FILE);
72
$MLLT_FILE = catfile($ST::CFG_MODEL_DIR, "${ST::CFG_EXPTNAME}.mllt");
74
# We have to clean up and run flat initialize if it is the first iteration
75
if ($iter == 1 and $n_gau == $ST::CFG_INITIAL_NUM_DENSITIES) {
76
Log("MODULE: 20 Training Context Independent models\n");
77
Log("Phase 1: Cleaning up directories:");
78
# Don't do this on a queue, because of NFS bugs
79
unless ($ST::CFG_QUEUE_TYPE eq 'Queue::PBS') {
80
LogProgress("\taccumulator...");
81
rmtree ($ST::CFG_BWACCUM_DIR, 0, 1);
82
mkdir ($ST::CFG_BWACCUM_DIR,0777);
84
LogProgress("logs...");
85
rmtree($logdir, 0, 1);
87
LogProgress("qmanager...");
88
rmtree ($ST::CFG_QMGR_DIR, 0, 1);
89
mkdir ($ST::CFG_QMGR_DIR,0777);
90
LogProgress("models...\n");
91
rmtree("$modeldir/${ST::CFG_EXPTNAME}.ci_$ST::CFG_DIRLABEL", 0, 1);
92
LogStatus('completed');
94
# If we previously force aligned with single-Gaussian models, use
95
# them for initialization to save some time.
96
if (($ST::CFG_FORCEDALIGN eq 'yes' or $ST::CFG_VTLN eq 'yes')
97
and $ST::CFG_FALIGN_CI_MGAU ne 'yes'
98
and -e catfile($ST::CFG_FORCE_ALIGN_MODELDIR, 'means')) {
99
$return_value = CopyInitialize();
100
exit ($return_value) if ($return_value);
103
# For the first iteration Flat initialize models.
104
$return_value = FlatInitialize();
105
exit ($return_value) if ($return_value);
107
Log("Phase 3: Forward-Backward");
110
if (defined($ST::CFG_PHSEG_DIR) and ! -d $ST::CFG_PHSEG_DIR) {
111
# Build phone segmentation dirs
112
open INPUT,"${ST::CFG_LISTOFFILES}" or die "Failed to open $ST::CFG_LISTOFFILES: $!";
117
my $uttid = pop @fields;
118
my $basedir = dirname($uttid);
119
next if $basedir eq ".";
120
unless ($dirs{$basedir}) {
122
mkpath(catdir($ST::CFG_PHSEG_DIR, $basedir), 0, 0777);
129
# Call baum_welch with iter part and n_parts,
130
# once done call norm_and_lauchbw.pl
132
for (my $i=1; $i<=$n_parts; $i++)
134
push @deps, LaunchScript("bw.$iter.$i", ['baum_welch.pl', $iter, $i, $n_parts, $n_gau])
136
LaunchScript("norm.$iter", ['norm_and_launchbw.pl', $iter, $n_parts, $n_gau], \@deps);
137
# For the first iteration (i.e. the one that was called from the
138
# command line or a parent script), wait until completion or error
139
if ($iter == 1 && $n_gau == $ST::CFG_INITIAL_NUM_DENSITIES) {
140
if ($ST::CFG_CI_MGAU eq 'yes') {
141
$return_value = TiedWaitForConvergence($logdir);
144
$return_value = WaitForConvergence($logdir);
150
Log("Phase 2: Copy initialize from falign model\n");
151
my $hmmdir = catdir($ST::CFG_BASE_DIR, "model_parameters");
152
my $outhmm = catdir($hmmdir, "${ST::CFG_EXPTNAME}.ci_${ST::CFG_DIRLABEL}_flatinitial");
153
my $modarchdir = catdir($ST::CFG_BASE_DIR, "model_architecture");
154
mkdir ($outhmm,0777);
155
foreach (qw(means variances mixture_weights transition_matrices)) {
156
copy(catfile($ST::CFG_FORCE_ALIGN_MODELDIR, $_), catfile($outhmm, $_))
159
my $ci_mdeffile = catfile($modarchdir, "$ST::CFG_EXPTNAME.falign_ci.mdef");
160
my $out_mdeffile = catfile($modarchdir, "$ST::CFG_EXPTNAME.ci.mdef");
161
copy($ci_mdeffile, $out_mdeffile);
167
Log("Phase 2: Flat initialize\n");
169
#**************************************************************************
170
# this script given an mdef file and a codebook (means/vars in S3 format)
171
# produces flat mixture weights in a semicontinuos setting. From the models
172
# produced by this script we can restart normal baum-welch training
173
# Flat init might not be the best choice, specially if we have access to
174
# segmentation files for the whole training database.
175
#**************************************************************************
177
my $logdir = "$ST::CFG_LOG_DIR/20.ci_hmm";
178
my $modarchdir = "$ST::CFG_BASE_DIR/model_architecture";
179
my $hmmdir = "$ST::CFG_BASE_DIR/model_parameters";
180
mkdir ($logdir,0777);
181
mkdir ($modarchdir,0777);
182
mkdir ($hmmdir,0777);
185
#-------------------------------------------------------------------------
186
# Take the phone list. Put three hyphens after every phone. That is the
187
# required format. Then make a ci model definition file from it using the
189
#-------------------------------------------------------------------------
191
#$rawphonefile obtained from variables.def
192
my $phonefile = "$modarchdir/$ST::CFG_EXPTNAME.phonelist";
193
my $ci_mdeffile = "$modarchdir/$ST::CFG_EXPTNAME.ci.mdef";
195
open PHONELIST, "<".$ST::CFG_RAWPHONEFILE;
196
open PHONEFILE, ">".$phonefile;
199
while (defined(my $line = <PHONELIST>)) {
201
next if $line =~ m/^\s*$/;
202
$line =~ s/$/ - - - /;
203
push @phonelist, $line;
207
# Make sure the CI phones are sorted, as PocketSphinx requires them to be
208
foreach (sort @phonelist) {
209
print PHONEFILE $_, "\n";
211
# system "sed 's+\$+ - - - +g' $ST::CFG_RAWPHONEFILE > $phonefile";
214
my $logfile = "$logdir/${ST::CFG_EXPTNAME}.make_ci_mdef_fromphonelist.log";
215
#-------------------------------------------------------------------------
216
# Decide on what topology to use for the hmms: 3 state, 5 state, blah state
217
# or what, give it to the variable "statesperhmm" and use it to create
218
# the topology matrix in the topology file
219
#-------------------------------------------------------------------------
221
#$statesperhmm obtained from variables.def
222
my $topologyfile = "$modarchdir/$ST::CFG_EXPTNAME.topology";
223
RunScript("../prepare/maketopology.pl", $topologyfile);
225
if ($return_value = RunTool('mk_mdef_gen', $logfile, 0,
226
-phnlstfn => $phonefile,
227
-ocimdef => $ci_mdeffile,
228
-n_state_pm => $ST::CFG_STATESPERHMM)) {
229
return $return_value;
232
#-------------------------------------------------------------------------
233
# make the flat models using the above topology file and the mdef file
234
#------------------------------------------------------------------------
235
my $outhmm = "$hmmdir/${ST::CFG_EXPTNAME}.ci_${ST::CFG_DIRLABEL}_flatinitial";
236
mkdir ($outhmm,0777);
238
my $FLAT = "$ST::CFG_BIN_DIR/mk_flat";
240
$logfile = "$logdir/${ST::CFG_EXPTNAME}.makeflat_cihmm.log";
241
if ($return_value = RunTool('mk_flat', $logfile, 0,
242
-moddeffn => $ci_mdeffile,
243
-topo => $topologyfile,
244
-mixwfn => catfile($outhmm, 'mixture_weights'),
245
-tmatfn => catfile($outhmm, 'transition_matrices'),
246
-nstream => $ST::CFG_NUM_STREAMS,
247
-ndensity => $ST::CFG_INITIAL_NUM_DENSITIES,
249
return $return_value;
252
# For semi-continuous, PTM, or generalized tied mixtures,
253
# duplicate the codebook in-place to produce the initial model
254
# (this does nothing for SC but is necessary for the others)
255
if ($ST::CFG_HMM_TYPE ne ".cont.") {
256
$logfile = "$logdir/${ST::CFG_EXPTNAME}.duplicate_codebook.log";
257
if ($return_value = RunTool('init_mixw', $logfile, 0,
258
# Flat K-means init always gives us one codebook
259
-src_ts2cbfn => '.semi.',
260
# There might be multiple codebooks here though
261
-dest_ts2cbfn => $ST::CFG_HMM_TYPE,
262
-fullvar => $ST::CFG_FULLVAR,
263
-src_moddeffn => $ci_mdeffile,
264
-dest_moddeffn => $ci_mdeffile,
265
-src_mixwfn => catfile($outhmm, 'mixture_weights'),
266
-dest_mixwfn => catfile($outhmm, 'mixture_weights'),
267
-src_tmatfn => catfile($outhmm, 'transition_matrices'),
268
-dest_tmatfn => catfile($outhmm, 'transition_matrices'),
269
-src_meanfn=> catfile($outhmm, 'means'),
270
-dest_meanfn => catfile($outhmm, 'means'),
271
-src_varfn=> catfile($outhmm, 'variances'),
272
-dest_varfn => catfile($outhmm, 'variances'),
274
return $return_value;
279
#-------------------------------------------------------------------------
280
# Accumulate the means from the training data
281
#------------------------------------------------------------------------
283
$logfile = "$logdir/${ST::CFG_EXPTNAME}.initmean_cihmm.log";
285
open LOG,">$logfile";
287
my $output_buffer_dir = "$ST::CFG_BWACCUM_DIR/${ST::CFG_EXPTNAME}_buff_1";
288
mkdir ($output_buffer_dir,0777);
290
# if there is an MLLT transformation, use it
292
if (defined($ST::CFG_SVSPEC)) {
293
push(@feat_args, -svspec =>$ST::CFG_SVSPEC);
298
-ldadim => $ST::CFG_LDA_DIMENSION);
300
if ($return_value = RunTool('init_gau', $logfile, 0,
301
-ctlfn => $ST::CFG_LISTOFFILES,
302
-part => 1, -npart => 1,
303
-cepdir => $ST::CFG_FEATFILES_DIR,
304
-cepext => $ST::CFG_FEATFILE_EXTENSION,
305
-accumdir => $output_buffer_dir,
306
-agc => $ST::CFG_AGC,
307
-cmn => $ST::CFG_CMN,
308
-varnorm => $ST::CFG_VARNORM,
309
-feat => $ST::CFG_FEATURE,
310
-ceplen => $ST::CFG_VECTOR_LENGTH,
313
return $return_value;
316
#-------------------------------------------------------------------------
317
# Normalize the means
318
#------------------------------------------------------------------------
320
$logfile = "$logdir/${ST::CFG_EXPTNAME}.normmean_cihmm.log";
322
if ($return_value = RunTool('norm', $logfile, 0,
323
-accumdir => $output_buffer_dir,
324
-meanfn => catfile($outhmm, "globalmean"),
326
return $return_value;
329
#-------------------------------------------------------------------------
330
# Accumulate the variances from the training data
331
#------------------------------------------------------------------------
333
$logfile = "$logdir/${ST::CFG_EXPTNAME}.initvar_cihmm.log";
335
if ($return_value = RunTool('init_gau', $logfile, 0,
336
-meanfn => catfile($outhmm, "globalmean"),
337
-ctlfn => $ST::CFG_LISTOFFILES,
338
-part => 1, -npart => 1,
339
-cepdir => $ST::CFG_FEATFILES_DIR,
340
-cepext => $ST::CFG_FEATFILE_EXTENSION,
341
-accumdir => $output_buffer_dir,
342
-agc => $ST::CFG_AGC,
343
-cmn => $ST::CFG_CMN,
344
-varnorm => $ST::CFG_VARNORM,
345
-feat => $ST::CFG_FEATURE,
346
-ceplen => $ST::CFG_VECTOR_LENGTH,
347
-fullvar => $ST::CFG_FULLVAR,
350
return $return_value;
353
#-------------------------------------------------------------------------
354
# Normalize the variances
355
#------------------------------------------------------------------------
357
$logfile = "$logdir/${ST::CFG_EXPTNAME}.normvar_cihmm.log";
359
if ($return_value = RunTool('norm', $logfile, 0,
360
-accumdir => $output_buffer_dir,
361
-fullvar => $ST::CFG_FULLVAR,
362
-varfn => catfile($outhmm, "globalvar"),
364
return $return_value;
368
#-------------------------------------------------------------------------
369
# Create the copy operation file, simply a map between states
370
#------------------------------------------------------------------------
372
my $NUM_CI_STATES = $NUM_PHONES * $ST::CFG_STATESPERHMM;
373
if (open CPFILE, ">$ST::CFG_CP_OPERATION") {
374
for (my $CI_STATE = 0; $CI_STATE < $NUM_CI_STATES; $CI_STATE++) {
375
print CPFILE "$CI_STATE\t0\n";
379
warn "Can't open $ST::CFG_CP_OPERATION\n";
382
#-------------------------------------------------------------------------
383
# Copy the means to all other states
384
#------------------------------------------------------------------------
386
$logfile = "$logdir/${ST::CFG_EXPTNAME}.cpmean_cihmm.log";
388
if ($return_value = RunTool('cp_parm', $logfile, 0,
389
-cpopsfn => $ST::CFG_CP_OPERATION,
390
-igaufn => catfile($outhmm, 'globalmean'),
391
-ncbout => $NUM_CI_STATES,
392
-ogaufn => catfile($outhmm, 'means')
394
return $return_value;
397
#-------------------------------------------------------------------------
398
# Copy the variances to all other states
399
#------------------------------------------------------------------------
401
$logfile = "$logdir/${ST::CFG_EXPTNAME}.cpvar_cihmm.log";
404
if ($ST::CFG_FULLVAR eq 'yes') {
405
@varcpy = (-ifullgaufn => catfile($outhmm, 'globalvar'),
406
-ofullgaufn => catfile($outhmm, 'variances'));
409
@varcpy = (-igaufn => catfile($outhmm, 'globalvar'),
410
-ogaufn => catfile($outhmm, 'variances'));
412
if ($return_value = RunTool('cp_parm', $logfile, 0,
413
-cpopsfn => $ST::CFG_CP_OPERATION,
414
-ncbout => $NUM_CI_STATES,
417
return $return_value;
420
unlink $ST::CFG_CP_OPERATION;
422
return $return_value;