compute-eer.cc
Go to the documentation of this file.
1 // ivectorbin/compute-eer.cc
2 
3 // Copyright 2013 Daniel Povey
4 
5 // See ../../COPYING for clarification regarding multiple authors
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 // http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
15 // WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
16 // MERCHANTABLITY OR NON-INFRINGEMENT.
17 // See the Apache 2 License for the specific language governing permissions and
18 // limitations under the License.
19 
20 
21 #include "base/kaldi-common.h"
22 #include "util/common-utils.h"
23 
24 namespace kaldi {
25 
48 BaseFloat ComputeEer(std::vector<BaseFloat> *target_scores,
49  std::vector<BaseFloat> *nontarget_scores,
50  BaseFloat *threshold) {
51  KALDI_ASSERT(!target_scores->empty() && !nontarget_scores->empty());
52  std::sort(target_scores->begin(), target_scores->end());
53  std::sort(nontarget_scores->begin(), nontarget_scores->end());
54 
55  size_t target_position = 0,
56  target_size = target_scores->size();
57  for (; target_position + 1 < target_size; target_position++) {
58  ssize_t nontarget_size = nontarget_scores->size(),
59  nontarget_n = nontarget_size * target_position * 1.0 / target_size,
60  nontarget_position = nontarget_size - 1 - nontarget_n;
61  if (nontarget_position < 0)
62  nontarget_position = 0;
63  if ((*nontarget_scores)[nontarget_position] <
64  (*target_scores)[target_position])
65  break;
66  }
67  *threshold = (*target_scores)[target_position];
68  BaseFloat eer = target_position * 1.0 / target_size;
69  return eer;
70 }
71 
72 
73 }
74 
75 
76 
77 int main(int argc, char *argv[]) {
78  using namespace kaldi;
79  typedef kaldi::int32 int32;
80  try {
81  const char *usage =
82  "Computes Equal Error Rate\n"
83  "Input is a series of lines, each with two fields.\n"
84  "The first field must be a numeric score, and the second\n"
85  "either the string 'target' or 'nontarget'. \n"
86  "The EER will be printed to the standard output.\n"
87  "\n"
88  "Usage: compute-eer <scores-in>\n"
89  "e.g.: compute-eer -\n";
90 
91  ParseOptions po(usage);
92  po.Read(argc, argv);
93 
94  if (po.NumArgs() != 1) {
95  po.PrintUsage();
96  exit(1);
97  }
98 
99  std::string scores_rxfilename = po.GetArg(1);
100 
101  std::vector<BaseFloat> target_scores, nontarget_scores;
102  Input ki(scores_rxfilename);
103 
104  std::string line;
105  while (std::getline(ki.Stream(), line)) {
106  std::vector<std::string> split_line;
107  SplitStringToVector(line, " \t", true, &split_line);
108  BaseFloat score;
109  if (split_line.size() != 2) {
110  KALDI_ERR << "Invalid input line (must have two fields): "
111  << line;
112  }
113  if (!ConvertStringToReal(split_line[0], &score)) {
114  KALDI_ERR << "Invalid input line (first field must be float): "
115  << line;
116  }
117  if (split_line[1] == "target")
118  target_scores.push_back(score);
119  else if (split_line[1] == "nontarget")
120  nontarget_scores.push_back(score);
121  else {
122  KALDI_ERR << "Invalid input line (second field must be "
123  << "'target' or 'nontarget')";
124  }
125  }
126  if (target_scores.empty() && nontarget_scores.empty())
127  KALDI_ERR << "Empty input.";
128  if (target_scores.empty())
129  KALDI_ERR << "No target scores seen.";
130  if (nontarget_scores.empty())
131  KALDI_ERR << "No non-target scores seen.";
132 
133  BaseFloat threshold;
134  BaseFloat eer = ComputeEer(&target_scores, &nontarget_scores, &threshold);
135 
136  KALDI_LOG << "Equal error rate is " << (100.0 * eer)
137  << "%, at threshold " << threshold;
138 
139  std::cout.precision(4);
140  std::cout << (100.0 * eer);
141 
142  return 0;
143  } catch(const std::exception &e) {
144  std::cerr << e.what();
145  return -1;
146  }
147 }
This code computes Goodness of Pronunciation (GOP) and extracts phone-level pronunciation feature for...
Definition: chain.dox:20
int main(int argc, char *argv[])
Definition: compute-eer.cc:77
void PrintUsage(bool print_command_line=false)
Prints the usage documentation [provided in the constructor].
kaldi::int32 int32
std::istream & Stream()
Definition: kaldi-io.cc:826
float BaseFloat
Definition: kaldi-types.h:29
The class ParseOptions is for parsing command-line options; see Parsing command-line options for more...
Definition: parse-options.h:36
void SplitStringToVector(const std::string &full, const char *delim, bool omit_empty_strings, std::vector< std::string > *out)
Split a string using any of the single character delimiters.
Definition: text-utils.cc:63
int Read(int argc, const char *const *argv)
Parses the command line options and fills the ParseOptions-registered variables.
#define KALDI_ERR
Definition: kaldi-error.h:147
bool ConvertStringToReal(const std::string &str, T *out)
ConvertStringToReal converts a string into either float or double and returns false if there was any ...
Definition: text-utils.cc:238
std::string GetArg(int param) const
Returns one of the positional parameters; 1-based indexing for argc/argv compatibility.
BaseFloat ComputeEer(std::vector< BaseFloat > *target_scores, std::vector< BaseFloat > *nontarget_scores, BaseFloat *threshold)
ComputeEer computes the Equal Error Rate (EER) for the given scores and returns it as a proportion be...
Definition: compute-eer.cc:48
int NumArgs() const
Number of positional parameters (c.f. argc-1).
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
#define KALDI_LOG
Definition: kaldi-error.h:153