mosesdecoder/moses/ScoreComponentCollection.h

488 lines
16 KiB
C
Raw Permalink Normal View History

// -*- mode: c++; indent-tabs-mode: nil; tab-width:2 -*-
/***********************************************************************
Moses - factored phrase-based language decoder
Copyright (C) 2006 University of Edinburgh
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
***********************************************************************/
#ifndef moses_ScoreComponentCollection_h
#define moses_ScoreComponentCollection_h
#include <numeric>
#include <sstream>
#ifdef MPI_ENABLE
#include <boost/serialization/access.hpp>
#include <boost/serialization/split_member.hpp>
#endif
2013-05-24 21:02:49 +04:00
#include "moses/FF/FeatureFunction.h"
#include "FeatureVector.h"
#include "TypeDef.h"
#include "Util.h"
2014-01-13 18:37:05 +04:00
#include "util/exception.hh"
namespace Moses
{
2013-09-08 17:57:31 +04:00
/**
* Smaller version for just 1 FF.
*/
2013-09-27 12:35:24 +04:00
struct ScorePair {
friend std::ostream& operator<<(std::ostream& os, const ScorePair& rhs);
std::vector<float> denseScores;
std::map<StringPiece, float> sparseScores;
2015-01-14 14:07:42 +03:00
ScorePair() {
}
2013-09-27 12:35:24 +04:00
ScorePair(const std::vector<float> &other)
2015-01-14 14:07:42 +03:00
:denseScores(other) {
}
2013-09-27 12:35:24 +04:00
void PlusEquals(const ScorePair &other);
void PlusEquals(const StringPiece &key, float value);
void PlusEquals(const std::vector<float> &other) {
UTIL_THROW_IF2(denseScores.size() != other.size(), "Number of scores incorrect");
2013-09-27 12:35:24 +04:00
std::transform(denseScores.begin(),
denseScores.end(),
other.begin(),
denseScores.begin(),
std::plus<float>());
}
2013-09-08 17:57:31 +04:00
};
/*** An unweighted collection of scores for a translation or step in a translation.
*
* In the factored phrase-based models that are implemented by moses, there are a set of
* scores that come from a variety of sources (translation probabilities, language model
* probablilities, distortion probabilities, generation probabilities). Furthermore, while
* some of these scores may be 0, this number is fixed (and generally quite small, ie, less
* than 15), for a given model.
*
* The values contained in ScoreComponentCollection objects are unweighted scores (log-probs).
*
* ScoreComponentCollection objects can be added and subtracted, which makes them appropriate
* to be the datatype used to return the result of a score computations (in this case they will
* have most values set to zero, except for the ones that are results of the indivudal computation
* this will then be added into the "running total" in the Hypothesis. In fact, for a score
* to be tracked in the hypothesis (and thus to participate in the decoding process), a class
* representing that score must extend the ScoreProducer abstract base class. For an example
* refer to the DistortionScoreProducer class.
*/
class ScoreComponentCollection
{
friend std::ostream& operator<<(std::ostream& os, const ScoreComponentCollection& rhs);
2013-08-22 13:16:24 +04:00
friend void swap(ScoreComponentCollection &first, ScoreComponentCollection &second);
2015-11-02 03:00:37 +03:00
private:
2013-05-29 21:16:15 +04:00
FVector m_scores;
2013-08-22 13:16:24 +04:00
public:
// typedef std::pair<size_t,size_t> IndexPair;
private:
// typedef std::map<const FeatureFunction*,IndexPair> ScoreIndexMap;
// static ScoreIndexMap s_scoreIndexes;
2011-11-09 21:16:02 +04:00
static size_t s_denseVectorSize;
public:
// static IndexPair GetIndexes(const FeatureFunction* sp) {
// ScoreIndexMap::const_iterator indexIter = s_scoreIndexes.find(sp);
// if (indexIter == s_scoreIndexes.end()) {
// std::stringstream strme;
// strme << "ERROR: FeatureFunction: " << sp->GetScoreProducerDescription() <<
// " not registered with ScoreIndexMap" << std::endl;
// strme << "You must call ScoreComponentCollection.RegisterScoreProducer() " <<
// " for every FeatureFunction" << std::endl;
// UTIL_THROW2(strme.str());
// }
// return indexIter->second;
// }
public:
static void ResetCounter() {
s_denseVectorSize = 0;
}
//! Create a new score collection with all values set to 0.0
ScoreComponentCollection();
//! Clone a score collection
2013-05-29 21:16:15 +04:00
ScoreComponentCollection(const ScoreComponentCollection& rhs)
: m_scores(rhs.m_scores) {
}
ScoreComponentCollection& operator=( const ScoreComponentCollection& rhs ) {
m_scores = rhs.m_scores;
return *this;
}
2011-11-09 21:16:02 +04:00
/**
2013-05-29 21:16:15 +04:00
* Register a ScoreProducer with a fixed number of scores, so that it can
2011-11-09 21:16:02 +04:00
* be allocated space in the dense part of the feature vector.
**/
static void RegisterScoreProducer(FeatureFunction* scoreProducer);
2011-11-09 21:16:02 +04:00
/** Load from file */
2013-05-29 21:16:15 +04:00
bool Load(const std::string& filename) {
return m_scores.load(filename);
}
2013-05-29 21:16:15 +04:00
const FVector& GetScoresVector() const {
return m_scores;
}
const std::valarray<FValue> &getCoreFeatures() const {
return m_scores.getCoreFeatures();
}
2013-05-29 21:16:15 +04:00
size_t Size() const {
return m_scores.size();
}
2013-05-29 21:16:15 +04:00
void Resize() {
2011-11-09 21:16:02 +04:00
if (m_scores.coreSize() != s_denseVectorSize) {
m_scores.resize(s_denseVectorSize);
}
}
/** Create and FVector with the right number of core features */
2013-05-29 21:16:15 +04:00
static FVector CreateFVector() {
2011-11-09 21:16:02 +04:00
return FVector(s_denseVectorSize);
}
2013-05-29 21:16:15 +04:00
void SetToBinaryOf(const ScoreComponentCollection& rhs) {
m_scores.setToBinaryOf(rhs.m_scores);
}
//! Set all values to 0.0
2013-05-29 21:16:15 +04:00
void ZeroAll() {
m_scores.clear();
}
void MultiplyEquals(float scalar);
void DivideEquals(float scalar);
void CoreDivideEquals(float scalar);
void DivideEquals(const ScoreComponentCollection& rhs);
void MultiplyEquals(const ScoreComponentCollection& rhs);
void MultiplyEqualsBackoff(const ScoreComponentCollection& rhs, float backoff);
void MultiplyEquals(float core_r0, float sparse_r0);
void MultiplyEquals(const FeatureFunction* sp, float scalar);
size_t GetNumberWeights(const FeatureFunction* sp);
void CoreAssign(const ScoreComponentCollection& rhs) {
m_scores.coreAssign(rhs.m_scores);
}
//! add the score in rhs
void PlusEquals(const ScoreComponentCollection& rhs) {
m_scores += rhs.m_scores;
}
// add only sparse features
void SparsePlusEquals(const ScoreComponentCollection& rhs) {
m_scores.sparsePlusEquals(rhs.m_scores);
}
2015-01-07 17:25:43 +03:00
// add only core features
void CorePlusEquals(const ScoreComponentCollection& rhs) {
m_scores.corePlusEquals(rhs.m_scores);
}
2013-05-29 21:16:15 +04:00
void PlusEquals(const FVector& scores) {
m_scores += scores;
}
//! subtract the score in rhs
void MinusEquals(const ScoreComponentCollection& rhs) {
m_scores -= rhs.m_scores;
}
//For features which have an unbounded number of components
2013-05-29 21:16:15 +04:00
void MinusEquals(const FeatureFunction*sp, const std::string& name, float score) {
FName fname(sp->GetScoreProducerDescription(),name);
m_scores[fname] -= score;
}
2011-12-16 23:53:46 +04:00
//For features which have an unbounded number of components
2013-05-29 21:16:15 +04:00
void SparseMinusEquals(const std::string& full_name, float score) {
2011-12-16 23:53:46 +04:00
FName fname(full_name);
m_scores[fname] -= score;
}
2013-05-29 21:16:15 +04:00
//! Add scores from a single ScoreProducer only
//! The length of scores must be equal to the number of score components
//! produced by sp
void
PlusEquals(const FeatureFunction* sp,
2015-05-02 13:45:24 +03:00
const ScoreComponentCollection& scores) {
size_t i = sp->GetIndex();
size_t stop = i + sp->GetNumScoreComponents();
2015-05-02 13:45:24 +03:00
for (; i < stop; ++i) m_scores[i] += scores.m_scores[i];
2013-05-29 21:16:15 +04:00
}
Feature function overhaul. Each feature function is computed in one of three ways: 1) Stateless feature functions from the phrase table/generation table: these are computed when the TranslationOption is created. They become part of the ScoreBreakdown object contained in the TranslationOption and are added to the feature value vector when a hypothesis is extended. 2) Stateless feature functions that are computed during state exploration. Currently, only WordPenalty falls into this category, but these functions implement a method Evaluate which do does not receive a Hypothesis or any contextual information. 3) Stateful feature functions: these features receive the arc information (translation option), compute some value and then return some context information. The context information created by a particular feature function is passed back to it as the previous context when a hypothesis originating at the node where the previous edge terminates is created. States in the search space may be recombined if the context information is identical. The context information must be stored in an object implementing the FFState interface. TODO: 1) the command line interface / MERT interface needs to go to named parameters that are otherwise opaque 2) StatefulFeatureFunction's Evaluate method should just take a TranslationOption and a context object. It is not good that it takes a hypothesis, because then people may be tempted to access information about the "previous" hypothesis without "declaring" this dependency. 3) Future cost estimates should be handled using feature functions. All stateful feature functions need some kind of future cost estimate. 4) Philipp's poor-man's cube pruning is broken. git-svn-id: https://mosesdecoder.svn.sourceforge.net/svnroot/mosesdecoder/trunk@2087 1f5c12ca-751b-0410-a591-d2e778427230
2009-02-06 18:43:06 +03:00
2013-05-29 21:16:15 +04:00
//! Add scores from a single FeatureFunction only
//! The length of scores must be equal to the number of score components
//! produced by sp
void PlusEquals(const FeatureFunction* sp, const std::vector<float>& scores) {
UTIL_THROW_IF2(scores.size() != sp->GetNumScoreComponents(),
2014-01-15 19:42:02 +04:00
"Number of scores is incorrect");
size_t offset = sp->GetIndex();
for (size_t i = 0; i < scores.size(); ++i) {
m_scores[i + offset] += scores[i];
}
}
2016-10-06 17:14:56 +03:00
void PlusEquals(const FeatureFunction* sp, float scores[]) {
2016-10-05 17:15:47 +03:00
size_t numScores = sp->GetNumScoreComponents();
size_t offset = sp->GetIndex();
for (size_t i = 0; i < numScores; ++i) {
m_scores[i + offset] += scores[i];
}
}
2013-05-29 21:16:15 +04:00
//! Special version PlusEquals(ScoreProducer, vector<float>)
//! to add the score from a single ScoreProducer that produces
//! a single value
void PlusEquals(const FeatureFunction* sp, float score) {
UTIL_THROW_IF2(sp->GetNumScoreComponents() != 1,
2014-01-15 19:42:02 +04:00
"Number of scores is incorrect");
m_scores[sp->GetIndex()] += score;
2013-05-29 21:16:15 +04:00
}
2013-04-29 21:46:48 +04:00
//For features which have an unbounded number of components
2013-05-29 21:16:15 +04:00
void PlusEquals(const FeatureFunction*sp, const StringPiece& name, float score) {
FName fname(sp->GetScoreProducerDescription(),name);
m_scores[fname] += score;
}
2013-09-08 17:57:31 +04:00
void PlusEquals(const FeatureFunction* sp, const ScorePair &scorePair);
2014-08-08 00:42:30 +04:00
// Add score by index
void PlusEquals(size_t index, float score) {
m_scores[index] += score;
}
2011-12-16 23:53:46 +04:00
//For features which have an unbounded number of components
2013-05-29 21:16:15 +04:00
void SparsePlusEquals(const std::string& full_name, float score) {
FName fname(full_name);
2011-12-16 23:53:46 +04:00
m_scores[fname] += score;
}
void SparsePlusEquals(const FName& fname, float score) {
m_scores[fname] += score;
}
2013-09-10 17:36:21 +04:00
void Assign(const FeatureFunction* sp, const std::vector<float>& scores);
2013-05-29 21:16:15 +04:00
void Assign(const FeatureFunction* sp, size_t idx, float sc);
//! Special version Assign(ScoreProducer, vector<float>)
//! to add the score from a single ScoreProducer that produces
//! a single value
2013-05-29 21:16:15 +04:00
void Assign(const FeatureFunction* sp, float score) {
UTIL_THROW_IF2(sp->GetNumScoreComponents() != 1,
2014-01-15 19:42:02 +04:00
"Feature function must must only contain 1 score");
m_scores[sp->GetIndex()] = score;
}
2013-05-29 21:16:15 +04:00
2014-08-08 00:42:30 +04:00
// Assign score by index
void Assign(size_t index, float score) {
m_scores[index] = score;
}
2011-12-09 13:30:48 +04:00
2013-05-29 21:16:15 +04:00
void Assign(const FeatureFunction*sp, const StringPiece &name, float score) {
FName fname(sp->GetScoreProducerDescription(),name);
m_scores[fname] = score;
}
2011-12-09 13:30:48 +04:00
//Read sparse features from string
2014-06-06 23:35:58 +04:00
void Assign(const FeatureFunction* sp, const std::string &line);
// shortcut: setting the value directly using the feature name
2013-05-29 21:16:15 +04:00
void Assign(const std::string name, float score) {
FName fname(name);
m_scores[fname] = score;
}
float InnerProduct(const ScoreComponentCollection& rhs) const {
return m_scores.inner_product(rhs.m_scores);
}
float PartialInnerProduct(const FeatureFunction* sp, const std::vector<float>& rhs) const {
std::vector<float> lhs = GetScoresForProducer(sp);
UTIL_THROW_IF2(lhs.size() != rhs.size(),
2014-01-15 19:42:02 +04:00
"Number of weights must match number of scores");
2013-05-29 21:16:15 +04:00
return std::inner_product(lhs.begin(), lhs.end(), rhs.begin(), 0.0f);
}
//! return a vector of all the scores associated with a certain FeatureFunction
std::vector<float> GetScoresForProducer(const FeatureFunction* sp) const {
size_t components = sp->GetNumScoreComponents();
std::vector<float> res(components);
size_t offset = sp->GetIndex();
2011-11-09 21:16:02 +04:00
for (size_t i = 0; i < res.size(); ++i) {
res[i] = m_scores[i + offset];
}
return res;
2013-05-29 21:16:15 +04:00
}
//! get subset of scores that belong to a certain sparse ScoreProducer
FVector GetVectorForProducer(const FeatureFunction* sp) const;
2013-05-29 21:16:15 +04:00
float GetSparseWeight(const FName& featureName) const {
return m_scores[featureName];
}
2013-05-29 21:16:15 +04:00
void PrintCoreFeatures() {
m_scores.printCoreFeatures();
}
2013-05-29 21:16:15 +04:00
void ThresholdScaling(float maxValue) {
// find (smallest) factor for which all weights are <= maxValue
// 0.1 / 0.14 = 0.714285714
// 0.1 / 0.17 = 0.588235294
m_scores.thresholdScale(maxValue);
2013-05-29 21:16:15 +04:00
}
void CapMax(float maxValue) {
// cap all sparse features to maxValue
m_scores.capMax(maxValue);
}
void CapMin(float minValue) {
// cap all sparse features to minValue
m_scores.capMin(minValue);
}
// std::pair<size_t,size_t> GetIndexesForProducer(const FeatureFunction* sp) const {
// IndexPair indexPair = GetIndexes(sp);
// return indexPair;
// }
2014-08-08 00:42:30 +04:00
2013-05-29 21:16:15 +04:00
//! if a FeatureFunction produces a single score (for example, a language model score)
//! this will return it. If not, this method will throw
float GetScoreForProducer(const FeatureFunction* sp) const {
UTIL_THROW_IF2(sp->GetNumScoreComponents() != 1,
2014-01-15 19:42:02 +04:00
"Feature function must must only contain 1 score");
return m_scores[sp->GetIndex()];
2013-05-29 21:16:15 +04:00
}
//For features which have an unbounded number of components
float GetScoreForProducer
2013-05-29 21:16:15 +04:00
(const FeatureFunction* sp, const std::string& name) const {
FName fname(sp->GetScoreProducerDescription(),name);
return m_scores[fname];
}
2013-05-29 21:16:15 +04:00
float GetWeightedScore() const;
void ZeroDenseFeatures(const FeatureFunction* sp);
void InvertDenseFeatures(const FeatureFunction* sp);
void L1Normalise();
2011-11-16 15:49:31 +04:00
float GetL1Norm() const;
float GetL2Norm() const;
float GetLInfNorm() const;
size_t L1Regularize(float lambda);
void L2Regularize(float lambda);
size_t SparseL1Regularize(float lambda);
void SparseL2Regularize(float lambda);
2011-11-16 15:49:31 +04:00
void Save(const std::string& filename) const;
void Save(std::ostream&, bool multiline=true) const;
2013-05-29 21:16:15 +04:00
void IncrementSparseHopeFeatures() {
m_scores.incrementSparseHopeFeatures();
}
void IncrementSparseFearFeatures() {
m_scores.incrementSparseFearFeatures();
}
void PrintSparseHopeFeatureCounts(std::ofstream& out) {
m_scores.printSparseHopeFeatureCounts(out);
}
void PrintSparseFearFeatureCounts(std::ofstream& out) {
m_scores.printSparseFearFeatureCounts(out);
}
void PrintSparseHopeFeatureCounts() {
m_scores.printSparseHopeFeatureCounts();
}
void PrintSparseFearFeatureCounts() {
m_scores.printSparseFearFeatureCounts();
}
size_t PruneSparseFeatures(size_t threshold) {
return m_scores.pruneSparseFeatures(threshold);
}
size_t PruneZeroWeightFeatures() {
return m_scores.pruneZeroWeightFeatures();
}
void UpdateConfidenceCounts(ScoreComponentCollection &weightUpdate, bool signedCounts) {
m_scores.updateConfidenceCounts(weightUpdate.m_scores, signedCounts);
}
void UpdateLearningRates(float decay_core, float decay_sparse, ScoreComponentCollection &confidenceCounts, float core_r0, float sparse_r0) {
m_scores.updateLearningRates(decay_core, decay_sparse, confidenceCounts.m_scores, core_r0, sparse_r0);
}
void Merge(const ScoreComponentCollection &other) {
m_scores.merge(other.m_scores);
}
void OutputAllFeatureScores(std::ostream &out, bool with_labels) const;
void OutputFeatureScores(std::ostream& out, Moses::FeatureFunction const* ff,
2015-11-02 03:00:37 +03:00
std::string &lastName, bool with_labels) const;
2014-12-30 16:23:30 +03:00
#ifdef MPI_ENABLE
2013-05-29 21:16:15 +04:00
public:
friend class boost::serialization::access;
2013-05-29 21:16:15 +04:00
private:
//serialization
template<class Archive>
void save(Archive &ar, const unsigned int version) const {
ar << m_scores;
}
template<class Archive>
void load(Archive &ar, const unsigned int version) {
ar >> m_scores;
}
BOOST_SERIALIZATION_SPLIT_MEMBER()
#endif
};
struct SCCPlus {
ScoreComponentCollection operator()
2013-05-29 21:16:15 +04:00
(const ScoreComponentCollection& lhs,
const ScoreComponentCollection& rhs) {
ScoreComponentCollection sum(lhs);
sum.PlusEquals(rhs);
return sum;
}
};
2013-08-23 16:53:30 +04:00
inline void swap(ScoreComponentCollection &first, ScoreComponentCollection &second)
{
2013-08-22 13:16:24 +04:00
swap(first.m_scores, second.m_scores);
}
}
#endif