Store SHyperedge feature scores as deltas instead of totals

This mirrors the change made for the chart decoder in commit 465b4756...
This commit is contained in:
Phil Williams 2015-11-16 19:23:27 +00:00
parent 07001f7645
commit d317fdc373
12 changed files with 70 additions and 37 deletions

View File

@ -393,9 +393,7 @@ template <class Model> FFState *LanguageModelKen<Model>::EvaluateWhenApplied(con
// Non-terminal is first so we can copy instead of rescoring.
const Syntax::SVertex *pred = hyperedge.tail[nonTermIndexMap[phrasePos]];
const lm::ngram::ChartState &prevState = static_cast<const LanguageModelChartStateKenLM*>(pred->states[featureID])->GetChartState();
float prob = UntransformLMScore(
pred->best->label.scoreBreakdown.GetScoresForProducer(this)[0]);
ruleScore.BeginNonTerminal(prevState, prob);
ruleScore.BeginNonTerminal(prevState);
phrasePos++;
}
}
@ -405,9 +403,7 @@ template <class Model> FFState *LanguageModelKen<Model>::EvaluateWhenApplied(con
if (word.IsNonTerminal()) {
const Syntax::SVertex *pred = hyperedge.tail[nonTermIndexMap[phrasePos]];
const lm::ngram::ChartState &prevState = static_cast<const LanguageModelChartStateKenLM*>(pred->states[featureID])->GetChartState();
float prob = UntransformLMScore(
pred->best->label.scoreBreakdown.GetScoresForProducer(this)[0]);
ruleScore.NonTerminal(prevState, prob);
ruleScore.NonTerminal(prevState);
} else {
ruleScore.Terminal(TranslateID(word));
}
@ -415,7 +411,16 @@ template <class Model> FFState *LanguageModelKen<Model>::EvaluateWhenApplied(con
float score = ruleScore.Finish();
score = TransformLMScore(score);
accumulator->Assign(this, score);
score -= target.GetScoreBreakdown().GetScoresForProducer(this)[0];
if (OOVFeatureEnabled()) {
std::vector<float> scores(2);
scores[0] = score;
scores[1] = 0.0;
accumulator->PlusEquals(this, scores);
} else {
accumulator->PlusEquals(this, score);
}
return newState;
}

View File

@ -101,10 +101,6 @@ SHyperedge *Cube::CreateHyperedge(const std::vector<int> &coordinates)
for (std::size_t i = 0; i < coordinates.size()-1; ++i) {
boost::shared_ptr<SVertex> pred = (*m_bundle.stacks[i])[coordinates[i]];
hyperedge->tail[i] = pred.get();
if (pred->best) {
hyperedge->label.scoreBreakdown.PlusEquals(
pred->best->label.scoreBreakdown);
}
}
hyperedge->label.inputWeight = m_bundle.inputWeight;
@ -112,8 +108,7 @@ SHyperedge *Cube::CreateHyperedge(const std::vector<int> &coordinates)
hyperedge->label.translation =
*(m_bundle.translations->begin()+coordinates.back());
hyperedge->label.scoreBreakdown.PlusEquals(
hyperedge->label.translation->GetScoreBreakdown());
// Calculate feature deltas.
const StaticData &staticData = StaticData::Instance();
@ -123,7 +118,7 @@ SHyperedge *Cube::CreateHyperedge(const std::vector<int> &coordinates)
StatelessFeatureFunction::GetStatelessFeatureFunctions();
for (unsigned i = 0; i < sfs.size(); ++i) {
if (!staticData.IsFeatureFunctionIgnored(*sfs[i])) {
sfs[i]->EvaluateWhenApplied(*hyperedge, &hyperedge->label.scoreBreakdown);
sfs[i]->EvaluateWhenApplied(*hyperedge, &hyperedge->label.deltas);
}
}
@ -132,12 +127,24 @@ SHyperedge *Cube::CreateHyperedge(const std::vector<int> &coordinates)
for (unsigned i = 0; i < ffs.size(); ++i) {
if (!staticData.IsFeatureFunctionIgnored(*ffs[i])) {
head->states[i] =
ffs[i]->EvaluateWhenApplied(*hyperedge, i,
&hyperedge->label.scoreBreakdown);
ffs[i]->EvaluateWhenApplied(*hyperedge, i, &hyperedge->label.deltas);
}
}
hyperedge->label.score = hyperedge->label.scoreBreakdown.GetWeightedScore();
// Calculate future score.
hyperedge->label.futureScore =
hyperedge->label.translation->GetScoreBreakdown().GetWeightedScore();
hyperedge->label.futureScore += hyperedge->label.deltas.GetWeightedScore();
for (std::vector<SVertex*>::const_iterator p = hyperedge->tail.begin();
p != hyperedge->tail.end(); ++p) {
const SVertex *pred = *p;
if (pred->best) {
hyperedge->label.futureScore += pred->best->label.futureScore;
}
}
return hyperedge;
}

View File

@ -42,7 +42,7 @@ private:
{
public:
bool operator()(const QueueItem &p, const QueueItem &q) const {
return p.first->label.score < q.first->label.score;
return p.first->label.futureScore < q.first->label.futureScore;
}
};

View File

@ -31,7 +31,7 @@ private:
{
public:
bool operator()(const Cube *p, const Cube *q) const {
return p->Top()->label.score < q->Top()->label.score;
return p->Top()->label.futureScore < q->Top()->label.futureScore;
}
};

View File

@ -304,7 +304,7 @@ void Manager<RuleMatcher>::RecombineAndSort(
// Compare the score of h against the score of the best incoming hyperedge
// for the stored vertex.
SVertex *storedVertex = result.first->second;
if (h->label.score > storedVertex->best->label.score) {
if (h->label.futureScore > storedVertex->best->label.futureScore) {
// h's score is better.
storedVertex->recombined.push_back(storedVertex->best);
storedVertex->best = h;

View File

@ -32,24 +32,25 @@ void KBestExtractor::Extract(
supremeVertex->best = new SHyperedge();
supremeVertex->best->head = supremeVertex.get();
supremeVertex->best->tail.push_back(&bestTopLevelVertex);
supremeVertex->best->label.score = bestTopLevelVertex.best->label.score;
supremeVertex->best->label.scoreBreakdown =
bestTopLevelVertex.best->label.scoreBreakdown;
supremeVertex->best->label.futureScore =
bestTopLevelVertex.best->label.futureScore;
supremeVertex->best->label.deltas = bestTopLevelVertex.best->label.deltas;
supremeVertex->best->label.translation = 0;
// For each alternative top-level SVertex, add a new incoming hyperedge to
// supremeVertex.
for (++p; p != topLevelVertices.end(); ++p) {
// Check that the first item in topLevelVertices really was the best.
UTIL_THROW_IF2((*p)->best->label.score > bestTopLevelVertex.best->label.score,
UTIL_THROW_IF2((*p)->best->label.futureScore >
bestTopLevelVertex.best->label.futureScore,
"top-level SVertices are not correctly sorted");
// Note: there's no need for a smart pointer here: supremeVertex will take
// ownership of altEdge.
SHyperedge *altEdge = new SHyperedge();
altEdge->head = supremeVertex.get();
altEdge->tail.push_back((*p).get());
altEdge->label.score = (*p)->best->label.score;
altEdge->label.scoreBreakdown = (*p)->best->label.scoreBreakdown;
altEdge->label.futureScore = (*p)->best->label.futureScore;
altEdge->label.deltas = (*p)->best->label.deltas;
altEdge->label.translation = 0;
supremeVertex->recombined.push_back(altEdge);
}
@ -282,7 +283,13 @@ void KBestExtractor::LazyNext(KVertex &v, const Derivation &d,
KBestExtractor::Derivation::Derivation(const boost::shared_ptr<KHyperedge> &e)
{
edge = e;
std::size_t arity = edge->tail.size();
const TargetPhrase *translation = edge->shyperedge.label.translation;
// Every hyperedge should have an associated target phrase, except for
// incoming hyperedges of the 'supreme' vertex.
if (translation) {
scoreBreakdown = translation->GetScoreBreakdown();
}
const std::size_t arity = edge->tail.size();
backPointers.resize(arity, 0);
subderivations.reserve(arity);
for (std::size_t i = 0; i < arity; ++i) {
@ -290,9 +297,10 @@ KBestExtractor::Derivation::Derivation(const boost::shared_ptr<KHyperedge> &e)
assert(pred.kBestList.size() >= 1);
boost::shared_ptr<Derivation> sub(pred.kBestList[0]);
subderivations.push_back(sub);
scoreBreakdown.PlusEquals(sub->scoreBreakdown);
}
score = edge->shyperedge.label.score;
scoreBreakdown = edge->shyperedge.label.scoreBreakdown;
scoreBreakdown.PlusEquals(edge->shyperedge.label.deltas);
score = scoreBreakdown.GetWeightedScore();
}
// Construct a Derivation that neighbours an existing Derivation.

View File

@ -32,7 +32,7 @@ void Manager::OutputBest(OutputCollector *collector) const
out << '\n';
} else {
if (options().output.ReportHypoScore) {
out << best->label.score << " ";
out << best->label.futureScore << " ";
}
Phrase yield = GetOneBestTargetYield(*best);
// delete 1st & last

View File

@ -368,7 +368,7 @@ void Manager<Parser>::RecombineAndSort(const std::vector<SHyperedge*> &buffer,
// Compare the score of h against the score of the best incoming hyperedge
// for the stored vertex.
SVertex *storedVertex = result.first->second;
if (h->label.score > storedVertex->best->label.score) {
if (h->label.futureScore > storedVertex->best->label.futureScore) {
// h's score is better.
storedVertex->recombined.push_back(storedVertex->best);
storedVertex->best = h;

View File

@ -16,7 +16,7 @@ public:
bundle.stacks.begin(); p != bundle.stacks.end(); ++p) {
const SVertexStack *stack = *p;
if (stack->front()->best) {
score += stack->front()->best->label.score;
score += stack->front()->best->label.futureScore;
}
}
return score;

View File

@ -8,11 +8,24 @@ namespace Moses
namespace Syntax
{
// A SHyperedge label.
//
struct SLabel {
float inputWeight;
float score;
ScoreComponentCollection scoreBreakdown;
// Deltas for individual feature scores. i.e. this object records the change
// in each feature score that results from applying the rule associated with
// this hyperedge.
ScoreComponentCollection deltas;
// Total derivation score to be used for comparison in beam search (i.e.
// including future cost estimates). This is the sum of the 1-best
// subderivations' future scores + deltas.
float futureScore;
// Target-side of the grammar rule.
const TargetPhrase *translation;
// Input weight of this hyperedge (e.g. from weighted input forest).
float inputWeight;
};
} // Syntax

View File

@ -18,7 +18,7 @@ struct SVertexStackContentOrderer {
public:
bool operator()(const boost::shared_ptr<SVertex> &x,
const boost::shared_ptr<SVertex> &y) {
return x->best->label.score > y->best->label.score;
return x->best->label.futureScore > y->best->label.futureScore;
}
};

View File

@ -264,7 +264,7 @@ void Manager<RuleMatcher>::RecombineAndSort(
// Compare the score of h against the score of the best incoming hyperedge
// for the stored vertex.
SVertex *storedVertex = result.first->second;
if (h->label.score > storedVertex->best->label.score) {
if (h->label.futureScore > storedVertex->best->label.futureScore) {
// h's score is better.
storedVertex->recombined.push_back(storedVertex->best);
storedVertex->best = h;