2008-05-15 18:04:42 +04:00
|
|
|
/**
|
2011-12-12 17:48:42 +04:00
|
|
|
* \description This is the main for the new version of the mert algorithm developed during the 2nd MT marathon
|
2008-05-15 18:04:42 +04:00
|
|
|
*/
|
2008-05-15 15:06:32 +04:00
|
|
|
|
|
|
|
#include <limits>
|
2009-02-12 15:58:27 +03:00
|
|
|
#include <unistd.h>
|
|
|
|
#include <cstdlib>
|
|
|
|
#include <iostream>
|
|
|
|
#include <fstream>
|
|
|
|
#include <cmath>
|
|
|
|
#include <ctime>
|
|
|
|
|
|
|
|
#include <getopt.h>
|
|
|
|
|
2008-05-15 15:06:32 +04:00
|
|
|
#include "Data.h"
|
|
|
|
#include "Point.h"
|
|
|
|
#include "Scorer.h"
|
2008-05-27 20:50:52 +04:00
|
|
|
#include "ScorerFactory.h"
|
2008-05-15 15:06:32 +04:00
|
|
|
#include "ScoreData.h"
|
|
|
|
#include "FeatureData.h"
|
|
|
|
#include "Optimizer.h"
|
2008-05-15 23:09:01 +04:00
|
|
|
#include "Types.h"
|
2008-05-16 23:57:01 +04:00
|
|
|
#include "Timer.h"
|
2008-05-16 11:09:15 +04:00
|
|
|
#include "Util.h"
|
2008-05-15 15:06:32 +04:00
|
|
|
|
2011-09-07 12:08:35 +04:00
|
|
|
#include "../moses/src/ThreadPool.h"
|
|
|
|
|
2012-02-01 07:35:50 +04:00
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
namespace {
|
2008-05-15 15:06:32 +04:00
|
|
|
|
2012-02-01 11:33:23 +04:00
|
|
|
const char kDefaultOptimizer[] = "powell";
|
|
|
|
const char kDefaultScorer[] = "BLEU";
|
|
|
|
const char kDefaultScorerFile[] = "statscore.data";
|
|
|
|
const char kDefaultFeatureFile[] = "features.data";
|
|
|
|
const char kDefaultInitFile[] = "init.opt";
|
|
|
|
|
2012-02-01 07:35:50 +04:00
|
|
|
/**
|
|
|
|
* Runs an optimisation, or a random restart.
|
|
|
|
*/
|
|
|
|
class OptimizationTask : public Moses::Task {
|
|
|
|
public:
|
|
|
|
OptimizationTask(Optimizer* optimizer, const Point& point)
|
|
|
|
: m_optimizer(optimizer), m_point(point) {}
|
|
|
|
|
|
|
|
~OptimizationTask() {}
|
|
|
|
|
2012-02-01 10:49:33 +04:00
|
|
|
virtual void Run() {
|
|
|
|
m_score = m_optimizer->Run(m_point);
|
2012-02-01 07:35:50 +04:00
|
|
|
}
|
|
|
|
|
2012-02-01 10:49:33 +04:00
|
|
|
virtual bool DeleteAfterExecution() {
|
2012-02-01 07:35:50 +04:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2012-02-01 10:49:33 +04:00
|
|
|
void resetOptimizer() {
|
|
|
|
if (m_optimizer) {
|
|
|
|
delete m_optimizer;
|
|
|
|
m_optimizer = NULL;
|
|
|
|
}
|
2012-02-01 07:35:50 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
statscore_t getScore() const {
|
|
|
|
return m_score;
|
|
|
|
}
|
|
|
|
|
|
|
|
const Point& getPoint() const {
|
|
|
|
return m_point;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
// Do not allow the user to instanciate without arguments.
|
|
|
|
OptimizationTask() {}
|
|
|
|
|
|
|
|
Optimizer* m_optimizer;
|
|
|
|
Point m_point;
|
|
|
|
statscore_t m_score;
|
|
|
|
};
|
2008-05-15 18:04:42 +04:00
|
|
|
|
2011-09-15 21:45:35 +04:00
|
|
|
void usage(int ret)
|
2011-02-24 15:42:19 +03:00
|
|
|
{
|
2012-02-01 11:15:22 +04:00
|
|
|
cerr << "usage: mert -d <dimensions> (mandatory)" << endl;
|
|
|
|
cerr << "[-n] retry ntimes (default 1)" << endl;
|
|
|
|
cerr << "[-m] number of random directions in powell (default 0)"<< endl;
|
|
|
|
cerr << "[-o] the indexes to optimize(default all)" << endl;
|
2012-02-01 11:33:23 +04:00
|
|
|
cerr << "[-t] the optimizer(default " << kDefaultOptimizer << ")" << endl;
|
2012-02-01 11:15:22 +04:00
|
|
|
cerr << "[-r] the random seed (defaults to system clock)" << endl;
|
2012-02-01 11:33:23 +04:00
|
|
|
cerr << "[--sctype|-s] the scorer type (default " << kDefaultScorer << ")" << endl;
|
2012-02-01 11:15:22 +04:00
|
|
|
cerr << "[--scconfig|-c] configuration string passed to scorer" << endl;
|
2012-02-01 11:33:23 +04:00
|
|
|
cerr << "[--scfile|-S] comma separated list of scorer data files (default " << kDefaultScorerFile << ")" << endl;
|
|
|
|
cerr << "[--ffile|-F] comma separated list of feature data files (default " << kDefaultFeatureFile << ")" << endl;
|
|
|
|
cerr << "[--ifile|-i] the starting point data file (default " << kDefaultInitFile << ")" << endl;
|
2011-09-07 12:08:35 +04:00
|
|
|
#ifdef WITH_THREADS
|
2012-02-01 11:15:22 +04:00
|
|
|
cerr << "[--threads|-T] use multiple threads (default 1)" << endl;
|
2011-09-07 12:08:35 +04:00
|
|
|
#endif
|
2012-02-01 11:15:22 +04:00
|
|
|
cerr << "[--shard-count] Split data into shards, optimize for each shard and average" << endl;
|
|
|
|
cerr << "[--shard-size] Shard size as proportion of data. If 0, use non-overlapping shards" << endl;
|
|
|
|
cerr << "[-v] verbose level" << endl;
|
|
|
|
cerr << "[--help|-h] print this message and exit" << endl;
|
2011-09-15 21:45:35 +04:00
|
|
|
exit(ret);
|
2008-05-15 15:06:32 +04:00
|
|
|
}
|
|
|
|
|
2011-02-24 15:42:19 +03:00
|
|
|
static struct option long_options[] = {
|
|
|
|
{"pdim", 1, 0, 'd'},
|
2012-02-01 11:15:22 +04:00
|
|
|
{"ntry", 1, 0, 'n'},
|
|
|
|
{"nrandom", 1, 0, 'm'},
|
|
|
|
{"rseed", required_argument, 0, 'r'},
|
|
|
|
{"optimize", 1, 0, 'o'},
|
|
|
|
{"pro", required_argument, 0, 'p'},
|
|
|
|
{"type", 1, 0, 't'},
|
|
|
|
{"sctype", 1, 0, 's'},
|
|
|
|
{"scconfig", required_argument, 0, 'c'},
|
|
|
|
{"scfile", 1, 0, 'S'},
|
|
|
|
{"ffile", 1, 0, 'F'},
|
|
|
|
{"ifile", 1, 0, 'i'},
|
2011-09-07 12:08:35 +04:00
|
|
|
#ifdef WITH_THREADS
|
2012-02-01 11:15:22 +04:00
|
|
|
{"threads", required_argument, 0, 'T'},
|
2011-09-07 12:08:35 +04:00
|
|
|
#endif
|
2011-09-15 21:45:35 +04:00
|
|
|
{"shard-count", required_argument, 0, 'a'},
|
|
|
|
{"shard-size", required_argument, 0, 'b'},
|
2012-02-01 11:15:22 +04:00
|
|
|
{"verbose", 1, 0, 'v'},
|
|
|
|
{"help", no_argument, 0, 'h'},
|
2011-02-24 15:42:19 +03:00
|
|
|
{0, 0, 0, 0}
|
|
|
|
};
|
2008-05-15 15:06:32 +04:00
|
|
|
|
2012-02-01 10:21:49 +04:00
|
|
|
struct ProgramOption {
|
|
|
|
string to_optimize_str;
|
|
|
|
int pdim;
|
|
|
|
int ntry;
|
|
|
|
int nrandom;
|
|
|
|
int seed;
|
|
|
|
bool has_seed;
|
|
|
|
string optimize_type;
|
|
|
|
string scorer_type;
|
|
|
|
string scorer_config;
|
|
|
|
string scorer_file;
|
|
|
|
string feature_file;
|
|
|
|
string init_file;
|
|
|
|
size_t num_threads;
|
|
|
|
float shard_size;
|
|
|
|
size_t shard_count;
|
|
|
|
|
|
|
|
ProgramOption()
|
|
|
|
: to_optimize_str(""),
|
|
|
|
pdim(-1),
|
|
|
|
ntry(1),
|
|
|
|
nrandom(0),
|
|
|
|
seed(0),
|
|
|
|
has_seed(false),
|
2012-02-01 11:33:23 +04:00
|
|
|
optimize_type(kDefaultOptimizer),
|
|
|
|
scorer_type(kDefaultScorer),
|
2012-02-01 10:21:49 +04:00
|
|
|
scorer_config(""),
|
2012-02-01 11:33:23 +04:00
|
|
|
scorer_file(kDefaultScorerFile),
|
|
|
|
feature_file(kDefaultFeatureFile),
|
|
|
|
init_file(kDefaultInitFile),
|
2012-02-01 10:21:49 +04:00
|
|
|
num_threads(1),
|
|
|
|
shard_size(0),
|
|
|
|
shard_count(0) { }
|
|
|
|
};
|
2011-02-24 15:42:19 +03:00
|
|
|
|
2012-02-01 10:21:49 +04:00
|
|
|
void ParseCommandOptions(int argc, char** argv, ProgramOption* opt) {
|
|
|
|
int c;
|
|
|
|
int option_index;
|
2011-07-04 01:01:16 +04:00
|
|
|
|
2012-02-01 10:21:49 +04:00
|
|
|
while ((c = getopt_long(argc, argv, "o:r:d:n:m:t:s:S:F:v:p:", long_options, &option_index)) != -1) {
|
2008-05-15 15:06:32 +04:00
|
|
|
switch (c) {
|
2011-11-12 04:24:19 +04:00
|
|
|
case 'o':
|
2012-02-01 10:21:49 +04:00
|
|
|
opt->to_optimize_str = string(optarg);
|
2011-11-12 04:24:19 +04:00
|
|
|
break;
|
|
|
|
case 'd':
|
2012-02-01 10:21:49 +04:00
|
|
|
opt->pdim = strtol(optarg, NULL, 10);
|
2011-11-12 04:24:19 +04:00
|
|
|
break;
|
|
|
|
case 'n':
|
2012-02-01 10:21:49 +04:00
|
|
|
opt->ntry = strtol(optarg, NULL, 10);
|
2011-11-17 19:58:56 +04:00
|
|
|
break;
|
2011-11-12 04:24:19 +04:00
|
|
|
case 'm':
|
2012-02-01 10:21:49 +04:00
|
|
|
opt->nrandom = strtol(optarg, NULL, 10);
|
2011-11-12 04:24:19 +04:00
|
|
|
break;
|
|
|
|
case 'r':
|
2012-02-01 10:21:49 +04:00
|
|
|
opt->seed = strtol(optarg, NULL, 10);
|
|
|
|
opt->has_seed = true;
|
2011-11-12 04:24:19 +04:00
|
|
|
break;
|
|
|
|
case 't':
|
2012-02-01 10:21:49 +04:00
|
|
|
opt->optimize_type = string(optarg);
|
2011-11-12 04:24:19 +04:00
|
|
|
break;
|
|
|
|
case's':
|
2012-02-01 10:21:49 +04:00
|
|
|
opt->scorer_type = string(optarg);
|
2011-11-12 04:24:19 +04:00
|
|
|
break;
|
|
|
|
case 'c':
|
2012-02-01 10:21:49 +04:00
|
|
|
opt->scorer_config = string(optarg);
|
2011-11-12 04:24:19 +04:00
|
|
|
break;
|
|
|
|
case 'S':
|
2012-02-01 10:21:49 +04:00
|
|
|
opt->scorer_file = string(optarg);
|
2011-11-12 04:24:19 +04:00
|
|
|
break;
|
|
|
|
case 'F':
|
2012-02-01 10:21:49 +04:00
|
|
|
opt->feature_file = string(optarg);
|
2011-11-12 04:24:19 +04:00
|
|
|
break;
|
|
|
|
case 'i':
|
2012-02-01 10:21:49 +04:00
|
|
|
opt->init_file = string(optarg);
|
2011-11-12 04:24:19 +04:00
|
|
|
break;
|
|
|
|
case 'v':
|
2012-02-01 10:21:49 +04:00
|
|
|
setverboselevel(strtol(optarg, NULL, 10));
|
2011-11-12 04:24:19 +04:00
|
|
|
break;
|
2011-09-07 12:08:35 +04:00
|
|
|
#ifdef WITH_THREADS
|
2011-11-12 04:24:19 +04:00
|
|
|
case 'T':
|
2012-02-01 10:21:49 +04:00
|
|
|
opt->num_threads = strtol(optarg, NULL, 10);
|
|
|
|
if (opt->num_threads < 1) opt->num_threads = 1;
|
2011-11-12 04:24:19 +04:00
|
|
|
break;
|
2011-09-07 12:08:35 +04:00
|
|
|
#endif
|
2011-11-12 04:24:19 +04:00
|
|
|
case 'a':
|
2012-02-01 10:21:49 +04:00
|
|
|
opt->shard_count = strtof(optarg, NULL);
|
2011-11-12 04:24:19 +04:00
|
|
|
break;
|
|
|
|
case 'b':
|
2012-02-01 10:21:49 +04:00
|
|
|
opt->shard_size = strtof(optarg, NULL);
|
2011-11-12 04:24:19 +04:00
|
|
|
break;
|
|
|
|
case 'h':
|
|
|
|
usage(0);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
usage(1);
|
2008-05-15 15:06:32 +04:00
|
|
|
}
|
|
|
|
}
|
2012-02-01 10:21:49 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
} // anonymous namespace
|
|
|
|
|
|
|
|
int main(int argc, char **argv)
|
|
|
|
{
|
|
|
|
ResetUserTime();
|
|
|
|
|
|
|
|
ProgramOption option;
|
|
|
|
ParseCommandOptions(argc, argv, &option);
|
|
|
|
|
|
|
|
vector<unsigned> to_optimize;
|
|
|
|
vector<vector<parameter_t> > start_list;
|
|
|
|
vector<parameter_t> min;
|
|
|
|
vector<parameter_t> max;
|
|
|
|
// NOTE: those mins and max are the bound for the starting points of the algorithm, not strict bound on the result!
|
|
|
|
|
|
|
|
if (option.pdim < 0)
|
2011-09-15 21:45:35 +04:00
|
|
|
usage(1);
|
|
|
|
|
2012-02-01 10:21:49 +04:00
|
|
|
cerr << "shard_size = " << option.shard_size << " shard_count = " << option.shard_count << endl;
|
|
|
|
if (option.shard_size && !option.shard_count) {
|
2011-09-15 21:45:35 +04:00
|
|
|
cerr << "Error: shard-size provided without shard-count" << endl;
|
|
|
|
exit(1);
|
|
|
|
}
|
2012-02-01 10:21:49 +04:00
|
|
|
if (option.shard_size > 1 || option.shard_size < 0) {
|
2011-09-15 21:45:35 +04:00
|
|
|
cerr << "Error: shard-size should be between 0 and 1" << endl;
|
|
|
|
exit(1);
|
|
|
|
}
|
2009-02-12 15:58:27 +03:00
|
|
|
|
2012-02-01 10:21:49 +04:00
|
|
|
if (option.has_seed) {
|
|
|
|
cerr << "Seeding random numbers with " << option.seed << endl;
|
|
|
|
srandom(option.seed);
|
2009-02-12 15:58:27 +03:00
|
|
|
} else {
|
2011-02-24 15:42:19 +03:00
|
|
|
cerr << "Seeding random numbers with system clock " << endl;
|
|
|
|
srandom(time(NULL));
|
2009-02-12 15:58:27 +03:00
|
|
|
}
|
2011-02-24 15:42:19 +03:00
|
|
|
|
2011-07-23 04:24:45 +04:00
|
|
|
// read in starting points
|
2012-02-01 10:21:49 +04:00
|
|
|
string onefile;
|
|
|
|
while (!option.init_file.empty()) {
|
|
|
|
getNextPound(option.init_file, onefile, ",");
|
2011-07-23 04:24:45 +04:00
|
|
|
vector<parameter_t> start;
|
|
|
|
ifstream opt(onefile.c_str());
|
2012-02-01 10:21:49 +04:00
|
|
|
if (opt.fail()) {
|
|
|
|
cerr << "could not open initfile: " << option.init_file << endl;
|
2011-07-23 04:24:45 +04:00
|
|
|
exit(3);
|
|
|
|
}
|
2012-02-01 10:21:49 +04:00
|
|
|
start.resize(option.pdim);//to do:read from file
|
2011-07-23 04:24:45 +04:00
|
|
|
int j;
|
2012-02-01 10:21:49 +04:00
|
|
|
for (j = 0; j < option.pdim && !opt.fail(); j++) {
|
|
|
|
opt >> start[j];
|
|
|
|
}
|
|
|
|
if (j < option.pdim) {
|
|
|
|
cerr << option.init_file << ":Too few starting weights." << endl;
|
2011-07-23 04:24:45 +04:00
|
|
|
exit(3);
|
|
|
|
}
|
|
|
|
start_list.push_back(start);
|
|
|
|
// for the first time, also read in the min/max values for scores
|
|
|
|
if (start_list.size() == 1) {
|
2012-02-01 10:21:49 +04:00
|
|
|
min.resize(option.pdim);
|
|
|
|
for (j = 0; j < option.pdim && !opt.fail(); j++) {
|
|
|
|
opt >> min[j];
|
|
|
|
}
|
|
|
|
if (j < option.pdim) {
|
|
|
|
cerr << option.init_file << ":Too few minimum weights." << endl;
|
|
|
|
cerr << "error could not initialize start point with " << option.init_file << endl;
|
|
|
|
cerr << "j: " << j << ", pdim: " << option.pdim << endl;
|
2011-07-23 04:24:45 +04:00
|
|
|
exit(3);
|
|
|
|
}
|
2012-02-01 10:21:49 +04:00
|
|
|
max.resize(option.pdim);
|
|
|
|
for (j = 0; j < option.pdim && !opt.fail(); j++) {
|
|
|
|
opt >> max[j];
|
|
|
|
}
|
|
|
|
if (j < option.pdim) {
|
|
|
|
cerr << option.init_file << ":Too few maximum weights." << endl;
|
2011-07-23 04:24:45 +04:00
|
|
|
exit(3);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
opt.close();
|
2011-07-04 01:01:16 +04:00
|
|
|
}
|
2008-05-16 14:57:24 +04:00
|
|
|
|
2008-11-18 21:51:02 +03:00
|
|
|
vector<string> ScoreDataFiles;
|
2012-02-01 10:21:49 +04:00
|
|
|
if (option.scorer_file.length() > 0) {
|
|
|
|
Tokenize(option.scorer_file.c_str(), ',', &ScoreDataFiles);
|
2008-11-18 21:51:02 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
vector<string> FeatureDataFiles;
|
2012-02-01 10:21:49 +04:00
|
|
|
if (option.feature_file.length() > 0) {
|
|
|
|
Tokenize(option.feature_file.c_str(), ',', &FeatureDataFiles);
|
2008-11-18 21:51:02 +03:00
|
|
|
}
|
|
|
|
|
2011-02-24 15:42:19 +03:00
|
|
|
if (ScoreDataFiles.size() != FeatureDataFiles.size()) {
|
2008-11-18 21:51:02 +03:00
|
|
|
throw runtime_error("Error: there is a different number of previous score and feature files");
|
|
|
|
}
|
|
|
|
|
2011-11-12 03:58:23 +04:00
|
|
|
// it make sense to know what parameter set were used to generate the nbest
|
2012-02-01 10:21:49 +04:00
|
|
|
Scorer *TheScorer = ScorerFactory::getScorer(option.scorer_type, option.scorer_config);
|
2008-05-21 14:03:48 +04:00
|
|
|
|
2008-11-18 21:51:02 +03:00
|
|
|
//load data
|
2008-05-27 20:50:52 +04:00
|
|
|
Data D(*TheScorer);
|
2012-02-01 10:21:49 +04:00
|
|
|
|
|
|
|
for (size_t i = 0; i < ScoreDataFiles.size(); i++) {
|
2012-02-01 11:15:22 +04:00
|
|
|
cerr<<"Loading Data from: "<< ScoreDataFiles.at(i) << " and " << FeatureDataFiles.at(i) << endl;
|
2008-11-18 21:51:02 +03:00
|
|
|
D.load(FeatureDataFiles.at(i), ScoreDataFiles.at(i));
|
|
|
|
}
|
2008-05-21 14:03:48 +04:00
|
|
|
|
2011-12-12 17:48:42 +04:00
|
|
|
//ADDED_BY_TS
|
|
|
|
D.remove_duplicates();
|
|
|
|
//END_ADDED
|
|
|
|
|
2010-01-08 18:12:28 +03:00
|
|
|
PrintUserTime("Data loaded");
|
2011-02-24 15:42:19 +03:00
|
|
|
|
2011-09-07 20:37:33 +04:00
|
|
|
// starting point score over latest n-best, accumulative n-best
|
|
|
|
//vector<unsigned> bests;
|
|
|
|
//compute bests with sparse features needs to be implemented
|
|
|
|
//currently sparse weights are not even loaded
|
|
|
|
//statscore_t score = TheScorer->score(bests);
|
|
|
|
|
2012-02-01 10:21:49 +04:00
|
|
|
if (option.to_optimize_str.length() > 0) {
|
|
|
|
cerr << "Weights to optimize: " << option.to_optimize_str << endl;
|
2010-01-08 18:12:28 +03:00
|
|
|
|
2011-11-12 03:58:23 +04:00
|
|
|
// Parse string to get weights to optimize, and set them as active
|
2012-02-01 10:21:49 +04:00
|
|
|
string substring;
|
2010-01-08 18:12:28 +03:00
|
|
|
int index;
|
2012-02-01 10:21:49 +04:00
|
|
|
while (!option.to_optimize_str.empty()) {
|
|
|
|
getNextPound(option.to_optimize_str, substring, ",");
|
2010-01-08 18:12:28 +03:00
|
|
|
index = D.getFeatureIndex(substring);
|
|
|
|
cerr << "FeatNameIndex:" << index << " to insert" << endl;
|
|
|
|
//index = strtol(substring.c_str(), NULL, 10);
|
2012-02-01 10:21:49 +04:00
|
|
|
if (index >= 0 && index < option.pdim) {
|
|
|
|
to_optimize.push_back(index);
|
2011-02-24 15:42:19 +03:00
|
|
|
} else {
|
2012-02-01 10:21:49 +04:00
|
|
|
cerr << "Index " << index << " is out of bounds. Allowed indexes are [0," << option.pdim - 1 << "]." << endl;
|
2011-02-24 15:42:19 +03:00
|
|
|
}
|
2010-01-08 18:12:28 +03:00
|
|
|
}
|
2011-02-24 15:42:19 +03:00
|
|
|
} else {
|
2010-01-08 18:12:28 +03:00
|
|
|
//set all weights as active
|
2012-02-01 10:21:49 +04:00
|
|
|
to_optimize.resize(option.pdim);//We'll optimize on everything
|
|
|
|
for (int i = 0; i < option.pdim; i++) {
|
|
|
|
to_optimize[i] = 1;
|
2011-02-24 15:42:19 +03:00
|
|
|
}
|
2010-01-08 18:12:28 +03:00
|
|
|
}
|
|
|
|
|
2011-09-07 20:37:33 +04:00
|
|
|
// treat sparse features just like regular features
|
|
|
|
if (D.hasSparseFeatures()) {
|
|
|
|
D.mergeSparseFeatures();
|
|
|
|
}
|
|
|
|
|
2009-01-07 16:30:06 +03:00
|
|
|
|
2011-09-07 12:08:35 +04:00
|
|
|
#ifdef WITH_THREADS
|
2012-02-01 10:21:49 +04:00
|
|
|
cerr << "Creating a pool of " << option.num_threads << " threads" << endl;
|
|
|
|
Moses::ThreadPool pool(option.num_threads);
|
2011-09-07 12:08:35 +04:00
|
|
|
#endif
|
|
|
|
|
2012-02-01 10:21:49 +04:00
|
|
|
Point::setpdim(option.pdim);
|
|
|
|
Point::setdim(to_optimize.size());
|
2011-09-07 12:08:35 +04:00
|
|
|
|
2011-09-15 21:45:35 +04:00
|
|
|
//starting points consist of specified points and random restarts
|
|
|
|
vector<Point> startingPoints;
|
2011-02-24 15:42:19 +03:00
|
|
|
|
2011-09-15 21:45:35 +04:00
|
|
|
for (size_t i = 0; i < start_list.size(); ++i) {
|
2012-02-01 11:15:22 +04:00
|
|
|
startingPoints.push_back(Point(start_list[i], min, max));
|
2011-09-15 21:45:35 +04:00
|
|
|
}
|
2012-02-01 10:21:49 +04:00
|
|
|
|
|
|
|
for (int i = 0; i < option.ntry; ++i) {
|
2012-02-01 11:15:22 +04:00
|
|
|
startingPoints.push_back(Point(start_list[0], min, max));
|
2011-09-15 21:45:35 +04:00
|
|
|
startingPoints.back().Randomize();
|
|
|
|
}
|
|
|
|
|
|
|
|
vector<vector<OptimizationTask*> > allTasks(1);
|
|
|
|
|
|
|
|
//optional sharding
|
|
|
|
vector<Data> shards;
|
2012-02-01 10:21:49 +04:00
|
|
|
if (option.shard_count) {
|
|
|
|
D.createShards(option.shard_count, option.shard_size, option.scorer_config, shards);
|
|
|
|
allTasks.resize(option.shard_count);
|
2011-09-15 21:45:35 +04:00
|
|
|
}
|
|
|
|
|
2011-11-12 03:58:23 +04:00
|
|
|
// launch tasks
|
2012-02-01 11:15:22 +04:00
|
|
|
for (size_t i = 0; i < allTasks.size(); ++i) {
|
2011-09-15 21:45:35 +04:00
|
|
|
Data& data = D;
|
2012-02-01 10:21:49 +04:00
|
|
|
if (option.shard_count)
|
|
|
|
data = shards[i]; //use the sharded data if it exists
|
|
|
|
|
2011-09-15 21:45:35 +04:00
|
|
|
vector<OptimizationTask*>& tasks = allTasks[i];
|
2012-02-01 10:21:49 +04:00
|
|
|
Optimizer *O = OptimizerFactory::BuildOptimizer(option.pdim, to_optimize, start_list[0], option.optimize_type, option.nrandom);
|
2011-09-15 21:45:35 +04:00
|
|
|
O->SetScorer(data.getScorer());
|
|
|
|
O->SetFData(data.getFeatureData());
|
|
|
|
//A task for each start point
|
|
|
|
for (size_t j = 0; j < startingPoints.size(); ++j) {
|
2011-11-11 15:40:59 +04:00
|
|
|
OptimizationTask* task = new OptimizationTask(O, startingPoints[j]);
|
2011-09-15 21:45:35 +04:00
|
|
|
tasks.push_back(task);
|
2011-09-07 12:08:35 +04:00
|
|
|
#ifdef WITH_THREADS
|
2011-09-15 21:45:35 +04:00
|
|
|
pool.Submit(task);
|
2011-09-07 12:08:35 +04:00
|
|
|
#else
|
2011-09-15 21:45:35 +04:00
|
|
|
task->Run();
|
2011-09-07 12:08:35 +04:00
|
|
|
#endif
|
2011-09-15 21:45:35 +04:00
|
|
|
}
|
2011-09-07 12:08:35 +04:00
|
|
|
}
|
2011-09-15 21:45:35 +04:00
|
|
|
|
2011-11-12 03:58:23 +04:00
|
|
|
// wait for all threads to finish
|
2011-09-07 12:08:35 +04:00
|
|
|
#ifdef WITH_THREADS
|
|
|
|
pool.Stop(true);
|
|
|
|
#endif
|
|
|
|
|
2011-09-15 21:45:35 +04:00
|
|
|
statscore_t total = 0;
|
|
|
|
Point totalP;
|
|
|
|
|
2011-11-12 03:58:23 +04:00
|
|
|
// collect results
|
2011-09-15 21:45:35 +04:00
|
|
|
for (size_t i = 0; i < allTasks.size(); ++i) {
|
2012-02-01 10:21:49 +04:00
|
|
|
statscore_t best = 0, mean = 0, var = 0;
|
2011-09-15 21:45:35 +04:00
|
|
|
Point bestP;
|
|
|
|
for (size_t j = 0; j < allTasks[i].size(); ++j) {
|
|
|
|
statscore_t score = allTasks[i][j]->getScore();
|
|
|
|
mean += score;
|
2012-02-01 10:21:49 +04:00
|
|
|
var += score * score;
|
2011-09-15 21:45:35 +04:00
|
|
|
if (score > best) {
|
|
|
|
bestP = allTasks[i][j]->getPoint();
|
|
|
|
best = score;
|
|
|
|
}
|
2011-02-24 15:42:19 +03:00
|
|
|
}
|
2011-09-15 21:45:35 +04:00
|
|
|
|
2012-02-01 10:21:49 +04:00
|
|
|
mean /= (float)option.ntry;
|
|
|
|
var /= (float)option.ntry;
|
|
|
|
var = sqrt(abs(var - mean * mean));
|
|
|
|
|
|
|
|
if (verboselevel() > 1) {
|
|
|
|
cerr << "shard " << i << " best score: " << best << " variance of the score (for " << option.ntry << " try): " << var << endl;
|
|
|
|
}
|
2011-09-15 21:45:35 +04:00
|
|
|
|
|
|
|
totalP += bestP;
|
|
|
|
total += best;
|
2012-02-01 10:21:49 +04:00
|
|
|
if (verboselevel() > 1)
|
2011-09-15 21:45:35 +04:00
|
|
|
cerr << "bestP " << bestP << endl;
|
2008-05-15 18:04:42 +04:00
|
|
|
}
|
2011-09-07 12:08:35 +04:00
|
|
|
|
2011-09-15 21:45:35 +04:00
|
|
|
//cerr << "totalP: " << totalP << endl;
|
|
|
|
Point finalP = totalP * (1.0 / allTasks.size());
|
|
|
|
statscore_t final = total / allTasks.size();
|
|
|
|
|
2012-02-01 11:15:22 +04:00
|
|
|
if (verboselevel() > 1)
|
2011-09-15 21:45:35 +04:00
|
|
|
cerr << "bestP: " << finalP << endl;
|
2011-02-24 15:42:19 +03:00
|
|
|
|
2011-07-23 04:24:45 +04:00
|
|
|
// L1-Normalization of the best Point
|
2012-02-01 10:21:49 +04:00
|
|
|
if ((int)to_optimize.size() == option.pdim) {
|
2011-09-15 21:45:35 +04:00
|
|
|
finalP.NormalizeL1();
|
2012-02-01 10:21:49 +04:00
|
|
|
}
|
2011-01-25 19:10:47 +03:00
|
|
|
|
2011-09-15 21:45:35 +04:00
|
|
|
cerr << "Best point: " << finalP << " => " << final << endl;
|
2011-02-24 15:42:19 +03:00
|
|
|
ofstream res("weights.txt");
|
2012-02-01 10:21:49 +04:00
|
|
|
res << finalP << endl;
|
2011-02-24 15:42:19 +03:00
|
|
|
|
2011-11-11 15:40:59 +04:00
|
|
|
for (size_t i = 0; i < allTasks.size(); ++i) {
|
|
|
|
allTasks[i][0]->resetOptimizer();
|
|
|
|
for (size_t j = 0; j < allTasks[i].size(); ++j) {
|
|
|
|
delete allTasks[i][j];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
delete TheScorer;
|
2011-02-24 15:42:19 +03:00
|
|
|
PrintUserTime("Stopping...");
|
2012-02-01 10:21:49 +04:00
|
|
|
|
|
|
|
return 0;
|
2008-05-15 15:06:32 +04:00
|
|
|
}
|