33 const std::string &ref_rspecifier,
34 const std::string &mode,
35 std::vector<std::pair<int32, int32> > & edit_word_per_hyp) {
40 int32 num_words = 0, word_errs = 0, num_ins = 0, num_del = 0, num_sub = 0;
43 for (; !ref_reader.
Done(); ref_reader.
Next()) {
44 std::string key = ref_reader.
Key();
45 const std::vector<std::string> &ref_sent = ref_reader.
Value();
46 std::vector<std::string> hyp_sent;
47 if (!hyp_reader.
HasKey(key)) {
49 KALDI_ERR <<
"No hypothesis for key " << key <<
" and strict " 51 if (mode ==
"present")
54 hyp_sent = hyp_reader.
Value(key);
56 num_words = ref_sent.size();
58 &num_ins, &num_del, &num_sub);
59 edit_word_per_hyp.push_back(std::pair<int32, int32>(word_errs, num_words));
64 const std::string &hyp_rspecifier2,
65 const std::string &ref_rspecifier,
66 const std::string &mode,
67 std::vector<std::pair<int32, int32> > & edit_word_per_hyp,
68 std::vector<std::pair<int32, int32> > & edit_word_per_hyp2) {
74 int32 num_words = 0, word_errs = 0,
75 num_ins = 0, num_del = 0, num_sub = 0;
78 for (; !ref_reader.
Done(); ref_reader.
Next()) {
79 std::string key = ref_reader.
Key();
80 const std::vector<std::string> &ref_sent = ref_reader.
Value();
81 std::vector<std::string> hyp_sent, hyp_sent2;
82 if (mode ==
"strict" &&
84 KALDI_ERR <<
"No hypothesis for key " << key <<
" in both transcripts " 85 "comparison is not possible.";
86 }
else if (mode ==
"present" &&
90 num_words = ref_sent.size();
93 if(hyp_reader.
HasKey(key)){
94 hyp_sent = hyp_reader.
Value(key);
96 &num_ins, &num_del, &num_sub);
99 word_errs = num_words;
100 edit_word_per_hyp.push_back(std::pair<int32, int32>(word_errs, num_words));
102 if(hyp_reader2.
HasKey(key)){
103 hyp_sent2 = hyp_reader2.
Value(key);
105 &num_ins, &num_del, &num_sub);
108 word_errs = num_words;
109 edit_word_per_hyp2.push_back(std::pair<int32, int32>(word_errs, num_words));
114 const std::vector<std::pair<int32, int32> > & edit_word_per_hyp,
117 BaseFloat wer_accum = 0.0, wer_mult_accum = 0.0;
119 for (
int32 i = 0;
i < replications; ++
i) {
120 int32 num_words = 0, word_errs = 0;
121 for (
int32 j = 0;
j < edit_word_per_hyp.size(); ++
j) {
123 word_errs += edit_word_per_hyp[random_pos].first;
124 num_words += edit_word_per_hyp[random_pos].second;
128 wer_accum += wer_rep;
129 wer_mult_accum += wer_rep*wer_rep;
133 *mean = wer_accum / replications;
134 *interval = 1.96*sqrt(wer_mult_accum/replications-(*mean)*(*mean));
138 const std::vector<std::pair<int32, int32> > & edit_word_per_hyp,
139 const std::vector<std::pair<int32, int32> > & edit_word_per_hyp2,
141 int32 improv_accum = 0.0;
143 for (
int32 i = 0;
i < replications; ++
i) {
145 for (
int32 j = 0;
j < edit_word_per_hyp.size(); ++
j) {
147 word_errs += edit_word_per_hyp[random_pos].first -
148 edit_word_per_hyp2[random_pos].first;
154 *p_improv =
static_cast<BaseFloat>(improv_accum) / replications;
159 int main(
int argc,
char *argv[]) {
160 using namespace kaldi;
165 "Compute a bootstrapping of WER to extract the 95% confidence interval.\n" 166 "Take a reference and a transcription file, in integer or text format,\n" 167 "and outputs overall WER statistics to standard output along with its\n" 168 "confidence interval using the bootstrap method of Bisani and Ney.\n" 169 "If a second transcription file corresponding to the same reference is\n" 170 "provided, a bootstrap comparison of the two transcription is performed\n" 171 "to estimate the probability of improvement.\n" 173 "Usage: compute-wer-bootci [options] <ref-rspecifier> <hyp-rspecifier> [<hyp2-rspecifier>]\n" 174 "E.g.: compute-wer-bootci --mode=present ark:data/train/text ark:hyp_text\n" 175 "or compute-wer-bootci ark:data/train/text ark:hyp_text ark:hyp_text2\n" 176 "See also: compute-wer\n";
180 std::string mode =
"strict";
182 "Scoring mode: \"present\"|\"all\"|\"strict\":\n" 183 " \"present\" means score those we have transcriptions for\n" 184 " \"all\" means treat absent transcriptions as empty\n" 185 " \"strict\" means die if all in ref not also in hyp");
187 int32 replications = 10000;
188 po.
Register(
"replications", &replications,
189 "Number of replications to compute the intervals");
198 std::string ref_rspecifier = po.
GetArg(1);
199 std::string hyp_rspecifier = po.
GetArg(2);
200 std::string hyp2_rspecifier = (po.
NumArgs() == 3?po.
GetArg(3):
"");
202 if (mode !=
"strict" && mode !=
"present" && mode !=
"all") {
204 "--mode option invalid: expected \"present\"|\"all\"|\"strict\", got " 209 std::vector<std::pair<int32, int32> > edit_word_per_hyp, edit_word_per_hyp2;
210 if(hyp2_rspecifier.empty())
214 edit_word_per_hyp, edit_word_per_hyp2);
218 BaseFloat mean_wer = 0.0, interval = 0.0,
219 mean_wer2 = 0.0, interval2 = 0.0,
223 &mean_wer, &interval);
225 if(!hyp2_rspecifier.empty()) {
227 &mean_wer2, &interval2);
230 replications, &p_improv);
234 std::cout.precision(2);
235 std::cerr.precision(2);
236 std::cout <<
"Set1: %WER " << std::fixed << 100*mean_wer <<
237 " 95% Conf Interval [ " << 100*mean_wer-100*interval <<
238 ", " << 100*mean_wer+100*interval <<
" ]" <<
'\n';
240 if(!hyp2_rspecifier.empty()) {
241 std::cout <<
"Set2: %WER " << std::fixed << 100*mean_wer2 <<
242 " 95% Conf Interval [ " << 100*mean_wer2-100*interval2 <<
243 ", " << 100*mean_wer2+100*interval2 <<
" ]" <<
'\n';
245 std::cout <<
"Probability of Set2 improving Set1: " << std::fixed <<
246 100*p_improv <<
'\n';
250 }
catch(
const std::exception &e) {
251 std::cerr << e.what();
This code computes Goodness of Pronunciation (GOP) and extracts phone-level pronunciation feature for...
void GetEditsSingleHyp(const std::string &hyp_rspecifier, const std::string &ref_rspecifier, const std::string &mode, std::vector< std::pair< int32, int32 > > &edit_word_per_hyp)
int main(int argc, char *argv[])
void PrintUsage(bool print_command_line=false)
Prints the usage documentation [provided in the constructor].
void GetEditsDualHyp(const std::string &hyp_rspecifier, const std::string &hyp_rspecifier2, const std::string &ref_rspecifier, const std::string &mode, std::vector< std::pair< int32, int32 > > &edit_word_per_hyp, std::vector< std::pair< int32, int32 > > &edit_word_per_hyp2)
void Register(const std::string &name, bool *ptr, const std::string &doc)
Allows random access to a collection of objects in an archive or script file; see The Table concept...
int32 LevenshteinEditDistance(const std::vector< T > &a, const std::vector< T > &b)
The class ParseOptions is for parsing command-line options; see Parsing command-line options for more...
const T & Value(const std::string &key)
A templated class for reading objects sequentially from an archive or script file; see The Table conc...
int Read(int argc, const char *const *argv)
Parses the command line options and fills the ParseOptions-registered variables.
std::string GetArg(int param) const
Returns one of the positional parameters; 1-based indexing for argc/argv compatibility.
void GetBootstrapWERInterval(const std::vector< std::pair< int32, int32 > > &edit_word_per_hyp, int32 replications, BaseFloat *mean, BaseFloat *interval)
bool HasKey(const std::string &key)
int NumArgs() const
Number of positional parameters (c.f. argc-1).
void GetBootstrapWERTwoSystemComparison(const std::vector< std::pair< int32, int32 > > &edit_word_per_hyp, const std::vector< std::pair< int32, int32 > > &edit_word_per_hyp2, int32 replications, BaseFloat *p_improv)
int32 RandInt(int32 min_val, int32 max_val, struct RandomState *state)