forked from aalto-speech/AaltoASR
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathoptimize.cc
270 lines (228 loc) · 10.3 KB
/
optimize.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
#include "Distributions.hh"
#include "conf.hh"
#include "LinearAlgebra.hh"
#include "HmmSet.hh"
#include "str.hh"
std::string stat_file;
conf::Config config;
HmmSet model;
int
main(int argc, char *argv[])
{
PDF::EstimationMode mode;
try {
config("usage: optimize [OPTION...]\n")
('h', "help", "", "", "display help")
('b', "base=BASENAME", "arg", "", "Previous base filename for model files")
('g', "gk=FILE", "arg", "", "Previous mixture base distributions")
('m', "mc=FILE", "arg", "", "Previous mixture coefficients for the states")
('p', "ph=FILE", "arg", "", "Previous HMM definitions")
('o', "out=FILE", "arg must", "", "output file for the coefficients")
('L', "list=LISTNAME", "arg", "", "file with one statistics file per line")
('\0', "subspace=FILE", "arg", "", "use an already initialized subspace")
('\0', "to-pcgmm", "", "", "convert Gaussians to have a subspace constraint on precisions")
('\0', "to-scgmm", "", "", "convert Gaussians to have an exponential subspace constraint")
('\0', "ml", "", "", "maximum likelihood estimation")
('\0', "mmi", "", "", "maximum mutual information estimation")
('\0', "mpe", "", "", "minimum phone error estimation")
('\0', "minvar=FLOAT", "arg", "0.1", "minimum variance (default 0.1)")
('\0', "covsmooth", "arg", "0", "covariance smoothing (default 0.0)")
('\0', "C1=FLOAT", "arg", "1.0", "constant \"C1\" for MMI updates (default 1.0)")
('\0', "C2=FLOAT", "arg", "2.0", "constant \"C2\" for MMI updates (default 2.0)")
('\0', "mmi-ismooth=FLOAT", "arg", "0.0", "I-smoothing constant for MMI")
('\0', "mpe-ismooth=FLOAT", "arg", "0.0", "I-smoothing constant for MPE")
('\0', "mmi-prior", "", "", "Use MMI prior when I-smoothing MPE model")
('\0', "hcl_bfgs_cfg=FILE", "arg", "", "configuration file for HCL biconjugate gradient algorithm")
('\0', "hcl_line_cfg=FILE", "arg", "", "configuration file for HCL line search algorithm")
('B', "batch=INT", "arg", "0", "number of batch processes with the same recipe")
('I', "bindex=INT", "arg", "0", "batch process index")
('i', "info=INT", "arg", "0", "info level")
;
config.default_parse(argc, argv);
// Load the previous models
if (config["base"].specified)
model.read_all(config["base"].get_str());
else {
if (config["gk"].specified)
model.read_gk(config["gk"].get_str());
else
throw std::string("At least --gk should be defined");
if (config["mc"].specified)
model.read_mc(config["mc"].get_str());
if (config["ph"].specified)
model.read_ph(config["ph"].get_str());
}
// Linesearch for subspace models
HCL_LineSearch_MT_d ls;
if (config["hcl_line_cfg"].specified)
ls.Parameters().Merge(config["hcl_line_cfg"].get_str().c_str());
// lmBFGS for subspace models
HCL_UMin_lbfgs_d bfgs(&ls);
if (config["hcl_bfgs_cfg"].specified)
bfgs.Parameters().Merge(config["hcl_bfgs_cfg"].get_str().c_str());
model.set_hcl_optimization(&ls, &bfgs, config["hcl_line_cfg"].get_str(), config["hcl_bfgs_cfg"].get_str());
// Open the file for writing out the subspace coefficients
std::string outfilename = config["out"].get_str();
std::ofstream outfile(outfilename.c_str());
if (!outfile)
{
fprintf(stderr, "Could not open %s for writing\n", config["out"].get_str().c_str());
exit(1);
}
// Optimize coefficients for this batch
int start_pos = int(floor( (config["bindex"].get_int()-1) * model.num_pool_pdfs() / config["batch"].get_int() ));
int end_pos = int(ceil( config["bindex"].get_int() * model.num_pool_pdfs() / config["batch"].get_int() ));
// Print out some information
if (config["info"].get_int()>0)
std::cout << "Processing Gaussians " << start_pos+1 << "-" << end_pos
<< " of " << model.num_pool_pdfs() << std::endl;
// Convert based on the statistics
if (config["list"].specified) {
if (!config["base"].specified &&
!(config["gk"].specified && config["mc"].specified && config["ph"].specified))
throw std::string("Must give either --base or all --gk, --mc and --ph");
int count = 0;
if (config["ml"].specified) {
count++;
mode = PDF::ML_EST;
}
if (config["mmi"].specified) {
count++;
mode = PDF::MMI_EST;
}
if (config["mpe"].specified) {
count++;
mode = PDF::MPE_EST;
}
if (count != 1)
throw std::string("Define exactly one of --ml, --mmi and --mpe!");
if (config["mmi-ismooth"].specified &&
(!config["mmi"].specified && !config["mmi-prior"].specified))
fprintf(stderr, "Warning: --mmi-ismooth ignored without --mmi or --mmi-prior\n");
if (config["mpe-ismooth"].specified && mode != PDF::MPE_EST)
fprintf(stderr, "Warning: --mpe-ismooth ignored without --mpe\n");
if (config["mmi-prior"].specified)
{
if (mode == PDF::MPE_EST)
mode = PDF::MPE_MMI_PRIOR_EST;
else
fprintf(stderr, "Warning: --mmi-prior ignored without --mpe\n");
}
// Open the list of statistics files
std::ifstream filelist(config["list"].get_str().c_str());
if (!filelist)
{
fprintf(stderr, "Could not open %s\n", config["list"].get_str().c_str());
exit(1);
}
// Set parameters for Gaussian estimation
model.set_gaussian_parameters(config["minvar"].get_double(),
config["covsmooth"].get_double(),
config["C1"].get_double(),
config["C2"].get_double(),
config["mmi-ismooth"].get_double(),
config["mpe-ismooth"].get_double());
// Accumulate .gk statistics
model.start_accumulating(mode);
while (filelist >> stat_file && stat_file != " ")
model.accumulate_gk_from_dump(stat_file+".gks");
for (int g=start_pos; g<end_pos; g++)
{
PrecisionConstrainedGaussian *pc = dynamic_cast< PrecisionConstrainedGaussian* > (model.get_pool_pdf(g));
SubspaceConstrainedGaussian *sc = dynamic_cast< SubspaceConstrainedGaussian* > (model.get_pool_pdf(g));
if (pc != NULL || sc != NULL)
std::cout << "Training Gaussian: " << g+1 << "/" << model.num_pool_pdfs() << std::endl;
try {
if (pc != NULL)
pc->estimate_parameters(mode,
config["minvar"].get_double(),
config["covsmooth"].get_double(),
config["C1"].get_double(),
config["C2"].get_double(),
false);
else if (sc != NULL)
sc->estimate_parameters(mode,
config["minvar"].get_double(),
config["covsmooth"].get_double(),
config["C1"].get_double(),
config["C2"].get_double(),
false);
} catch (std::string errstr) {
std::cout << "Warning: Gaussian number " << g
<< ": " << errstr << std::endl;
}
outfile << g;
if (pc != NULL) {
pc->write(outfile);
}
else if (sc != NULL) {
sc->write(outfile);
}
outfile << std::endl;
}
}
// Convert the old model
else {
if (!config["to-pcgmm"].specified && !config["to-scgmm"].specified)
throw std::string("Define either --to-pcgmm or --to-scgmm if you want to convert an old model!");
if (config["to-pcgmm"].specified && config["to-scgmm"].specified)
throw std::string("Don't define both --to-pcgmm and --to-scgmm if you want to convert an old model!");
if (!config["subspace"].specified)
throw std::string("Please specify --subspace if you want to convert an old model");
PrecisionSubspace *ps = NULL;
ExponentialSubspace *es = NULL;
if (config["to-pcgmm"].specified) {
ps = new PrecisionSubspace();
std::ifstream in(config["subspace"].get_str().c_str());
ps->read_subspace(in);
ps->set_hcl_optimization(&ls, &bfgs, config["hcl_line_cfg"].get_str(), config["hcl_bfgs_cfg"].get_str());
in.close();
}
else if (config["to-scgmm"].specified) {
es = new ExponentialSubspace();
std::ifstream in(config["subspace"].get_str().c_str());
es->read_subspace(in);
es->set_hcl_optimization(&ls, &bfgs, config["hcl_line_cfg"].get_str(), config["hcl_bfgs_cfg"].get_str());
in.close();
}
Matrix covariance;
Vector mean;
for (int g=start_pos; g<end_pos; g++) {
// Print Gaussian index
if (config["info"].get_int()>0)
std::cout << "Converting Gaussian: " << g+1 << "/" << model.num_pool_pdfs();
// Fetch source Gaussian
Gaussian *source_gaussian = dynamic_cast< Gaussian* > (model.get_pool_pdf(g));
if (source_gaussian == NULL)
continue;
Gaussian *target_gaussian = NULL;
if (config["to-pcgmm"].specified)
target_gaussian = new PrecisionConstrainedGaussian(ps);
else if (config["to-scgmm"].specified)
target_gaussian = new SubspaceConstrainedGaussian(es);
// Get the old Gaussian parameters
source_gaussian->get_covariance(covariance);
source_gaussian->get_mean(mean);
// Set parameters
target_gaussian->set_parameters(mean, covariance);
// Print kullback-leibler
if (config["info"].get_int() > 0) {
std::cout << "\tkl-divergence: " << source_gaussian->kullback_leibler(*target_gaussian);
std::cout << std::endl;
}
outfile << g;
target_gaussian->write(outfile);
outfile << std::endl;
}
outfile.close();
}
}
catch (std::exception &e) {
fprintf(stderr, "exception: %s\n", e.what());
abort();
}
catch (std::string &str) {
fprintf(stderr, "exception: %s\n", str.c_str());
abort();
}
}