2008-05-14 15:00:59 +04:00
|
|
|
#include <cassert>
|
|
|
|
#include <vector>
|
2008-05-15 20:03:49 +04:00
|
|
|
#include <limits>
|
|
|
|
#include <list>
|
2008-05-14 15:00:59 +04:00
|
|
|
#include <cfloat>
|
|
|
|
#include <iostream>
|
|
|
|
|
2008-05-15 20:03:49 +04:00
|
|
|
#include "Optimizer.h"
|
|
|
|
|
2008-05-14 15:00:59 +04:00
|
|
|
using namespace std;
|
|
|
|
|
2008-05-16 18:21:24 +04:00
|
|
|
static const float MIN_FLOAT=-1.0*numeric_limits<float>::max();
|
2008-05-15 20:03:49 +04:00
|
|
|
static const float MAX_FLOAT=numeric_limits<float>::max();
|
2008-05-14 16:49:45 +04:00
|
|
|
|
2011-11-12 03:58:23 +04:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Compute the intersection of 2 lines.
|
|
|
|
*/
|
|
|
|
float intersect(float m1, float b1,float m2,float b2)
|
|
|
|
{
|
|
|
|
float isect = ((b2-b1)/(m1-m2));
|
|
|
|
if (!isfinite(isect)) {
|
|
|
|
isect = MAX_FLOAT;
|
|
|
|
}
|
|
|
|
return isect;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace
|
2008-05-15 14:57:20 +04:00
|
|
|
|
|
|
|
|
2011-11-11 15:40:59 +04:00
|
|
|
void Optimizer::SetScorer(Scorer *_scorer)
|
2011-02-24 15:42:19 +03:00
|
|
|
{
|
2011-11-11 15:40:59 +04:00
|
|
|
scorer = _scorer;
|
2008-05-14 15:00:59 +04:00
|
|
|
}
|
|
|
|
|
2011-11-11 15:40:59 +04:00
|
|
|
void Optimizer::SetFData(FeatureData *_FData)
|
2011-02-24 15:42:19 +03:00
|
|
|
{
|
2011-11-11 15:40:59 +04:00
|
|
|
FData = _FData;
|
2011-11-12 04:40:01 +04:00
|
|
|
}
|
2008-05-14 15:00:59 +04:00
|
|
|
|
2011-07-23 04:24:45 +04:00
|
|
|
Optimizer::Optimizer(unsigned Pd,vector<unsigned> i2O,vector<parameter_t> start, unsigned int nrandom):scorer(NULL),FData(NULL),number_of_random_directions(nrandom)
|
2011-02-24 15:42:19 +03:00
|
|
|
{
|
2011-11-12 03:58:23 +04:00
|
|
|
// Warning: the init vector is a full set of parameters, of dimension pdim!
|
2008-05-15 14:57:20 +04:00
|
|
|
Point::pdim=Pd;
|
2011-02-24 15:42:19 +03:00
|
|
|
|
2008-05-15 14:57:20 +04:00
|
|
|
assert(start.size()==Pd);
|
|
|
|
Point::dim=i2O.size();
|
|
|
|
Point::optindices=i2O;
|
2011-02-24 15:42:19 +03:00
|
|
|
if (Point::pdim>Point::dim) {
|
|
|
|
for (unsigned int i=0; i<Point::pdim; i++) {
|
2010-01-08 18:12:28 +03:00
|
|
|
unsigned int j = 0;
|
|
|
|
while (j<Point::dim && i!=i2O[j])
|
2011-02-24 15:42:19 +03:00
|
|
|
j++;
|
2010-01-08 18:12:28 +03:00
|
|
|
|
2011-11-12 03:58:23 +04:00
|
|
|
// The index i wasnt found on optindices, it is a fixed index,
|
|
|
|
// we use the value of the start vector.
|
|
|
|
if (j==Point::dim)
|
2010-01-08 18:12:28 +03:00
|
|
|
Point::fixedweights[i]=start[i];
|
2008-05-15 14:57:20 +04:00
|
|
|
}
|
|
|
|
}
|
2011-11-12 04:40:01 +04:00
|
|
|
}
|
2008-05-15 14:57:20 +04:00
|
|
|
|
2011-11-11 15:40:59 +04:00
|
|
|
Optimizer::~Optimizer() {}
|
2008-05-15 14:57:20 +04:00
|
|
|
|
2011-02-24 15:42:19 +03:00
|
|
|
statscore_t Optimizer::GetStatScore(const Point& param)const
|
|
|
|
{
|
2008-05-15 14:57:20 +04:00
|
|
|
vector<unsigned> bests;
|
|
|
|
Get1bests(param,bests);
|
2008-05-17 16:19:02 +04:00
|
|
|
//copy(bests.begin(),bests.end(),ostream_iterator<unsigned>(cerr," "));
|
|
|
|
statscore_t score = GetStatScore(bests);
|
|
|
|
return score;
|
2011-11-12 04:40:01 +04:00
|
|
|
}
|
2008-05-15 14:57:20 +04:00
|
|
|
|
2011-02-24 15:42:19 +03:00
|
|
|
map<float,diff_t >::iterator AddThreshold(map<float,diff_t >& thresholdmap,float newt,pair<unsigned,unsigned> newdiff)
|
|
|
|
{
|
2008-05-20 16:42:11 +04:00
|
|
|
map<float,diff_t>::iterator it=thresholdmap.find(newt);
|
2011-02-24 15:42:19 +03:00
|
|
|
if(it!=thresholdmap.end()) {
|
2008-05-20 16:42:11 +04:00
|
|
|
//the threshold already exists!! this is very unlikely
|
|
|
|
if(it->second.back().first==newdiff.first)
|
|
|
|
it->second.back().second=newdiff.second;//there was already a diff for this sentence, we change the 1 best;
|
|
|
|
else
|
|
|
|
it->second.push_back(newdiff);
|
2011-02-24 15:42:19 +03:00
|
|
|
} else {
|
2008-05-20 16:42:11 +04:00
|
|
|
//normal case
|
|
|
|
pair< map<float,diff_t >::iterator,bool > ins=thresholdmap.insert(threshold(newt,diff_t(1,newdiff)));
|
|
|
|
assert(ins.second);//we really inserted something
|
|
|
|
it=ins.first;
|
|
|
|
}
|
|
|
|
return it;
|
2011-11-12 04:40:01 +04:00
|
|
|
}
|
2008-05-20 16:42:11 +04:00
|
|
|
|
|
|
|
|
2011-02-24 15:42:19 +03:00
|
|
|
statscore_t Optimizer::LineOptimize(const Point& origin,const Point& direction,Point& bestpoint)const
|
|
|
|
{
|
2008-05-14 20:19:00 +04:00
|
|
|
|
2011-11-12 03:58:23 +04:00
|
|
|
// We are looking for the best Point on the line y=Origin+x*direction
|
2008-05-15 23:09:01 +04:00
|
|
|
float min_int=0.0001;
|
2008-05-20 16:42:11 +04:00
|
|
|
//typedef pair<unsigned,unsigned> diff;//first the sentence that changes, second is the new 1best for this sentence
|
|
|
|
//list<threshold> thresholdlist;
|
2011-02-24 15:42:19 +03:00
|
|
|
|
2008-05-20 16:42:11 +04:00
|
|
|
map<float,diff_t> thresholdmap;
|
|
|
|
thresholdmap[MIN_FLOAT]=diff_t();
|
2011-11-12 03:58:23 +04:00
|
|
|
vector<unsigned> first1best; // the vector of nbests for x=-inf
|
2011-02-24 15:42:19 +03:00
|
|
|
for(unsigned int S=0; S<size(); S++) {
|
2008-05-20 16:42:11 +04:00
|
|
|
map<float,diff_t >::iterator previnserted=thresholdmap.begin();
|
2011-11-12 03:58:23 +04:00
|
|
|
// First, we determine the translation with the best feature score
|
|
|
|
// for each sentence and each value of x.
|
2008-05-20 14:21:20 +04:00
|
|
|
//cerr << "Sentence " << S << endl;
|
2008-05-14 15:00:59 +04:00
|
|
|
multimap<float,unsigned> gradient;
|
|
|
|
vector<float> f0;
|
2008-05-16 11:09:15 +04:00
|
|
|
f0.resize(FData->get(S).size());
|
2011-02-24 15:42:19 +03:00
|
|
|
for(unsigned j=0; j<FData->get(S).size(); j++) {
|
2008-05-14 19:44:59 +04:00
|
|
|
gradient.insert(pair<float,unsigned>(direction*(FData->get(S,j)),j));//gradient of the feature function for this particular target sentence
|
|
|
|
f0[j]=origin*FData->get(S,j);//compute the feature function at the origin point
|
2008-05-14 15:00:59 +04:00
|
|
|
}
|
2011-11-12 03:58:23 +04:00
|
|
|
// Now let's compute the 1best for each value of x.
|
2011-02-24 15:42:19 +03:00
|
|
|
|
2008-05-20 16:42:11 +04:00
|
|
|
// vector<pair<float,unsigned> > onebest;
|
2011-02-24 15:42:19 +03:00
|
|
|
|
2008-05-20 16:42:11 +04:00
|
|
|
|
|
|
|
multimap<float,unsigned>::iterator gradientit=gradient.begin();
|
2008-05-20 14:21:20 +04:00
|
|
|
multimap<float,unsigned>::iterator highest_f0=gradient.begin();
|
2011-02-24 15:42:19 +03:00
|
|
|
|
2008-05-20 16:42:11 +04:00
|
|
|
float smallest=gradientit->first;//smallest gradient
|
2011-11-12 03:58:23 +04:00
|
|
|
// Several candidates can have the lowest slope (e.g., for word penalty where the gradient is an integer).
|
2008-05-20 16:42:11 +04:00
|
|
|
|
|
|
|
gradientit++;
|
2011-02-24 15:42:19 +03:00
|
|
|
while(gradientit!=gradient.end()&&gradientit->first==smallest) {
|
2008-05-20 16:42:11 +04:00
|
|
|
// cerr<<"ni"<<gradientit->second<<endl;;
|
|
|
|
//cerr<<"fos"<<f0[gradientit->second]<<" "<<f0[index]<<" "<<index<<endl;
|
|
|
|
if(f0[gradientit->second]>f0[highest_f0->second])
|
2011-02-24 15:42:19 +03:00
|
|
|
highest_f0=gradientit;//the highest line is the one with he highest f0
|
2008-05-20 16:42:11 +04:00
|
|
|
gradientit++;
|
2008-05-16 00:49:49 +04:00
|
|
|
}
|
2011-02-24 15:42:19 +03:00
|
|
|
|
2008-05-20 16:42:11 +04:00
|
|
|
gradientit = highest_f0;
|
2011-02-24 15:42:19 +03:00
|
|
|
first1best.push_back(highest_f0->second);
|
2008-05-20 16:42:11 +04:00
|
|
|
|
2011-11-12 03:58:23 +04:00
|
|
|
// Now we look for the intersections points indicating a change of 1 best.
|
|
|
|
// We use the fact that the function is convex, which means that the gradient can only go up.
|
2011-02-24 15:42:19 +03:00
|
|
|
while(gradientit!=gradient.end()) {
|
2008-05-20 16:42:11 +04:00
|
|
|
map<float,unsigned>::iterator leftmost=gradientit;
|
|
|
|
float m=gradientit->first;
|
|
|
|
float b=f0[gradientit->second];
|
|
|
|
multimap<float,unsigned>::iterator gradientit2=gradientit;
|
|
|
|
gradientit2++;
|
2008-05-16 20:47:01 +04:00
|
|
|
float leftmostx=MAX_FLOAT;
|
2011-02-24 15:42:19 +03:00
|
|
|
for(; gradientit2!=gradient.end(); gradientit2++) {
|
|
|
|
//cerr<<"--"<<d++<<' '<<gradientit2->first<<' '<<gradientit2->second<<endl;
|
2011-11-12 03:58:23 +04:00
|
|
|
// Look for all candidate with a gradient bigger than the current one, and
|
|
|
|
// find the one with the leftmost intersection.
|
2011-02-24 15:42:19 +03:00
|
|
|
float curintersect;
|
|
|
|
if(m!=gradientit2->first) {
|
|
|
|
curintersect=intersect(m,b,gradientit2->first,f0[gradientit2->second]);
|
2008-05-16 20:47:01 +04:00
|
|
|
//cerr << "curintersect: " << curintersect << " leftmostx: " << leftmostx << endl;
|
2011-02-24 15:42:19 +03:00
|
|
|
if(curintersect<=leftmostx) {
|
2011-11-12 03:58:23 +04:00
|
|
|
// We have found an intersection to the left of the leftmost we had so far.
|
|
|
|
// We might have curintersect==leftmostx for example is 2 candidates are the same
|
|
|
|
// in that case its better its better to update leftmost to gradientit2 to avoid some recomputing later.
|
2011-02-24 15:42:19 +03:00
|
|
|
leftmostx=curintersect;
|
2011-11-12 03:58:23 +04:00
|
|
|
leftmost=gradientit2; // this is the new reference
|
2011-02-24 15:42:19 +03:00
|
|
|
}
|
|
|
|
}
|
2008-05-14 15:00:59 +04:00
|
|
|
}
|
2008-05-20 16:42:11 +04:00
|
|
|
if (leftmost == gradientit) {
|
2011-11-12 03:58:23 +04:00
|
|
|
// We didn't find any more intersections.
|
|
|
|
// The rightmost bestindex is the one with the highest slope.
|
|
|
|
|
|
|
|
// They should be equal but there might be.
|
|
|
|
assert(abs(leftmost->first-gradient.rbegin()->first)<0.0001);
|
|
|
|
// A small difference due to rounding error
|
2011-02-24 15:42:19 +03:00
|
|
|
break;
|
2008-05-16 20:47:01 +04:00
|
|
|
}
|
2011-11-12 03:58:23 +04:00
|
|
|
// We have found the next intersection!
|
2008-05-14 19:44:59 +04:00
|
|
|
|
2008-05-20 16:42:11 +04:00
|
|
|
pair<unsigned,unsigned> newd(S,leftmost->second);//new onebest for Sentence S is leftmost->second
|
2008-05-15 23:09:01 +04:00
|
|
|
|
2011-02-24 15:42:19 +03:00
|
|
|
if(leftmostx-previnserted->first<min_int) {
|
2011-11-12 03:58:23 +04:00
|
|
|
// Require that the intersection Point be at least min_int to the right of the previous
|
|
|
|
// one (for this sentence). If not, we replace the previous intersection Point with
|
|
|
|
// this one.
|
|
|
|
// Yes, it can even happen that the new intersection Point is slightly to the left of
|
|
|
|
// the old one, because of numerical imprecision. We do not check that we are to the
|
|
|
|
// right of the penultimate point also. It this happen the 1best the interval will
|
|
|
|
// be wrong we are going to replace previnsert by the new one because we do not want to keep
|
|
|
|
// 2 very close threshold: if the minima is there it could be an artifact.
|
|
|
|
|
2011-02-24 15:42:19 +03:00
|
|
|
map<float,diff_t>::iterator tit=thresholdmap.find(leftmostx);
|
|
|
|
if(tit==previnserted) {
|
2011-11-12 03:58:23 +04:00
|
|
|
// The threshold is the same as before can happen if 2 candidates are the same for example.
|
2011-02-24 15:42:19 +03:00
|
|
|
assert(previnserted->second.back().first==newd.first);
|
2011-11-12 03:58:23 +04:00
|
|
|
previnserted->second.back()=newd; // just replace the 1 best for sentence S
|
|
|
|
// previnsert doesn't change
|
2011-02-24 15:42:19 +03:00
|
|
|
} else {
|
|
|
|
|
|
|
|
if(tit==thresholdmap.end()) {
|
2011-11-12 03:58:23 +04:00
|
|
|
thresholdmap[leftmostx]=previnserted->second; // We keep the diffs at previnsert
|
|
|
|
thresholdmap.erase(previnserted); // erase old previnsert
|
|
|
|
previnserted=thresholdmap.find(leftmostx); // point previnsert to the new threshold
|
|
|
|
previnserted->second.back()=newd; // We update the diff for sentence S
|
|
|
|
// Threshold already exists but is not the previous one.
|
|
|
|
} else {
|
|
|
|
// We append the diffs in previnsert to tit before destroying previnsert.
|
2011-02-24 15:42:19 +03:00
|
|
|
tit->second.insert(tit->second.end(),previnserted->second.begin(),previnserted->second.end());
|
|
|
|
assert(tit->second.back().first==newd.first);
|
2011-11-12 03:58:23 +04:00
|
|
|
tit->second.back()=newd; // change diff for sentence S
|
|
|
|
thresholdmap.erase(previnserted); // erase old previnsert
|
|
|
|
previnserted=tit; // point previnsert to the new threshold
|
2011-02-24 15:42:19 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(previnserted != thresholdmap.end());
|
|
|
|
} else { //normal insertion process
|
|
|
|
previnserted=AddThreshold(thresholdmap,leftmostx,newd);
|
2008-05-14 18:25:07 +04:00
|
|
|
}
|
2008-05-20 16:42:11 +04:00
|
|
|
gradientit=leftmost;
|
2011-11-12 03:58:23 +04:00
|
|
|
} // while(gradientit!=gradient.end()){
|
|
|
|
} // loop on S
|
|
|
|
|
|
|
|
// Now the thresholdlist is up to date: it contains a list of all the parameter_ts where
|
|
|
|
// the function changed its value, along with the nbest list for the interval after each threshold.
|
2011-02-24 15:42:19 +03:00
|
|
|
|
2008-05-20 16:42:11 +04:00
|
|
|
map<float,diff_t >::iterator thrit;
|
2011-02-24 15:42:19 +03:00
|
|
|
if(verboselevel()>6) {
|
2008-05-20 16:42:11 +04:00
|
|
|
cerr << "Thresholds:(" <<thresholdmap.size()<<")"<< endl;
|
2011-02-24 15:42:19 +03:00
|
|
|
for (thrit = thresholdmap.begin(); thrit!=thresholdmap.end(); thrit++) {
|
2008-05-20 16:42:11 +04:00
|
|
|
cerr << "x: " << thrit->first << " diffs";
|
|
|
|
for (size_t j = 0; j < thrit->second.size(); ++j) {
|
2011-02-24 15:42:19 +03:00
|
|
|
cerr << " " <<thrit->second[j].first << "," << thrit->second[j].second;
|
2008-05-20 16:42:11 +04:00
|
|
|
}
|
|
|
|
cerr << endl;
|
|
|
|
}
|
2008-05-20 14:21:20 +04:00
|
|
|
}
|
2011-02-24 15:42:19 +03:00
|
|
|
|
2011-11-12 03:58:23 +04:00
|
|
|
// Last thing to do is compute the Stat score (i.e., BLEU) and find the minimum.
|
2008-05-20 16:42:11 +04:00
|
|
|
thrit=thresholdmap.begin();
|
2011-11-12 03:58:23 +04:00
|
|
|
++thrit; // first diff corrrespond to MIN_FLOAT and first1best
|
2008-05-20 16:42:11 +04:00
|
|
|
diffs_t diffs;
|
2011-02-24 15:42:19 +03:00
|
|
|
for(; thrit!=thresholdmap.end(); thrit++)
|
2008-05-20 16:42:11 +04:00
|
|
|
diffs.push_back(thrit->second);
|
2008-05-15 23:09:01 +04:00
|
|
|
vector<statscore_t> scores=GetIncStatScore(first1best,diffs);
|
2011-02-24 15:42:19 +03:00
|
|
|
|
2008-05-20 16:42:11 +04:00
|
|
|
thrit=thresholdmap.begin();
|
2008-05-15 23:09:01 +04:00
|
|
|
statscore_t bestscore=MIN_FLOAT;
|
2008-05-16 14:57:24 +04:00
|
|
|
float bestx=MIN_FLOAT;
|
2011-11-12 03:58:23 +04:00
|
|
|
|
|
|
|
// We skipped the first el of thresholdlist but GetIncStatScore return 1 more for first1best.
|
|
|
|
assert(scores.size()==thresholdmap.size());
|
2011-02-24 15:42:19 +03:00
|
|
|
for(unsigned int sc=0; sc!=scores.size(); sc++) {
|
2008-05-21 20:22:43 +04:00
|
|
|
//cerr << "x=" << thrit->first << " => " << scores[sc] << endl;
|
2008-05-16 20:47:01 +04:00
|
|
|
if (scores[sc] > bestscore) {
|
2011-11-12 03:58:23 +04:00
|
|
|
// This is the score for the interval [lit2->first, (lit2+1)->first]
|
|
|
|
// unless we're at the last score, when it's the score
|
|
|
|
// for the interval [lit2->first,+inf].
|
2011-02-24 15:42:19 +03:00
|
|
|
bestscore = scores[sc];
|
|
|
|
|
2011-11-12 03:58:23 +04:00
|
|
|
// If we're not in [-inf,x1] or [xn,+inf], then just take the value
|
|
|
|
// if x which splits the interval in half. For the rightmost interval,
|
|
|
|
// take x to be the last interval boundary + 0.1, and for the leftmost
|
|
|
|
// interval, take x to be the first interval boundary - 1000.
|
|
|
|
// These values are taken from cmert.
|
2011-02-24 15:42:19 +03:00
|
|
|
float leftx = thrit->first;
|
|
|
|
if (thrit == thresholdmap.begin()) {
|
|
|
|
leftx = MIN_FLOAT;
|
|
|
|
}
|
|
|
|
++thrit;
|
|
|
|
float rightx = MAX_FLOAT;
|
|
|
|
if (thrit != thresholdmap.end()) {
|
|
|
|
rightx = thrit->first;
|
|
|
|
}
|
|
|
|
--thrit;
|
|
|
|
//cerr << "leftx: " << leftx << " rightx: " << rightx << endl;
|
|
|
|
if (leftx == MIN_FLOAT) {
|
|
|
|
bestx = rightx-1000;
|
|
|
|
} else if (rightx == MAX_FLOAT) {
|
|
|
|
bestx = leftx+0.1;
|
|
|
|
} else {
|
|
|
|
bestx = 0.5 * (rightx + leftx);
|
|
|
|
}
|
|
|
|
//cerr << "x = " << "set new bestx to: " << bestx << endl;
|
2008-05-14 15:00:59 +04:00
|
|
|
}
|
2008-05-20 16:42:11 +04:00
|
|
|
++thrit;
|
2008-05-14 19:44:59 +04:00
|
|
|
}
|
2008-05-20 16:42:11 +04:00
|
|
|
|
2011-02-24 15:42:19 +03:00
|
|
|
if(abs(bestx)<0.00015) {
|
2011-11-12 03:58:23 +04:00
|
|
|
// The origin of the line is the best point! We put it back at 0
|
|
|
|
// so we do not propagate rounding erros.
|
|
|
|
bestx=0.0;
|
|
|
|
|
|
|
|
// Finally, we manage to extract the best score;
|
|
|
|
// now we convert bestx (position on the line) to a point.
|
2008-05-16 18:21:24 +04:00
|
|
|
if(verboselevel()>4)
|
|
|
|
cerr<<"best point on line at origin"<<endl;
|
|
|
|
}
|
2011-02-24 15:42:19 +03:00
|
|
|
if(verboselevel()>3) {
|
2008-05-21 20:52:00 +04:00
|
|
|
// cerr<<"end Lineopt, bestx="<<bestx<<endl;
|
2011-02-24 15:42:19 +03:00
|
|
|
}
|
|
|
|
bestpoint=direction*bestx+origin;
|
2008-05-16 14:57:24 +04:00
|
|
|
bestpoint.score=bestscore;
|
2011-02-24 15:42:19 +03:00
|
|
|
return bestscore;
|
2011-11-12 04:40:01 +04:00
|
|
|
}
|
2008-05-20 16:42:11 +04:00
|
|
|
|
2011-02-24 15:42:19 +03:00
|
|
|
void Optimizer::Get1bests(const Point& P,vector<unsigned>& bests)const
|
|
|
|
{
|
2008-05-15 14:57:20 +04:00
|
|
|
assert(FData);
|
|
|
|
bests.clear();
|
|
|
|
bests.resize(size());
|
2011-02-24 15:42:19 +03:00
|
|
|
|
|
|
|
for(unsigned i=0; i<size(); i++) {
|
2008-05-15 20:03:49 +04:00
|
|
|
float bestfs=MIN_FLOAT;
|
2008-05-15 14:57:20 +04:00
|
|
|
unsigned idx=0;
|
|
|
|
unsigned j;
|
2011-02-24 15:42:19 +03:00
|
|
|
for(j=0; j<FData->get(i).size(); j++) {
|
2008-05-15 14:57:20 +04:00
|
|
|
float curfs=P*FData->get(i,j);
|
2011-02-24 15:42:19 +03:00
|
|
|
if(curfs>bestfs) {
|
|
|
|
bestfs=curfs;
|
|
|
|
idx=j;
|
2008-05-15 14:57:20 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
bests[i]=idx;
|
|
|
|
}
|
2011-02-24 15:42:19 +03:00
|
|
|
|
2008-05-15 14:57:20 +04:00
|
|
|
}
|
2008-05-14 15:00:59 +04:00
|
|
|
|
2011-02-24 15:42:19 +03:00
|
|
|
statscore_t Optimizer::Run(Point& P)const
|
|
|
|
{
|
|
|
|
if(!FData) {
|
2008-05-16 11:09:15 +04:00
|
|
|
cerr<<"error trying to optimize without Features loaded"<<endl;
|
2008-05-14 20:19:00 +04:00
|
|
|
exit(2);
|
|
|
|
}
|
2011-02-24 15:42:19 +03:00
|
|
|
if(!scorer) {
|
2008-05-14 20:19:00 +04:00
|
|
|
cerr<<"error trying to optimize without a Scorer loaded"<<endl;
|
|
|
|
exit(2);
|
|
|
|
}
|
2011-02-24 15:42:19 +03:00
|
|
|
if (scorer->getReferenceSize()!=FData->size()) {
|
2010-12-08 13:13:19 +03:00
|
|
|
cerr<<"error length mismatch between feature file and score file"<<endl;
|
2008-05-16 00:49:49 +04:00
|
|
|
exit(2);
|
|
|
|
}
|
2008-05-23 15:48:16 +04:00
|
|
|
|
2011-02-24 15:42:19 +03:00
|
|
|
statscore_t score=GetStatScore(P);
|
|
|
|
P.score=score;
|
|
|
|
|
|
|
|
if(verboselevel()>2)
|
2008-05-27 20:50:52 +04:00
|
|
|
cerr<<"Starting point: "<< P << " => "<< P.score << endl;
|
2008-05-15 23:09:01 +04:00
|
|
|
statscore_t s=TrueRun(P);
|
2008-05-15 18:04:42 +04:00
|
|
|
P.score=s;//just in case its not done in TrueRun
|
2008-05-27 20:50:52 +04:00
|
|
|
if (verboselevel()>2)
|
|
|
|
cerr<<"Ending point: "<< P <<" => "<< s << endl;
|
2008-05-15 18:04:42 +04:00
|
|
|
return s;
|
2008-05-14 20:19:00 +04:00
|
|
|
}
|
2008-05-15 23:09:01 +04:00
|
|
|
|
2011-02-24 15:42:19 +03:00
|
|
|
|
|
|
|
vector<statscore_t> Optimizer::GetIncStatScore(vector<unsigned> thefirst,vector<vector <pair<unsigned,unsigned> > > thediffs)const
|
|
|
|
{
|
2008-05-15 23:09:01 +04:00
|
|
|
assert(scorer);
|
|
|
|
|
|
|
|
vector<statscore_t> theres;
|
|
|
|
|
|
|
|
scorer->score(thefirst,thediffs,theres);
|
|
|
|
return theres;
|
2011-11-12 04:40:01 +04:00
|
|
|
}
|
2008-05-15 23:09:01 +04:00
|
|
|
|
|
|
|
|
2011-02-24 15:42:19 +03:00
|
|
|
statscore_t SimpleOptimizer::TrueRun(Point& P)const
|
|
|
|
{
|
2008-05-16 18:21:24 +04:00
|
|
|
statscore_t prevscore=0;
|
2008-05-16 11:09:15 +04:00
|
|
|
statscore_t bestscore=MIN_FLOAT;
|
2008-05-16 20:47:01 +04:00
|
|
|
Point best;
|
2011-02-24 15:42:19 +03:00
|
|
|
|
2011-11-12 03:58:23 +04:00
|
|
|
// If P is already defined and provides a score,
|
|
|
|
// We must improve over this score.
|
2011-02-24 15:42:19 +03:00
|
|
|
if(P.score>bestscore) {
|
|
|
|
bestscore=P.score;
|
|
|
|
best=P;
|
|
|
|
}
|
|
|
|
|
2008-05-16 14:57:24 +04:00
|
|
|
int nrun=0;
|
2011-02-24 15:42:19 +03:00
|
|
|
do {
|
|
|
|
++nrun;
|
2008-05-16 18:21:24 +04:00
|
|
|
if(verboselevel()>2&&nrun>1)
|
2008-05-21 20:52:00 +04:00
|
|
|
cerr<<"last diff="<<bestscore-prevscore<<" nrun "<<nrun<<endl;
|
2008-05-16 11:09:15 +04:00
|
|
|
prevscore=bestscore;
|
2011-02-24 15:42:19 +03:00
|
|
|
|
2008-05-15 14:57:20 +04:00
|
|
|
Point linebest;
|
2011-02-24 15:42:19 +03:00
|
|
|
|
2011-07-23 04:24:45 +04:00
|
|
|
for(unsigned int d=0; d<Point::getdim()+number_of_random_directions; d++) {
|
2011-02-24 15:42:19 +03:00
|
|
|
if(verboselevel()>4) {
|
|
|
|
// cerr<<"minimizing along direction "<<d<<endl;
|
|
|
|
cerr<<"starting point: " << P << " => " << prevscore << endl;
|
2008-05-21 20:52:00 +04:00
|
|
|
}
|
2008-05-15 14:57:20 +04:00
|
|
|
Point direction;
|
2011-07-23 04:24:45 +04:00
|
|
|
if (d<Point::getdim()) { // regular updates along one dimension
|
|
|
|
for(unsigned int i=0; i<Point::getdim(); i++)
|
|
|
|
direction[i]=0.0;
|
|
|
|
direction[d]=1.0;
|
|
|
|
}
|
|
|
|
else { // random direction update
|
|
|
|
direction.Randomize();
|
|
|
|
}
|
2008-05-15 23:09:01 +04:00
|
|
|
statscore_t curscore=LineOptimize(P,direction,linebest);//find the minimum on the line
|
2011-02-24 15:42:19 +03:00
|
|
|
if(verboselevel()>5) {
|
|
|
|
cerr<<"direction: "<< d << " => " << curscore << endl;
|
|
|
|
cerr<<"\tending point: "<< linebest << " => " << curscore << endl;
|
|
|
|
}
|
|
|
|
if(curscore>bestscore) {
|
|
|
|
bestscore=curscore;
|
|
|
|
best=linebest;
|
|
|
|
if(verboselevel()>3) {
|
|
|
|
cerr<<"new best dir:"<<d<<" ("<<nrun<<")"<<endl;
|
|
|
|
cerr<<"new best Point "<<best<< " => " <<curscore<<endl;
|
|
|
|
}
|
|
|
|
}
|
2008-05-14 15:00:59 +04:00
|
|
|
}
|
2011-11-12 03:58:23 +04:00
|
|
|
P=best; //update the current vector with the best point on all line tested
|
2011-02-24 15:42:19 +03:00
|
|
|
if(verboselevel()>3)
|
|
|
|
cerr<<nrun<<"\t"<<P<<endl;
|
2011-11-12 05:16:31 +04:00
|
|
|
} while(bestscore-prevscore>kEPS);
|
2011-02-24 15:42:19 +03:00
|
|
|
|
|
|
|
if(verboselevel()>2) {
|
2008-05-16 14:57:24 +04:00
|
|
|
cerr<<"end Powell Algo, nrun="<<nrun<<endl;
|
|
|
|
cerr<<"last diff="<<bestscore-prevscore<<endl;
|
2008-05-16 18:21:24 +04:00
|
|
|
cerr<<"\t"<<P<<endl;
|
2011-02-24 15:42:19 +03:00
|
|
|
}
|
2008-05-15 18:04:42 +04:00
|
|
|
return bestscore;
|
2008-05-14 15:00:59 +04:00
|
|
|
}
|
2008-05-15 18:04:42 +04:00
|
|
|
|
2011-07-23 04:24:45 +04:00
|
|
|
statscore_t RandomDirectionOptimizer::TrueRun(Point& P)const
|
|
|
|
{
|
|
|
|
statscore_t prevscore=P.score;
|
|
|
|
|
|
|
|
// do specified number of random direction optimizations
|
|
|
|
unsigned int nrun = 0;
|
|
|
|
unsigned int nrun_no_change = 0;
|
|
|
|
for(; nrun_no_change<number_of_random_directions; nrun++, nrun_no_change++)
|
|
|
|
{
|
|
|
|
// choose a random direction in which to optimize
|
|
|
|
Point direction;
|
|
|
|
direction.Randomize();
|
|
|
|
|
|
|
|
//find the minimum on the line
|
|
|
|
statscore_t score=LineOptimize(P,direction,P);
|
|
|
|
if(verboselevel()>4) {
|
|
|
|
cerr<<"direction: "<< direction << " => " << score;
|
|
|
|
cerr<<" ("<< (score-prevscore) << ")" << endl;
|
|
|
|
cerr<<"\tending point: "<< P << " => " << score << endl;
|
|
|
|
}
|
|
|
|
|
2011-11-12 05:16:31 +04:00
|
|
|
if (score-prevscore > kEPS)
|
2011-07-23 04:24:45 +04:00
|
|
|
nrun_no_change=0;
|
|
|
|
prevscore = score;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(verboselevel()>2) {
|
|
|
|
cerr<<"end Powell Algo, nrun="<<nrun<<endl;
|
|
|
|
}
|
|
|
|
return prevscore;
|
|
|
|
}
|
2008-05-15 18:04:42 +04:00
|
|
|
|
|
|
|
|
2011-02-24 15:42:19 +03:00
|
|
|
statscore_t RandomOptimizer::TrueRun(Point& P)const
|
|
|
|
{
|
2011-07-04 01:01:16 +04:00
|
|
|
P.Randomize();
|
2011-02-24 15:42:19 +03:00
|
|
|
statscore_t score=GetStatScore(P);
|
|
|
|
P.score=score;
|
|
|
|
return score;
|
2008-05-16 14:57:24 +04:00
|
|
|
}
|
2011-11-12 03:58:23 +04:00
|
|
|
|
2008-05-16 14:57:24 +04:00
|
|
|
//--------------------------------------
|
2011-11-12 03:58:23 +04:00
|
|
|
|
2008-05-16 14:57:24 +04:00
|
|
|
vector<string> OptimizerFactory::typenames;
|
2008-05-15 18:04:42 +04:00
|
|
|
|
2011-02-24 15:42:19 +03:00
|
|
|
void OptimizerFactory::SetTypeNames()
|
|
|
|
{
|
|
|
|
if(typenames.empty()) {
|
2008-05-16 14:57:24 +04:00
|
|
|
typenames.resize(NOPTIMIZER);
|
|
|
|
typenames[POWELL]="powell";
|
2011-07-23 04:24:45 +04:00
|
|
|
typenames[RANDOM_DIRECTION]="random-direction";
|
2008-05-16 14:57:24 +04:00
|
|
|
typenames[RANDOM]="random";
|
2011-11-12 03:58:23 +04:00
|
|
|
// Add new type there
|
2011-02-24 15:42:19 +03:00
|
|
|
}
|
2008-05-16 14:57:24 +04:00
|
|
|
}
|
2011-02-24 15:42:19 +03:00
|
|
|
vector<string> OptimizerFactory::GetTypeNames()
|
|
|
|
{
|
2008-05-16 14:57:24 +04:00
|
|
|
if(typenames.empty())
|
|
|
|
SetTypeNames();
|
|
|
|
return typenames;
|
|
|
|
}
|
|
|
|
|
2011-02-24 15:42:19 +03:00
|
|
|
OptimizerFactory::OptType OptimizerFactory::GetOType(string type)
|
|
|
|
{
|
2008-05-23 15:48:16 +04:00
|
|
|
unsigned int thetype;
|
2008-05-16 14:57:24 +04:00
|
|
|
if(typenames.empty())
|
|
|
|
SetTypeNames();
|
2011-02-24 15:42:19 +03:00
|
|
|
for(thetype=0; thetype<typenames.size(); thetype++)
|
2008-05-16 14:57:24 +04:00
|
|
|
if(typenames[thetype]==type)
|
|
|
|
break;
|
|
|
|
return((OptType)thetype);
|
2011-11-12 04:40:01 +04:00
|
|
|
}
|
2008-05-16 14:57:24 +04:00
|
|
|
|
2011-07-23 04:24:45 +04:00
|
|
|
Optimizer* OptimizerFactory::BuildOptimizer(unsigned dim,vector<unsigned> i2o,vector<parameter_t> start,string type, unsigned int nrandom)
|
2011-02-24 15:42:19 +03:00
|
|
|
{
|
2008-05-16 14:57:24 +04:00
|
|
|
OptType T=GetOType(type);
|
2011-02-24 15:42:19 +03:00
|
|
|
if(T==NOPTIMIZER) {
|
2008-05-17 16:19:02 +04:00
|
|
|
cerr<<"Error: unknown Optimizer type "<<type<<endl;
|
2008-05-16 14:57:24 +04:00
|
|
|
cerr<<"Known Algorithm are:"<<endl;
|
2008-05-23 15:48:16 +04:00
|
|
|
unsigned int thetype;
|
2011-02-24 15:42:19 +03:00
|
|
|
for(thetype=0; thetype<typenames.size(); thetype++)
|
2008-05-16 14:57:24 +04:00
|
|
|
cerr<<typenames[thetype]<<endl;
|
|
|
|
throw ("unknown Optimizer Type");
|
|
|
|
}
|
2011-02-24 15:42:19 +03:00
|
|
|
|
|
|
|
switch((OptType)T) {
|
2011-11-12 04:24:19 +04:00
|
|
|
case POWELL:
|
|
|
|
return new SimpleOptimizer(dim,i2o,start,nrandom);
|
|
|
|
break;
|
|
|
|
case RANDOM_DIRECTION:
|
|
|
|
return new RandomDirectionOptimizer(dim,i2o,start,nrandom);
|
|
|
|
break;
|
|
|
|
case RANDOM:
|
|
|
|
return new RandomOptimizer(dim,i2o,start,nrandom);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
cerr<<"Error: unknown optimizer"<<type<<endl;
|
|
|
|
return NULL;
|
2011-02-24 15:42:19 +03:00
|
|
|
}
|
2008-05-16 14:57:24 +04:00
|
|
|
}
|