00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "LatticeMBR.h"
00011 #include "moses/StaticData.h"
00012 #include <algorithm>
00013 #include <set>
00014
00015 using namespace std;
00016 using namespace Moses;
00017
00018 namespace MosesCmd
00019 {
00020
00021 size_t bleu_order = 4;
00022 float UNKNGRAMLOGPROB = -20;
00023 void GetOutputWords(const TrellisPath &path, vector <Word> &translation)
00024 {
00025 const std::vector<const Hypothesis *> &edges = path.GetEdges();
00026
00027
00028 for (int currEdge = (int)edges.size() - 1 ; currEdge >= 0 ; currEdge--) {
00029 const Hypothesis &edge = *edges[currEdge];
00030 const Phrase &phrase = edge.GetCurrTargetPhrase();
00031 size_t size = phrase.GetSize();
00032 for (size_t pos = 0 ; pos < size ; pos++) {
00033 translation.push_back(phrase.GetWord(pos));
00034 }
00035 }
00036 }
00037
00038
00039 void extract_ngrams(const vector<Word >& sentence, map < Phrase, int > & allngrams)
00040 {
00041 for (int k = 0; k < (int)bleu_order; k++) {
00042 for(int i =0; i < max((int)sentence.size()-k,0); i++) {
00043 Phrase ngram( k+1);
00044 for ( int j = i; j<= i+k; j++) {
00045 ngram.AddWord(sentence[j]);
00046 }
00047 ++allngrams[ngram];
00048 }
00049 }
00050 }
00051
00052
00053
00054 void NgramScores::addScore(const Hypothesis* node, const Phrase& ngram, float score)
00055 {
00056 set<Phrase>::const_iterator ngramIter = m_ngrams.find(ngram);
00057 if (ngramIter == m_ngrams.end()) {
00058 ngramIter = m_ngrams.insert(ngram).first;
00059 }
00060 map<const Phrase*,float>& ngramScores = m_scores[node];
00061 map<const Phrase*,float>::iterator scoreIter = ngramScores.find(&(*ngramIter));
00062 if (scoreIter == ngramScores.end()) {
00063 ngramScores[&(*ngramIter)] = score;
00064 } else {
00065 ngramScores[&(*ngramIter)] = log_sum(score,scoreIter->second);
00066 }
00067 }
00068
00069 NgramScores::NodeScoreIterator NgramScores::nodeBegin(const Hypothesis* node)
00070 {
00071 return m_scores[node].begin();
00072 }
00073
00074
00075 NgramScores::NodeScoreIterator NgramScores::nodeEnd(const Hypothesis* node)
00076 {
00077 return m_scores[node].end();
00078 }
00079
00080 LatticeMBRSolution::LatticeMBRSolution(const TrellisPath& path, bool isMap) :
00081 m_score(0.0f)
00082 {
00083 const std::vector<const Hypothesis *> &edges = path.GetEdges();
00084
00085 for (int currEdge = (int)edges.size() - 1 ; currEdge >= 0 ; currEdge--) {
00086 const Hypothesis &edge = *edges[currEdge];
00087 const Phrase &phrase = edge.GetCurrTargetPhrase();
00088 size_t size = phrase.GetSize();
00089 for (size_t pos = 0 ; pos < size ; pos++) {
00090 m_words.push_back(phrase.GetWord(pos));
00091 }
00092 }
00093 if (isMap) {
00094 m_mapScore = path.GetTotalScore();
00095 } else {
00096 m_mapScore = 0;
00097 }
00098 }
00099
00100
00101 void LatticeMBRSolution::CalcScore(map<Phrase, float>& finalNgramScores, const vector<float>& thetas, float mapWeight)
00102 {
00103 m_ngramScores.assign(thetas.size()-1, -10000);
00104
00105 map < Phrase, int > counts;
00106 extract_ngrams(m_words,counts);
00107
00108
00109 m_score = thetas[0] * m_words.size();
00110
00111
00112 for (map < Phrase, int >::iterator ngrams = counts.begin(); ngrams != counts.end(); ++ngrams) {
00113 float ngramPosterior = UNKNGRAMLOGPROB;
00114 map<Phrase,float>::const_iterator ngramPosteriorIt = finalNgramScores.find(ngrams->first);
00115 if (ngramPosteriorIt != finalNgramScores.end()) {
00116 ngramPosterior = ngramPosteriorIt->second;
00117 }
00118 size_t ngramSize = ngrams->first.GetSize();
00119 m_ngramScores[ngramSize-1] = log_sum(log((float)ngrams->second) + ngramPosterior,m_ngramScores[ngramSize-1]);
00120 }
00121
00122
00123 for (size_t i = 0; i < m_ngramScores.size(); ++i) {
00124 m_ngramScores[i] = exp(m_ngramScores[i]);
00125 m_score += thetas[i+1] * m_ngramScores[i];
00126 }
00127
00128
00129
00130 m_score += m_mapScore*mapWeight;
00131 }
00132
00133
00134 void pruneLatticeFB(Lattice & connectedHyp, map < const Hypothesis*, set <const Hypothesis* > > & outgoingHyps, map<const Hypothesis*, vector<Edge> >& incomingEdges,
00135 const vector< float> & estimatedScores, const Hypothesis* bestHypo, size_t edgeDensity, float scale)
00136 {
00137
00138
00139 VERBOSE(2,"Pruning lattice to edge density " << edgeDensity << endl);
00140 const Hypothesis* emptyHyp = connectedHyp.at(0);
00141 while (emptyHyp->GetId() != 0) {
00142 emptyHyp = emptyHyp->GetPrevHypo();
00143 }
00144 connectedHyp.push_back(emptyHyp);
00145
00146
00147 for (size_t i = 0; i < connectedHyp.size(); ++i) {
00148 if (connectedHyp[i]->GetId() > 0 && connectedHyp[i]->GetPrevHypo()->GetId() == 0)
00149 outgoingHyps[emptyHyp].insert(connectedHyp[i]);
00150 }
00151
00152
00153 multimap<float, const Hypothesis*> sortHypsByVal;
00154 for (size_t i =0; i < estimatedScores.size(); ++i) {
00155 sortHypsByVal.insert(make_pair(estimatedScores[i], connectedHyp[i]));
00156 }
00157
00158 multimap<float, const Hypothesis*>::const_iterator it = --sortHypsByVal.end();
00159 float bestScore = it->first;
00160
00161 sortHypsByVal.insert(make_pair(bestScore, emptyHyp));
00162
00163
00164 IFVERBOSE(3) {
00165 for (multimap<float, const Hypothesis*>::const_iterator it = --sortHypsByVal.end(); it != --sortHypsByVal.begin(); --it) {
00166 const Hypothesis* currHyp = it->second;
00167 cerr << "Hyp " << currHyp->GetId() << ", estimated score: " << it->first << endl;
00168 }
00169 }
00170
00171
00172 set <const Hypothesis*> survivingHyps;
00173
00174 VERBOSE(2, "BEST HYPO TARGET LENGTH : " << bestHypo->GetSize() << endl)
00175 size_t numEdgesTotal = edgeDensity * bestHypo->GetSize();
00176 size_t numEdgesCreated = 0;
00177 VERBOSE(2, "Target edge count: " << numEdgesTotal << endl);
00178
00179 float prevScore = -999999;
00180
00181
00182 for (multimap<float, const Hypothesis*>::const_iterator it = --sortHypsByVal.end(); it != --sortHypsByVal.begin(); --it) {
00183 float currEstimatedScore = it->first;
00184 const Hypothesis* currHyp = it->second;
00185
00186 if (numEdgesCreated >= numEdgesTotal && prevScore > currEstimatedScore)
00187 break;
00188
00189 prevScore = currEstimatedScore;
00190 VERBOSE(3, "Num edges created : "<< numEdgesCreated << ", numEdges wanted " << numEdgesTotal << endl)
00191 VERBOSE(3, "Considering hyp " << currHyp->GetId() << ", estimated score: " << it->first << endl)
00192
00193 survivingHyps.insert(currHyp);
00194
00195
00196 if (survivingHyps.find(currHyp->GetPrevHypo()) != survivingHyps.end()) {
00197 vector <Edge>& edges = incomingEdges[currHyp];
00198 Edge winningEdge(currHyp->GetPrevHypo(),currHyp,scale*(currHyp->GetScore() - currHyp->GetPrevHypo()->GetScore()),currHyp->GetCurrTargetPhrase());
00199 edges.push_back(winningEdge);
00200 ++numEdgesCreated;
00201 }
00202
00203
00204 const ArcList *arcList = currHyp->GetArcList();
00205 if (arcList != NULL) {
00206 ArcList::const_iterator iterArcList;
00207 for (iterArcList = arcList->begin() ; iterArcList != arcList->end() ; ++iterArcList) {
00208 const Hypothesis *loserHypo = *iterArcList;
00209 const Hypothesis* loserPrevHypo = loserHypo->GetPrevHypo();
00210 if (survivingHyps.find(loserPrevHypo) != survivingHyps.end()) {
00211 double arcScore = loserHypo->GetScore() - loserPrevHypo->GetScore();
00212 Edge losingEdge(loserPrevHypo, currHyp, arcScore*scale, loserHypo->GetCurrTargetPhrase());
00213 vector <Edge>& edges = incomingEdges[currHyp];
00214 edges.push_back(losingEdge);
00215 ++numEdgesCreated;
00216 }
00217 }
00218 }
00219
00220
00221 map < const Hypothesis*, set < const Hypothesis* > >::const_iterator outgoingIt = outgoingHyps.find(currHyp);
00222
00223 if (outgoingIt != outgoingHyps.end()) {
00224 const set<const Hypothesis*> & outHyps = outgoingIt->second;
00225 for (set<const Hypothesis*>::const_iterator outHypIts = outHyps.begin(); outHypIts != outHyps.end(); ++outHypIts) {
00226 const Hypothesis* succHyp = *outHypIts;
00227
00228 if (survivingHyps.find(succHyp) == survivingHyps.end())
00229 continue;
00230
00231
00232 if (succHyp->GetPrevHypo() == currHyp) {
00233 vector <Edge>& succEdges = incomingEdges[succHyp];
00234 Edge succWinningEdge(currHyp, succHyp, scale*(succHyp->GetScore() - currHyp->GetScore()), succHyp->GetCurrTargetPhrase());
00235 succEdges.push_back(succWinningEdge);
00236 survivingHyps.insert(succHyp);
00237 ++numEdgesCreated;
00238 }
00239
00240
00241 const ArcList *arcList = succHyp->GetArcList();
00242 if (arcList != NULL) {
00243 ArcList::const_iterator iterArcList;
00244
00245 for (iterArcList = arcList->begin() ; iterArcList != arcList->end() ; ++iterArcList) {
00246 const Hypothesis *loserHypo = *iterArcList;
00247 const Hypothesis* loserPrevHypo = loserHypo->GetPrevHypo();
00248 if (loserPrevHypo == currHyp) {
00249 vector <Edge>& succEdges = incomingEdges[succHyp];
00250 double arcScore = loserHypo->GetScore() - currHyp->GetScore();
00251 Edge losingEdge(currHyp, succHyp,scale* arcScore, loserHypo->GetCurrTargetPhrase());
00252 succEdges.push_back(losingEdge);
00253 ++numEdgesCreated;
00254 }
00255 }
00256 }
00257 }
00258 }
00259 }
00260
00261 connectedHyp.clear();
00262 for (set <const Hypothesis*>::iterator it = survivingHyps.begin(); it != survivingHyps.end(); ++it) {
00263 connectedHyp.push_back(*it);
00264 }
00265
00266 VERBOSE(2, "Done! Num edges created : "<< numEdgesCreated << ", numEdges wanted " << numEdgesTotal << endl)
00267
00268 IFVERBOSE(3) {
00269 cerr << "Surviving hyps: " ;
00270 for (set <const Hypothesis*>::iterator it = survivingHyps.begin(); it != survivingHyps.end(); ++it) {
00271 cerr << (*it)->GetId() << " ";
00272 }
00273 cerr << endl;
00274 }
00275
00276
00277 }
00278
00279 void calcNgramExpectations(Lattice & connectedHyp, map<const Hypothesis*, vector<Edge> >& incomingEdges,
00280 map<Phrase, float>& finalNgramScores, bool posteriors)
00281 {
00282
00283 sort(connectedHyp.begin(),connectedHyp.end(),ascendingCoverageCmp);
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295 map<const Hypothesis*, float> forwardScore;
00296 forwardScore[connectedHyp[0]] = 0.0f;
00297 set< const Hypothesis *> finalHyps;
00298
00299 NgramScores ngramScores;
00300
00301 for (size_t i = 1; i < connectedHyp.size(); ++i) {
00302 const Hypothesis* currHyp = connectedHyp[i];
00303 if (currHyp->GetWordsBitmap().IsComplete()) {
00304 finalHyps.insert(currHyp);
00305 }
00306
00307 VERBOSE(3, "Processing hyp: " << currHyp->GetId() << ", num words cov= " << currHyp->GetWordsBitmap().GetNumWordsCovered() << endl)
00308
00309 vector <Edge> & edges = incomingEdges[currHyp];
00310 for (size_t e = 0; e < edges.size(); ++e) {
00311 const Edge& edge = edges[e];
00312 if (forwardScore.find(currHyp) == forwardScore.end()) {
00313 forwardScore[currHyp] = forwardScore[edge.GetTailNode()] + edge.GetScore();
00314 VERBOSE(3, "Fwd score["<<currHyp->GetId()<<"] = fwdScore["<<edge.GetTailNode()->GetId() << "] + edge Score: " << edge.GetScore() << endl)
00315 } else {
00316 forwardScore[currHyp] = log_sum(forwardScore[currHyp], forwardScore[edge.GetTailNode()] + edge.GetScore());
00317 VERBOSE(3, "Fwd score["<<currHyp->GetId()<<"] += fwdScore["<<edge.GetTailNode()->GetId() << "] + edge Score: " << edge.GetScore() << endl)
00318 }
00319 }
00320
00321
00322 for (size_t j =0 ; j < edges.size(); ++j) {
00323 Edge& edge = edges[j];
00324 const NgramHistory & incomingPhrases = edge.GetNgrams(incomingEdges);
00325
00326
00327 for (NgramHistory::const_iterator it = incomingPhrases.begin(); it != incomingPhrases.end(); ++it) {
00328 const Phrase& ngram = it->first;
00329 const PathCounts& pathCounts = it->second;
00330 VERBOSE(4, "Calculating score for: " << it->first << endl)
00331
00332 for (PathCounts::const_iterator pathCountIt = pathCounts.begin(); pathCountIt != pathCounts.end(); ++pathCountIt) {
00333
00334 const Path& path = pathCountIt->first;
00335
00336 float score = forwardScore[path[0]->GetTailNode()];
00337 for (size_t i = 0; i < path.size(); ++i) {
00338 score += path[i]->GetScore();
00339 }
00340
00341
00342 size_t count = posteriors ? 1 : pathCountIt->second;
00343 for (size_t k = 0; k < count; ++k) {
00344 ngramScores.addScore(currHyp,ngram,score);
00345 }
00346 }
00347 }
00348
00349
00350 for (NgramScores::NodeScoreIterator it = ngramScores.nodeBegin(edge.GetTailNode());
00351 it != ngramScores.nodeEnd(edge.GetTailNode()); ++it) {
00352 const Phrase & currNgram = *(it->first);
00353 float currNgramScore = it->second;
00354 VERBOSE(4, "Calculating score for: " << currNgram << endl)
00355
00356
00357 if (!posteriors || incomingPhrases.find(currNgram) == incomingPhrases.end()) {
00358 float score = edge.GetScore() + currNgramScore;
00359 ngramScores.addScore(currHyp,currNgram,score);
00360 }
00361 }
00362
00363 }
00364 }
00365
00366 float Z = 9999999;
00367
00368
00369 for (set< const Hypothesis *>::iterator finalHyp = finalHyps.begin(); finalHyp != finalHyps.end(); ++finalHyp) {
00370 const Hypothesis* hyp = *finalHyp;
00371
00372 for (NgramScores::NodeScoreIterator it = ngramScores.nodeBegin(hyp); it != ngramScores.nodeEnd(hyp); ++it) {
00373 const Phrase& ngram = *(it->first);
00374 if (finalNgramScores.find(ngram) == finalNgramScores.end()) {
00375 finalNgramScores[ngram] = it->second;
00376 } else {
00377 finalNgramScores[ngram] = log_sum(it->second, finalNgramScores[ngram]);
00378 }
00379 }
00380
00381 if (Z == 9999999) {
00382 Z = forwardScore[hyp];
00383 } else {
00384 Z = log_sum(Z, forwardScore[hyp]);
00385 }
00386 }
00387
00388
00389
00390 for (map<Phrase, float>::iterator finalScoresIt = finalNgramScores.begin(); finalScoresIt != finalNgramScores.end(); ++finalScoresIt) {
00391 finalScoresIt->second = finalScoresIt->second - Z;
00392 IFVERBOSE(2) {
00393 VERBOSE(2,finalScoresIt->first << " [" << finalScoresIt->second << "]" << endl);
00394 }
00395 }
00396
00397 }
00398
00399 const NgramHistory& Edge::GetNgrams(map<const Hypothesis*, vector<Edge> > & incomingEdges)
00400 {
00401
00402 if (m_ngrams.size() > 0)
00403 return m_ngrams;
00404
00405 const Phrase& currPhrase = GetWords();
00406
00407 for (size_t start = 0; start < currPhrase.GetSize(); ++start) {
00408 for (size_t end = start; end < start + bleu_order; ++end) {
00409 if (end < currPhrase.GetSize()) {
00410 Phrase edgeNgram(end-start+1);
00411 for (size_t index = start; index <= end; ++index) {
00412 edgeNgram.AddWord(currPhrase.GetWord(index));
00413 }
00414
00415 vector<const Edge*> edgeHistory;
00416 edgeHistory.push_back(this);
00417 storeNgramHistory(edgeNgram, edgeHistory);
00418 } else {
00419 break;
00420 }
00421 }
00422 }
00423
00424 map<const Hypothesis*, vector<Edge> >::iterator it = incomingEdges.find(m_tailNode);
00425 if (it != incomingEdges.end()) {
00426 vector<Edge> & inEdges = it->second;
00427
00428 for (vector<Edge>::iterator edge = inEdges.begin(); edge != inEdges.end(); ++edge) {
00429 const NgramHistory & edgeIncomingNgrams = edge->GetNgrams(incomingEdges);
00430 for (NgramHistory::const_iterator edgeInNgramHist = edgeIncomingNgrams.begin(); edgeInNgramHist != edgeIncomingNgrams.end(); ++edgeInNgramHist) {
00431 const Phrase& edgeIncomingNgram = edgeInNgramHist->first;
00432 const PathCounts & edgeIncomingNgramPaths = edgeInNgramHist->second;
00433 size_t back = min(edgeIncomingNgram.GetSize(), edge->GetWordsSize());
00434 const Phrase& edgeWords = edge->GetWords();
00435 IFVERBOSE(3) {
00436 cerr << "Edge: "<< *edge <<endl;
00437 cerr << "edgeWords: " << edgeWords << endl;
00438 cerr << "edgeInNgram: " << edgeIncomingNgram << endl;
00439 }
00440
00441 Phrase edgeSuffix(ARRAY_SIZE_INCR);
00442 Phrase ngramSuffix(ARRAY_SIZE_INCR);
00443 GetPhraseSuffix(edgeWords,back,edgeSuffix);
00444 GetPhraseSuffix(edgeIncomingNgram,back,ngramSuffix);
00445
00446 if (ngramSuffix == edgeSuffix) {
00447 size_t edgeInNgramSize = edgeIncomingNgram.GetSize();
00448
00449 for (size_t i = 0; i < GetWordsSize() && i + edgeInNgramSize < bleu_order ; ++i) {
00450 Phrase newNgram(edgeIncomingNgram);
00451 for (size_t j = 0; j <= i ; ++j) {
00452 newNgram.AddWord(GetWords().GetWord(j));
00453 }
00454 VERBOSE(3, "Inserting New Phrase : " << newNgram << endl)
00455
00456 for (PathCounts::const_iterator pathIt = edgeIncomingNgramPaths.begin(); pathIt != edgeIncomingNgramPaths.end(); ++pathIt) {
00457 Path newNgramPath = pathIt->first;
00458 newNgramPath.push_back(this);
00459 storeNgramHistory(newNgram, newNgramPath, pathIt->second);
00460 }
00461 }
00462 }
00463 }
00464 }
00465 }
00466 return m_ngrams;
00467 }
00468
00469
00470 void Edge::GetPhraseSuffix(const Phrase& origPhrase, size_t lastN, Phrase& targetPhrase) const
00471 {
00472 size_t origSize = origPhrase.GetSize();
00473 size_t startIndex = origSize - lastN;
00474 for (size_t index = startIndex; index < origPhrase.GetSize(); ++index) {
00475 targetPhrase.AddWord(origPhrase.GetWord(index));
00476 }
00477 }
00478
00479 bool Edge::operator< (const Edge& compare ) const
00480 {
00481 if (m_headNode->GetId() < compare.m_headNode->GetId())
00482 return true;
00483 if (compare.m_headNode->GetId() < m_headNode->GetId())
00484 return false;
00485 if (m_tailNode->GetId() < compare.m_tailNode->GetId())
00486 return true;
00487 if (compare.m_tailNode->GetId() < m_tailNode->GetId())
00488 return false;
00489 return GetScore() < compare.GetScore();
00490 }
00491
00492 ostream& operator<< (ostream& out, const Edge& edge)
00493 {
00494 out << "Head: " << edge.m_headNode->GetId() << ", Tail: " << edge.m_tailNode->GetId() << ", Score: " << edge.m_score << ", Phrase: " << edge.m_targetPhrase << endl;
00495 return out;
00496 }
00497
00498 bool ascendingCoverageCmp(const Hypothesis* a, const Hypothesis* b)
00499 {
00500 return a->GetWordsBitmap().GetNumWordsCovered() < b->GetWordsBitmap().GetNumWordsCovered();
00501 }
00502
00503 void getLatticeMBRNBest(Manager& manager, TrellisPathList& nBestList,
00504 vector<LatticeMBRSolution>& solutions, size_t n)
00505 {
00506 const StaticData& staticData = StaticData::Instance();
00507 std::map < int, bool > connected;
00508 std::vector< const Hypothesis *> connectedList;
00509 map<Phrase, float> ngramPosteriors;
00510 std::map < const Hypothesis*, set <const Hypothesis*> > outgoingHyps;
00511 map<const Hypothesis*, vector<Edge> > incomingEdges;
00512 vector< float> estimatedScores;
00513 manager.GetForwardBackwardSearchGraph(&connected, &connectedList, &outgoingHyps, &estimatedScores);
00514 pruneLatticeFB(connectedList, outgoingHyps, incomingEdges, estimatedScores, manager.GetBestHypothesis(), staticData.GetLatticeMBRPruningFactor(),staticData.GetMBRScale());
00515 calcNgramExpectations(connectedList, incomingEdges, ngramPosteriors,true);
00516
00517 vector<float> mbrThetas = staticData.GetLatticeMBRThetas();
00518 float p = staticData.GetLatticeMBRPrecision();
00519 float r = staticData.GetLatticeMBRPRatio();
00520 float mapWeight = staticData.GetLatticeMBRMapWeight();
00521 if (mbrThetas.size() == 0) {
00522 mbrThetas.push_back(-1);
00523 mbrThetas.push_back(1/(bleu_order*p));
00524 for (size_t i = 2; i <= bleu_order; ++i) {
00525 mbrThetas.push_back(mbrThetas[i-1] / r);
00526 }
00527 }
00528 IFVERBOSE(2) {
00529 VERBOSE(2,"Thetas: ");
00530 for (size_t i = 0; i < mbrThetas.size(); ++i) {
00531 VERBOSE(2,mbrThetas[i] << " ");
00532 }
00533 VERBOSE(2,endl);
00534 }
00535 TrellisPathList::const_iterator iter;
00536 size_t ctr = 0;
00537 LatticeMBRSolutionComparator comparator;
00538 for (iter = nBestList.begin() ; iter != nBestList.end() ; ++iter, ++ctr) {
00539 const TrellisPath &path = **iter;
00540 solutions.push_back(LatticeMBRSolution(path,iter==nBestList.begin()));
00541 solutions.back().CalcScore(ngramPosteriors,mbrThetas,mapWeight);
00542 sort(solutions.begin(), solutions.end(), comparator);
00543 while (solutions.size() > n) {
00544 solutions.pop_back();
00545 }
00546 }
00547 VERBOSE(2,"LMBR Score: " << solutions[0].GetScore() << endl);
00548 }
00549
00550 vector<Word> doLatticeMBR(Manager& manager, TrellisPathList& nBestList)
00551 {
00552
00553 vector<LatticeMBRSolution> solutions;
00554 getLatticeMBRNBest(manager, nBestList, solutions,1);
00555 return solutions.at(0).GetWords();
00556 }
00557
00558 const TrellisPath doConsensusDecoding(Manager& manager, TrellisPathList& nBestList)
00559 {
00560 static const int BLEU_ORDER = 4;
00561 static const float SMOOTH = 1;
00562
00563
00564 const StaticData& staticData = StaticData::Instance();
00565 std::map < int, bool > connected;
00566 std::vector< const Hypothesis *> connectedList;
00567 map<Phrase, float> ngramExpectations;
00568 std::map < const Hypothesis*, set <const Hypothesis*> > outgoingHyps;
00569 map<const Hypothesis*, vector<Edge> > incomingEdges;
00570 vector< float> estimatedScores;
00571 manager.GetForwardBackwardSearchGraph(&connected, &connectedList, &outgoingHyps, &estimatedScores);
00572 pruneLatticeFB(connectedList, outgoingHyps, incomingEdges, estimatedScores, manager.GetBestHypothesis(), staticData.GetLatticeMBRPruningFactor(),staticData.GetMBRScale());
00573 calcNgramExpectations(connectedList, incomingEdges, ngramExpectations,false);
00574
00575
00576
00577 float ref_length = 0.0f;
00578 for (map<Phrase,float>::const_iterator ref_iter = ngramExpectations.begin();
00579 ref_iter != ngramExpectations.end(); ++ref_iter) {
00580
00581
00582 if (ref_iter->first.GetSize() == 1) {
00583 ref_length += exp(ref_iter->second);
00584
00585 }
00586 }
00587
00588 VERBOSE(2,"REF Length: " << ref_length << endl);
00589
00590
00591 TrellisPathList::const_iterator iter;
00592 TrellisPathList::const_iterator best = nBestList.end();
00593 float bestScore = -100000;
00594
00595 for (iter = nBestList.begin() ; iter != nBestList.end() ; ++iter) {
00596 const TrellisPath &path = **iter;
00597 vector<Word> words;
00598 map<Phrase,int> ngrams;
00599 GetOutputWords(path,words);
00600
00601
00602
00603
00604
00605 extract_ngrams(words,ngrams);
00606
00607 vector<float> comps(2*BLEU_ORDER+1);
00608 float logbleu = 0.0;
00609 float brevity = 0.0;
00610 int hyp_length = words.size();
00611 for (int i = 0; i < BLEU_ORDER; ++i) {
00612 comps[2*i] = 0.0;
00613 comps[2*i+1] = max(hyp_length-i,0);
00614 }
00615
00616 for (map<Phrase,int>::const_iterator hyp_iter = ngrams.begin();
00617 hyp_iter != ngrams.end(); ++hyp_iter) {
00618 map<Phrase,float>::const_iterator ref_iter = ngramExpectations.find(hyp_iter->first);
00619 if (ref_iter != ngramExpectations.end()) {
00620 comps[2*(hyp_iter->first.GetSize()-1)] += min(exp(ref_iter->second), (float)(hyp_iter->second));
00621 }
00622
00623 }
00624 comps[comps.size()-1] = ref_length;
00625
00626
00627
00628
00629
00630
00631 float score = 0.0f;
00632 if (comps[0] != 0) {
00633 for (int i=0; i<BLEU_ORDER; i++) {
00634 if ( i > 0 ) {
00635 logbleu += log((float)comps[2*i]+SMOOTH)-log((float)comps[2*i+1]+SMOOTH);
00636 } else {
00637 logbleu += log((float)comps[2*i])-log((float)comps[2*i+1]);
00638 }
00639 }
00640 logbleu /= BLEU_ORDER;
00641 brevity = 1.0-(float)comps[comps.size()-1]/comps[1];
00642 if (brevity < 0.0) {
00643 logbleu += brevity;
00644 }
00645 score = exp(logbleu);
00646 }
00647
00648
00649 if (score > bestScore) {
00650 bestScore = score;
00651 best = iter;
00652 VERBOSE(2,"NEW BEST: " << score << endl);
00653
00654
00655
00656
00657 }
00658 }
00659
00660 assert (best != nBestList.end());
00661 return **best;
00662
00663
00664
00665 }
00666
00667 }
00668
00669