summaryrefslogtreecommitdiff
path: root/mteval/ns_comb.cc
blob: 41c634cddfb416dfa12e4466430123a4a2048d06 (plain)
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
#include "ns_comb.h"

#include <iostream>

#include "stringlib.h"

using namespace std;

// e.g. COMB:IBM_BLEU=0.5;TER=0.5
CombinationMetric::CombinationMetric(const std::string& cmd) :
    EvaluationMetric(cmd),
    total_size() {
  if (cmd.find("COMB:") != 0 || cmd.size() < 9) {
    cerr << "Error in combination metric specifier: " << cmd << endl;
    exit(1);
  }
  string mix = cmd.substr(5);
  vector<string> comps;
  Tokenize(cmd.substr(5), ';', &comps);
  if(comps.size() < 2) {
    cerr << "Error in combination metric specifier: " << cmd << endl;
    exit(1);
  }
  vector<string> cwpairs;
  for (unsigned i = 0; i < comps.size(); ++i) {
    Tokenize(comps[i], '=', &cwpairs);
    if (cwpairs.size() != 2) { cerr << "Error in combination metric specifier: " << cmd << endl; exit(1); }
    metrics.push_back(EvaluationMetric::Instance(cwpairs[0]));
    coeffs.push_back(atof(cwpairs[1].c_str()));
    offsets.push_back(total_size);
    total_size += metrics.back()->SufficientStatisticsVectorSize();
    cerr << (i > 0 ? " + " : "( ") << coeffs.back() << " * " << cwpairs[0];
  }
  cerr << " )\n";
}

struct CombinationSegmentEvaluator : public SegmentEvaluator {
  CombinationSegmentEvaluator(const string& id,
                              const vector<vector<WordID> >& refs,
                              const vector<EvaluationMetric*>& metrics,
                              const vector<unsigned>& offsets,
                              const unsigned ts) : id_(id), offsets_(offsets), total_size_(ts), component_evaluators_(metrics.size()) {
    for (unsigned i = 0; i < metrics.size(); ++i)
      component_evaluators_[i] = metrics[i]->CreateSegmentEvaluator(refs);
  }
  virtual void Evaluate(const std::vector<WordID>& hyp, SufficientStats* out) const {
    out->id_ = id_;
    out->fields.resize(total_size_);
    for (unsigned i = 0; i < component_evaluators_.size(); ++i) {
      SufficientStats t;
      component_evaluators_[i]->Evaluate(hyp, &t);
      for (unsigned j = 0; j < t.fields.size(); ++j) {
        unsigned op = j + offsets_[i];
        assert(op < out->fields.size());
        out->fields[op] = t[j];
      }
    }
  }
  const string& id_;
  const vector<unsigned>& offsets_;
  const unsigned total_size_;
  vector<boost::shared_ptr<SegmentEvaluator> > component_evaluators_;
};

boost::shared_ptr<SegmentEvaluator> CombinationMetric::CreateSegmentEvaluator(const std::vector<std::vector<WordID> >& refs) const {
  boost::shared_ptr<SegmentEvaluator> res;
  res.reset(new CombinationSegmentEvaluator(MetricId(), refs, metrics, offsets, total_size));
  return res;
}

float CombinationMetric::ComputeScore(const SufficientStats& stats) const {
  float tot = 0;
  for (unsigned i = 0; i < metrics.size(); ++i) {
    SufficientStats t;
    unsigned next = total_size;
    if (i + 1 < offsets.size()) next = offsets[i+1];
    for (unsigned j = offsets[i]; j < next; ++j)
      t.fields.push_back(stats[j]);
    tot += metrics[i]->ComputeScore(t) * coeffs[i];
  }
  return tot;
}

unsigned CombinationMetric::SufficientStatisticsVectorSize() const {
  return total_size;
}