00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
#include "Learner.h"
00046
00047
#include <plearn/io/TmpFilenames.h>
00048
00049
#include <plearn/base/stringutils.h>
00050
#include <plearn/io/MPIStream.h>
00051
#include <plearn/vmat/FileVMatrix.h>
00052
#include <plearn/vmat/RemoveRowsVMatrix.h>
00053
#include <plearn/sys/PLMPI.h>
00054
00055
namespace PLearn {
00056
using namespace std;
00057
00058 Vec Learner::tmp_input;
00059 Vec Learner::tmp_target;
00060 Vec Learner::tmp_weight;
00061 Vec Learner::tmp_output;
00062 Vec Learner::tmp_costs;
00063
00064 PStream& Learner::default_vlog()
00065 {
00066
00067
static PStream default_vlog(&cout);
00068 default_vlog.
outmode=PStream::raw_ascii;
00069
return default_vlog;
00070 }
00071 int Learner::use_file_if_bigger = 64000000L;
00072 bool Learner::force_saving_on_all_processes =
false;
00073
00074 Learner::Learner(
int the_inputsize,
int the_targetsize,
int the_outputsize)
00075 :train_objective_stream(0), epoch_(0), distributed_(false),
00076 inputsize_(the_inputsize), targetsize_(the_targetsize), outputsize_(the_outputsize),
00077 weightsize_(0), dont_parallelize(false), save_at_every_epoch(false), save_objective(true), best_step(0)
00078 {
00079
test_every = 1;
00080
minibatch_size = 1;
00081
setEarlyStopping(-1, 0, 0);
00082
vlog =
default_vlog();
00083
report_test_progress_every = 10000;
00084
measure_cpu_time_first=
false;
00085
setTestStatistics(
mean_stats() &
stderr_stats());
00086 }
00087
00088
PLEARN_IMPLEMENT_ABSTRACT_OBJECT(
Learner,
"DEPRECATED CLASS: Derive from PLearner instead",
"NO HELP");
00089 void Learner::makeDeepCopyFromShallowCopy(
CopiesMap& copies)
00090 {
00091 Object::makeDeepCopyFromShallowCopy(copies);
00092
00093
00094
00095
deepCopyField(
avg_objective, copies);
00096
deepCopyField(
avgsq_objective, copies);
00097
deepCopyField(
test_costfuncs, copies);
00098
deepCopyField(
test_statistics, copies);
00099 }
00100
00101 void Learner::outputResultLineToFile(
const string & fname,
const Vec& results,
bool append,
const string& names)
00102 {
00103
#if __GNUC__ < 3
00104
ofstream teststream(
fname.c_str(),ios::out|(append?ios::app:0));
00105
#else
00106
ofstream teststream(
fname.c_str(),ios_base::out|(append?ios_base::app:static_cast<ios::openmode>(0)));
00107
#endif
00108
00109
#if __GNUC__ < 3 && !defined(WIN32)
00110
if(teststream.tellp()==0)
00111
#else
00112
if(teststream.tellp() == streampos(0))
00113
#endif
00114
teststream <<
"#: epoch " << names <<
endl;
00115 teststream << setw(5) <<
epoch_ <<
" " << results <<
endl;
00116 }
00117
00118 string Learner::basename()
const
00119
{
00120
if(!
experiment_name.empty())
00121 {
00122
PLWARNING(
"** Warning: the experiment_name system is DEPRECATED, please use the expdir system from now on, through setExperimentDirectory, and don't set an experiment_name. For now I'll be using the specified experiment_name=%s as the default basename for your results, but this won't be supported in the future",
experiment_name.c_str());
00123
return experiment_name;
00124 }
00125
else if(
expdir.empty())
00126 {
00127
PLERROR(
"Problem in Learner: Please call setExperimentDirectory for your learner prior to calling a train/test");
00128 }
00129
else if(!
train_set)
00130 {
00131
PLWARNING(
"You should call setTrainingSet at the beginning of the train method in class %s ... Using 'unknown' as alias for now...",
classname().
c_str());
00132
return expdir +
"unknown";
00133 }
00134
else if(
train_set->getAlias().empty())
00135 {
00136
00137
return expdir +
"unknown";
00138 }
00139
return expdir+
train_set->getAlias();
00140 }
00141
00142
00143 void Learner::declareOptions(
OptionList& ol)
00144 {
00145
declareOption(ol,
"inputsize", &Learner::inputsize_, OptionBase::buildoption,
00146
"dimensionality of input vector \n");
00147
00148
declareOption(ol,
"outputsize", &Learner::outputsize_, OptionBase::buildoption,
00149
"dimensionality of output \n");
00150
00151
declareOption(ol,
"targetsize", &Learner::targetsize_, OptionBase::buildoption,
00152
"dimensionality of target \n");
00153
00154
declareOption(ol,
"weightsize", &Learner::weightsize_, OptionBase::buildoption,
00155
"Number of weights within target. The last 'weightsize' fields of the target vector will be used as cost weights.\n"
00156
"This is usually 0 (no weight) or 1 (1 weight per sample). Special loss functions may be able to give a meaning\n"
00157
"to weightsize>1. Not all learners support weights.");
00158
00159
declareOption(ol,
"dont_parallelize", &Learner::dont_parallelize, OptionBase::buildoption,
00160
"By default, MPI parallelization done at a given level prevents further parallelization\n"
00161
"at levels further down. If true, this means *don't parallelize processing at this level*");
00162
00163
declareOption(ol,
"earlystop_testsetnum", &Learner::earlystop_testsetnum, OptionBase::buildoption,
00164
" index of test set (in test_sets) to use for early \n"
00165
" stopping (-1 means no early-stopping) \n");
00166
00167
declareOption(ol,
"earlystop_testresultindex", &Learner::earlystop_testresultindex, OptionBase::buildoption,
00168
" index of statistic (as returned by test) to use\n");
00169
00170
declareOption(ol,
"earlystop_max_degradation", &Learner::earlystop_max_degradation, OptionBase::buildoption,
00171
" maximum degradation in error from last best value\n");
00172
00173
declareOption(ol,
"earlystop_min_value", &Learner::earlystop_min_value, OptionBase::buildoption,
00174
" minimum error beyond which we stop\n");
00175
00176
declareOption(ol,
"earlystop_min_improvement", &Learner::earlystop_min_improvement, OptionBase::buildoption,
00177
" minimum improvement in error otherwise we stop\n");
00178
00179
declareOption(ol,
"earlystop_relative_changes", &Learner::earlystop_relative_changes, OptionBase::buildoption,
00180
" are max_degradation and min_improvement relative?\n");
00181
00182
declareOption(ol,
"earlystop_save_best", &Learner::earlystop_save_best, OptionBase::buildoption,
00183
" if yes, then return with saved 'best' model\n");
00184
00185
declareOption(ol,
"earlystop_max_degraded_steps", &Learner::earlystop_max_degraded_steps, OptionBase::buildoption,
00186
" ax. nb of steps beyond best found (-1 means ignore) \n");
00187
00188
declareOption(ol,
"save_at_every_epoch", &Learner::save_at_every_epoch, OptionBase::buildoption,
00189
" save learner at each epoch?\n");
00190
00191
declareOption(ol,
"save_objective", &Learner::save_objective, OptionBase::buildoption,
00192
" save objective at each epoch?\n");
00193
00194
declareOption(ol,
"expdir", &Learner::expdir, OptionBase::buildoption,
00195
" The directory in which to save results \n");
00196
00197
declareOption(ol,
"test_costfuncs", &Learner::test_costfuncs, OptionBase::buildoption,
00198
" The cost functions used by the default useAndCost method \n");
00199
00200
declareOption(ol,
"test_statistics", &Learner::test_statistics, OptionBase::buildoption,
00201
" The test statistics used by the default test method \n",
00202
"mean_stats() & stderr_stats()");
00203
00204
declareOption(ol,
"test_every", &Learner::test_every, OptionBase::buildoption,
00205
" Compute cost on the test set every <test_every> steps (if 0, then no test is done during training\n");
00206
00207
declareOption(ol,
"minibatch_size", &Learner::minibatch_size,
00208 OptionBase::buildoption,
00209
" size of blocks over which to perform tests, calling 'apply' if >1, otherwise caling 'use'\n");
00210
00211 inherited::declareOptions(ol);
00212 }
00213
00214
00215 void Learner::setExperimentDirectory(
const string& the_expdir)
00216 {
00217
#if USING_MPI
00218
if(PLMPI::rank==0) {
00219
#endif
00220
if(!
force_mkdir(the_expdir))
00221 {
00222
PLERROR(
"In Learner::setExperimentDirectory Could not create experiment directory %s",the_expdir.c_str());}
00223
#if USING_MPI
00224
}
00225
#endif
00226
expdir =
abspath(the_expdir);
00227 }
00228
00229 void Learner::build_()
00230 {
00231
00232
earlystop_previousval = FLT_MAX;
00233
earlystop_minval = FLT_MAX;
00234 }
00235
00236 void Learner::build()
00237 {
00238 inherited::build();
00239
build_();
00240 }
00241
00242 void Learner::forget()
00243 {
00244
00245
earlystop_previousval = FLT_MAX;
00246
earlystop_minval = FLT_MAX;
00247
epoch_ = 0;
00248 }
00249
00250 void Learner::useAndCostOnTestVec(
const VMat& test_set,
int i,
const Vec& output,
const Vec& cost)
00251 {
00252
tmpvec.
resize(test_set.
width());
00253
if (
minibatch_size > 1)
00254 {
00255
Vec inputvec(
inputsize()*
minibatch_size);
00256
Vec targetvec(
targetsize()*
minibatch_size);
00257
for (
int k=0;
k<
minibatch_size;
k++)
00258 {
00259 test_set->getRow(i+
k,
tmpvec);
00260
for (
int j=0; j<
inputsize(); j++)
00261 inputvec[
k*
inputsize()+j] =
tmpvec[j];
00262
for (
int j=0; j<
targetsize(); j++)
00263 targetvec[
k*
targetsize()+j] = tmpvec[
inputsize()+j];
00264 }
00265
useAndCost(inputvec, targetvec, output, cost);
00266 }
00267
else
00268 {
00269 test_set->getRow(i,
tmpvec);
00270
useAndCost(
tmpvec.
subVec(0,
inputsize()),
tmpvec.
subVec(
inputsize(),
targetsize()), output, cost);
00271 }
00272 }
00273
00274 void Learner::useAndCost(
const Vec& input,
const Vec& target,
Vec output,
Vec cost)
00275 {
00276
use(input,output);
00277
computeCost(input, target, output, cost);
00278 }
00279
00280 void Learner::computeCost(
const Vec& input,
const Vec& target,
const Vec& output,
const Vec& cost)
00281 {
00282
00283
for (
int k=0;
k<
test_costfuncs.
size();
k++)
00284 cost[
k] =
test_costfuncs[
k](output, target);
00285 }
00286
00287 void Learner::setTestDuringTrain(ostream& out,
int every,
Array<VMat> testsets)
00288 {
00289
testout(&out);
00290
test_every = every;
00291
test_sets = testsets;
00292 }
00293
00294 void Learner::openTrainObjectiveStream()
00295 {
00296
string filename =
expdir.empty() ?
string(
"/dev/null") :
expdir+
"train.objective";
00297
if(
train_objective_stream)
00298
delete train_objective_stream;
00299
train_objective_stream =
new ofstream(filename.c_str(),ios::out|ios::app);
00300 ostream& out = *
train_objective_stream;
00301
if(out.bad())
00302
PLERROR(
"could not open file %s for appending",filename.c_str());
00303
00304
#if __GNUC__ < 3 && !defined(WIN32)
00305
if(out.tellp()==0)
00306
#else
00307
if(out.tellp() == streampos(0))
00308
#endif
00309
out <<
"# epoch | " <<
join(
trainObjectiveNames(),
" | ") <<
endl;
00310 }
00311
00312 ostream& Learner::getTrainObjectiveStream()
00313 {
00314
if(!
train_objective_stream)
00315
openTrainObjectiveStream();
00316
return *
train_objective_stream;
00317 }
00318
00320 void Learner::openTestResultsStreams()
00321 {
00322
freeTestResultsStreams();
00323
int n =
test_sets.
size();
00324
test_results_streams.
resize(n);
00325
for(
int k=0;
k<n;
k++)
00326 {
00327
string alias =
test_sets[
k]->getAlias();
00328
00329
00330
string filename = alias.empty() ?
string(
"/dev/null") :
expdir+alias+
".results";
00331
test_results_streams[
k] =
new ofstream(filename.c_str(), ios::out|ios::app);
00332 ostream& out = *
test_results_streams[
k];
00333
if(out.bad())
00334
PLERROR(
"In Learner::openTestResultsStreams could not open file %s for appending",filename.c_str());
00335
00336
#if __GNUC__ < 3 && !defined(WIN32)
00337
if(out.tellp() == 0)
00338
#else
00339
if(out.tellp() == streampos(0))
00340
#endif
00341
out <<
"#: epoch " <<
join(
testResultsNames(),
" ") <<
endl;
00342 }
00343 }
00344
00345 void Learner::freeTestResultsStreams()
00346 {
00347
int n =
test_results_streams.
size();
00348
for(
int k=0;
k<n;
k++)
00349
delete test_results_streams[
k];
00350
test_results_streams.
resize(0);
00351 }
00352
00353
00354 ostream& Learner::getTestResultsStream(
int k)
00355 {
00356
if(
test_results_streams.
size()==0)
00357
openTestResultsStreams();
00358
return *
test_results_streams[
k];
00359 }
00360
00361
00362 void Learner::setTestDuringTrain(
Array<VMat> testsets)
00363 {
test_sets = testsets; }
00364
00365 Learner::~Learner()
00366 {
00367
if(
train_objective_stream)
00368
delete train_objective_stream;
00369
freeTestResultsStreams();
00370 }
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381 void Learner::setEarlyStopping(
int which_testset,
int which_testresult,
00382
real max_degradation,
real min_value,
00383
real min_improvement,
bool relative_changes,
00384
bool save_best,
int max_degraded_steps)
00385 {
00386
earlystop_testsetnum = which_testset;
00387
earlystop_testresultindex = which_testresult;
00388
earlystop_max_degradation = max_degradation;
00389
earlystop_min_value = min_value;
00390
earlystop_previousval = FLT_MAX;
00391
earlystop_minval = FLT_MAX;
00392
earlystop_relative_changes = relative_changes;
00393
earlystop_min_improvement = min_improvement;
00394
earlystop_save_best = save_best;
00395
earlystop_max_degraded_steps = max_degraded_steps;
00396 }
00397
00398 bool Learner::measure(
int step,
const Vec& costs)
00399 {
00400
earlystop_min_value /=
minibatch_size;
00401
if (costs.
length()<1)
00402
PLERROR(
"Learner::measure: costs.length_=%d should be >0", costs.
length());
00403
00404
00405
00406
00407
00408
00409
00410
if (((!PLMPI::synchronized &&
each_cpu_saves_its_errors) || PLMPI::rank==0) &&
save_objective)
00411
outputResultLineToFile(
basename()+
".objective",costs,
true,
join(
trainObjectiveNames(),
" "));
00412
00413
bool muststop =
false;
00414
00415
if (((!PLMPI::synchronized &&
each_cpu_saves_its_errors) || PLMPI::rank==0) &&
save_at_every_epoch)
00416 {
00417
string fname =
basename()+
".epoch"+
tostring(
epoch())+
".psave";
00418
vlog <<
" >> Saving model in " <<
fname <<
endl;
00419
PLearn::save(
fname, *
this);
00420 }
00421
if ((
test_every != 0) && (step%
test_every==0))
00422 {
00423
int ntestsets =
test_sets.
size();
00424
Array<Vec> test_results(ntestsets);
00425
for (
int n=0; n<ntestsets; n++)
00426 {
00427 test_results[n] =
test(
test_sets[n]);
00428
if ((!PLMPI::synchronized &&
each_cpu_saves_its_errors) || PLMPI::rank==0)
00429
outputResultLineToFile(
basename()+
"."+
test_sets[n]->getAlias()+
".hist.results",test_results[n],
true,
00430
join(
testResultsNames(),
" "));
00431 }
00432
00433
if (ntestsets>0 &&
earlystop_testsetnum>=0)
00434 {
00435
real earlystop_currentval =
00436 test_results[earlystop_testsetnum][
earlystop_testresultindex];
00437
00438
00439
if ((
earlystop_relative_changes &&
00440 ((earlystop_currentval-
earlystop_minval >
00441
earlystop_max_degradation *
abs(
earlystop_minval))
00442 || (earlystop_currentval <
earlystop_min_value)
00443 || (
earlystop_previousval-earlystop_currentval <
00444
earlystop_min_improvement *
abs(
earlystop_previousval)))) ||
00445 (!
earlystop_relative_changes &&
00446 ((earlystop_currentval-
earlystop_minval >
earlystop_max_degradation)
00447 || (earlystop_currentval <
earlystop_min_value)
00448 || (
earlystop_previousval-earlystop_currentval <
00449
earlystop_min_improvement))) ||
00450 (
earlystop_max_degraded_steps>=0 &&
00451 (step-
best_step>=
earlystop_max_degraded_steps) &&
00452 (
earlystop_minval < FLT_MAX)))
00453 {
00454
if (
earlystop_save_best)
00455 {
00456
string fname =
basename()+
".psave";
00457
vlog <<
"Met early-stopping condition!" <<
endl;
00458
vlog <<
"earlystop_currentval = " << earlystop_currentval <<
endl;
00459
vlog <<
"earlystop_minval = " <<
earlystop_minval <<
endl;
00460
vlog <<
"threshold = " <<
earlystop_max_degradation*
earlystop_minval <<
endl;
00461
vlog <<
"STOPPING (reloading best model)" <<
endl;
00462
if(
expdir.empty())
00463
load();
00464
else
00465
PLearn::load(
fname,*
this);
00466 }
00467
else
00468 cout <<
"Result for benchmark is: " << test_results <<
endl;
00469 muststop =
true;
00470 }
00471
else
00472 {
00473
earlystop_previousval = earlystop_currentval;
00474
if (PLMPI::rank==0 &&
earlystop_save_best
00475 && (earlystop_currentval <
earlystop_minval))
00476 {
00477
string fname =
basename()+
".psave";
00478
vlog <<
"saving model in " <<
fname <<
" because of earlystopping / improvement: " <<
endl;
00479
vlog <<
"earlystop_currentval = " << earlystop_currentval <<
endl;
00480
vlog <<
"earlystop_minval = " <<
earlystop_minval <<
endl;
00481
PLearn::save(
fname,*
this);
00482
00483
if ((!PLMPI::synchronized &&
each_cpu_saves_its_errors) || PLMPI::rank==0)
00484
for (
int n=0; n<ntestsets; n++)
00485
outputResultLineToFile(
basename()+
"."+
test_sets[n]->getAlias()+
".results",test_results[n],
false,
00486
join(
testResultsNames(),
" "));
00487 cout <<
"Result for benchmark is: " << test_results <<
endl;
00488 }
00489 }
00490
if (earlystop_currentval <
earlystop_minval)
00491 {
00492
earlystop_minval = earlystop_currentval;
00493 best_step = step;
00494
if(PLMPI::rank==0)
00495
vlog <<
"currently best step at " << best_step <<
" with " << earlystop_currentval <<
" " << test_results <<
endl;
00496 }
00497 }
00498
else
00499
00500
if ((!PLMPI::synchronized &&
each_cpu_saves_its_errors) || PLMPI::rank==0)
00501
for (
int n=0; n<ntestsets; n++)
00502
outputResultLineToFile(
basename()+
"."+
test_sets[n]->getAlias()+
".results",test_results[n],
false,
00503
join(
testResultsNames(),
" "));
00504 }
00505
00506
for (
int i=0; i<
measurers.
size(); i++)
00507 muststop = muststop ||
measurers[i]->measure(step,costs);
00508
00509 ++
epoch_;
00510
00511
00512
00513
00514
00515
00516
return muststop;
00517 }
00518
00519
00520
00521
00522 void Learner::apply(
const VMat& data,
VMat outputs)
00523 {
00524
int n=data.
length();
00525
Vec data_row(data.
width());
00526
Vec input = data_row.
subVec(0,
inputsize());
00527
Vec output(
outputsize());
00528
for (
int i=0;i<n;i++)
00529 {
00530 data->getRow(i,data_row);
00531
use(input,output);
00532 outputs->putRow(i,output);
00533 }
00534 }
00535
00536
00537
00538
00539 void Learner::computeCosts(
const VMat& data,
VMat costs)
00540 {
00541
int n=data.
length();
00542
int ncostfuncs =
costsize();
00543
Vec output_row(
outputsize());
00544
Vec cost(ncostfuncs);
00545 cout << ncostfuncs <<
endl;
00546
for (
int i=0;i*
minibatch_size<n;i++)
00547 {
00548
useAndCostOnTestVec(data, i*
minibatch_size, output_row, cost);
00549 costs->putRow(i,cost);
00550 }
00551 }
00552
00553 void Learner::computeLeaveOneOutCosts(
const VMat& data,
VMat costsmat)
00554 {
00555
00556
00557
00558
Vec output(
outputsize());
00559
Vec cost(
costsize());
00560
00561
for(
int i=0; i<data.
length(); i++)
00562 {
00563
00564
train(
removeRow(data,i));
00565
useAndCostOnTestVec(data, i, output, cost);
00566
00567 costsmat->putRow(i,cost);
00568
vlog <<
'.' <<
flush;
00569
if(i%100==0)
00570
vlog <<
'\n' << i <<
flush;
00571 }
00572 }
00573
00574 void Learner::computeLeaveOneOutCosts(
const VMat& data,
VMat costsmat,
CostFunc costf)
00575 {
00576
00577
if( (costsmat.
length() != data.
length()) | (costsmat.
width()!=1))
00578
PLERROR(
"In Learner::computeLeaveOneOutCosts bad dimensions for costsmat VMat");
00579
Vec testsample(
inputsize()+
targetsize());
00580
Vec testinput = testsample.
subVec(0,
inputsize());
00581
Vec testtarget = testsample.
subVec(
inputsize(),
targetsize());
00582
Vec output(
outputsize());
00583
VMat subset;
00584
for(
int i=0; i<data.
length(); i++)
00585 {
00586 data->getRow(i,testsample);
00587
train(
removeRow(data,i));
00588
use(testinput,output);
00589 costsmat->put(i,0,costf(output,testtarget));
00590
vlog <<
'.' <<
flush;
00591
if(i%100==0)
00592
vlog <<
'\n' << i <<
flush;
00593 }
00594 }
00595
00596
00597
00598
00599 void Learner::applyAndComputeCosts(
const VMat& data,
VMat outputs,
VMat costs)
00600 {
00601
int n=data.
length();
00602
int ncostfuncs =
costsize();
00603
Vec output_row(
outputsize()*
minibatch_size);
00604
Vec costs_row(ncostfuncs);
00605
for (
int i=0;i*
minibatch_size<n;i++)
00606 {
00607
00608
useAndCostOnTestVec(data, i*
minibatch_size, output_row, costs_row);
00609
00610
00611
00612
for (
int k=0;
k<minibatch_size;
k++)
00613 {
00614 outputs->putRow(i+
k,output_row.
subVec(
k*
outputsize(),
outputsize()));
00615 }
00616 costs->putRow(i,costs_row);
00617 }
00618 }
00619
00620 Vec Learner::computeTestStatistics(
const VMat& costs)
00621 {
00622
return concat(
test_statistics.
computeStats(costs));
00623 }
00624
00625
00626
00627
00628
00629
00630
00634
00635 Vec Learner::test(
VMat test_set,
const string& save_test_outputs,
const string& save_test_costs)
00636 {
00637
int ncostfuncs =
costsize();
00638
00639
Vec output(
outputsize()*
minibatch_size);
00640
Vec cost(ncostfuncs);
00641
Mat output_block(
minibatch_size,
outputsize());
00642
Mat cost_block(
minibatch_size,
outputsize());
00643
if (
minibatch_size>1)
00644 cost_block.
resize(
minibatch_size,
costsize());
00645
00646
Vec result;
00647
00648
VMat outputs;
00649
VMat costs;
00650
if(PLMPI::rank==0 && !save_test_outputs.empty())
00651 outputs =
new FileVMatrix(save_test_outputs, test_set.
length(),
outputsize());
00652
00653
if(PLMPI::rank==0 && !save_test_costs.empty())
00654 costs =
new FileVMatrix(save_test_costs, test_set.
length(), ncostfuncs);
00655
00656
int l = test_set.
length();
00657
ProgressBar progbar(
vlog,
"Testing " + test_set->getAlias(), l);
00658
00659
00660
00661
00662
bool multipass =
test_statistics.
requiresMultiplePasses();
00663
00664
00665
if (PLMPI::rank==0 && save_test_costs.empty() && multipass)
00666 {
00667
TmpFilenames tmpfile(1);
00668
bool save_on_file = ncostfuncs*test_set.
length() >
use_file_if_bigger;
00669
if (save_on_file)
00670 costs =
new FileVMatrix(tmpfile.
addFilename(),test_set.
length(),ncostfuncs);
00671
else
00672 costs =
Mat(test_set.
length(),ncostfuncs);
00673 }
00674
00675
if(!multipass)
00676
test_statistics.
init(ncostfuncs);
00677
00678
if(USING_MPI && PLMPI::synchronized && !
dont_parallelize && PLMPI::size>1)
00679 {
00680
00681
#if USING_MPI
00682
PLMPI::synchronized =
false;
00683
if(PLMPI::rank==0)
00684 {
00685 MPIStreams mpistreams(200,200);
00686
00687
for(
int i=0; i<l; i++)
00688 {
00689
int pnum = 1 + i%(PLMPI::size-1);
00690
if(!save_test_outputs.empty())
00691 {
00692
00693
00694
PLearn::binread(mpistreams[pnum], output);
00695 outputs->putRow(i, output);
00696 }
00697
00698
00699
00700
00701
00702
00703
00704
PLearn::binread(mpistreams[pnum], cost);
00705
if(costs)
00706 costs->putRow(i,cost);
00707
if(!multipass)
00708
test_statistics.
update(cost);
00709 progbar(i);
00710 }
00711 }
00712
else
00713 {
00714 MPIStream mpistream(0,200,200);
00715
int step = PLMPI::size-1;
00716
for(
int i=PLMPI::rank-1; i<l; i+=step)
00717 {
00718
useAndCostOnTestVec(test_set, i, output, cost);
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
if(!save_test_outputs.empty())
00734
PLearn::binwrite(mpistream, output);
00735
00736
PLearn::binwrite(mpistream, cost);
00737 }
00738 }
00739
00740
00741
int result_len;
00742
if(PLMPI::rank==0)
00743 {
00744
if(!multipass)
00745 {
00746
test_statistics.
finish();
00747 result =
concat(
test_statistics.
getResults());
00748 }
00749
else
00750 result =
concat(
test_statistics.
computeStats(costs));
00751 result_len = result.
length();
00752 }
00753 MPI_Bcast(&result_len, 1, MPI_INT, 0, MPI_COMM_WORLD);
00754 result.
resize(result_len);
00755 MPI_Bcast(result.
data(), result.
length(), PLMPI_REAL, 0, MPI_COMM_WORLD);
00756 PLMPI::synchronized =
true;
00757
#endif
00758
}
00759
else
00760 {
00761
00762
for (
int i=0; i<l; i++)
00763 {
00764
if (i%10000<
minibatch_size)
stop_if_wanted();
00765
if (
minibatch_size>1 && i+
minibatch_size<l)
00766 {
00767
applyAndComputeCostsOnTestMat(test_set, i, output_block, cost_block);
00768 i+=
minibatch_size;
00769
if(outputs)
00770 outputs->putMat(i,0,output_block);
00771
if(costs)
00772 costs->putMat(i,0,cost_block);
00773
if(!multipass)
00774
test_statistics.
update(cost_block);
00775 }
00776
else
00777 {
00778
useAndCostOnTestVec(test_set, i, output, cost);
00779
if(outputs)
00780 outputs->putRow(i,output);
00781
if(costs)
00782 costs->putRow(i,cost);
00783
if(!multipass)
00784
test_statistics.
update(cost);
00785 }
00786
00787
00788
00789 progbar(i);
00790
00791 }
00792
00793
00794
if(!multipass)
00795 {
00796
test_statistics.
finish();
00797 result =
concat(
test_statistics.
getResults());
00798 }
00799
else
00800 result =
concat(
test_statistics.
computeStats(costs));
00801
00802 }
00803
00804
return result;
00805 }
00806
00807 void Learner::applyAndComputeCostsOnTestMat(
const VMat& test_set,
int i,
const Mat& output_block,
00808
const Mat& cost_block)
00809 {
00810
applyAndComputeCosts(test_set.
subMatRows(i,output_block.
length()),output_block,cost_block);
00811
00812 }
00813
00814 void Learner::setModel(
const Vec& options) {
00815
PLERROR(
"setModel: method not implemented for this Learner (and DEPRECATED!!! DON'T IMPLEMENT IT, DON'T CALL IT. SEE setOption INSTEAD)");
00816 }
00817
00818 int Learner::costsize()
const
00819
{
return test_costfuncs.
size(); }
00820
00821 Array<string> Learner::costNames()
const
00822
{
00823
Array<string> cost_names(
test_costfuncs.
size());
00824
for (
int i=0; i<cost_names.
size(); i++)
00825 cost_names[i] =
space_to_underscore(
test_costfuncs[i]->
info());
00826
return cost_names;
00827 }
00828
00829 Array<string> Learner::testResultsNames()
const
00830
{
00831
Array<string> cost_names =
costNames();
00832
Array<string> names(
test_statistics.
size()*cost_names.
size());
00833
int k=0;
00834
for (
int i=0;i<
test_statistics.
size();i++)
00835 {
00836
string stati =
test_statistics[i]->info();
00837
for (
int j=0;j<cost_names.
size();j++)
00838 names[
k++] =
space_to_underscore(cost_names[j] +
"." + stati);
00839 }
00840
return names;
00841 }
00842
00843 Array<string> Learner::trainObjectiveNames()
const
00844
{
return testResultsNames(); }
00845
00846 void Learner::oldwrite(ostream& out)
const
00847
{
00848
writeHeader(out,
"Learner",1);
00849
writeField(out,
"inputsize",
inputsize_);
00850
writeField(out,
"outputsize",
outputsize_);
00851
writeField(out,
"targetsize",
targetsize_);
00852
writeField(out,
"test_every",
test_every);
00853
writeField(out,
"earlystop_testsetnum",
earlystop_testsetnum);
00854
writeField(out,
"earlystop_testresultindex",
earlystop_testresultindex);
00855
writeField(out,
"earlystop_max_degradation",
earlystop_max_degradation);
00856
writeField(out,
"earlystop_min_value",
earlystop_min_value);
00857
writeField(out,
"earlystop_min_improvement",
earlystop_min_improvement);
00858
writeField(out,
"earlystop_relative_changes",
earlystop_relative_changes);
00859
writeField(out,
"earlystop_save_best",
earlystop_save_best);
00860
writeField(out,
"earlystop_max_degraded_steps",
earlystop_max_degraded_steps);
00861
writeField(out,
"save_at_every_epoch",
save_at_every_epoch);
00862
writeField(out,
"experiment_name",
experiment_name);
00863
writeField(out,
"test_costfuncs",
test_costfuncs);
00864
writeField(out,
"test_statistics",
test_statistics);
00865
writeFooter(out,
"Learner");
00866 }
00867
00868 void Learner::oldread(istream& in)
00869 {
00870
int version=
readHeader(in,
"Learner");
00871
if(version>=2)
00872 {
00873
readField(in,
"expdir",
expdir);
00874
readField(in,
"epoch",
epoch_);
00875 }
00876
readField(in,
"inputsize",
inputsize_);
00877
readField(in,
"outputsize",
outputsize_);
00878
readField(in,
"targetsize",
targetsize_);
00879
readField(in,
"test_every",
test_every);
00880
readField(in,
"earlystop_testsetnum",
earlystop_testsetnum);
00881
readField(in,
"earlystop_testresultindex",
earlystop_testresultindex);
00882
readField(in,
"earlystop_max_degradation",
earlystop_max_degradation);
00883
readField(in,
"earlystop_min_value",
earlystop_min_value);
00884
readField(in,
"earlystop_min_improvement",
earlystop_min_improvement);
00885
readField(in,
"earlystop_relative_changes",
earlystop_relative_changes);
00886
readField(in,
"earlystop_save_best",
earlystop_save_best);
00887
if (version>=1)
00888
readField(in,
"earlystop_max_degraded_steps",
earlystop_max_degraded_steps);
00889
else
00890
earlystop_max_degraded_steps=-1;
00891
readField(in,
"save_at_every_epoch",
save_at_every_epoch);
00892
readField(in,
"experiment_name",
experiment_name);
00893
readField(in,
"test_costfuncs",
test_costfuncs);
00894
readField(in,
"test_statistics",
test_statistics);
00895
readFooter(in,
"Learner");
00896 }
00897
00898 void Learner::save(
const string& filename)
const
00899
{
00900
#if USING_MPI
00901
if (PLMPI::rank!=0 && !
force_saving_on_all_processes)
00902
return;
00903
#endif
00904
if(!filename.empty())
00905 Object::save(filename);
00906
else if(!
experiment_name.empty())
00907 Object::save(
experiment_name);
00908
else
00909
PLERROR(
"Called Learner::save with an empty filename, while experiment_name is also empty. What file name am I supposed to use???? Anyway this method is DEPRECATED, you should call directly function PLearn::save(whatever_filename_you_want, the_object) ");
00910 }
00911
00912 void Learner::load(
const string& filename)
00913 {
00914
if (!filename.empty())
00915 Object::load(filename);
00916
else if (!
experiment_name.empty())
00917 Object::load(
experiment_name);
00918
else
00919
PLERROR(
"Called Learner::load with an empty filename, while experiment_name is also empty. What file name am I supposed to use???? Anyway this method is DEPRECATED, you should call directly function PLearn::load(whatever_filename_you_want, the_object) ");
00920 }
00921
00922 void Learner::stop_if_wanted()
00923 {
00924
string stopping_filename =
basename()+
".stop";
00925
if (
file_exists(stopping_filename.c_str()))
00926 {
00927
#ifdef PROFILE
00928
string profile_report_name =
basename();
00929
#if USING_MPI
00930
profile_report_name +=
"_r" +
tostring(PLMPI::rank);;
00931
#endif
00932
profile_report_name +=
".profile";
00933 ofstream profile_report(profile_report_name.c_str());
00934 Profiler::report(profile_report);
00935
#endif
00936
#if USING_MPI
00937
MPI_Barrier(MPI_COMM_WORLD);
00938
if (PLMPI::rank==0)
00939 {
00940
string fname =
basename()+
".stopped.psave";
00941
PLearn::save(
fname,*
this);
00942
vlog <<
"saving and quitting because of stop signal" <<
endl;
00943 unlink(stopping_filename.c_str());
00944 }
00945 exit(0);
00946
#else
00947
unlink(stopping_filename.c_str());
00948 exit(0);
00949
#endif
00950
}
00951 }
00952
00953
00954
00955
00956 void Learner::computeOutput(
const VVec& input,
Vec& output)
00957 {
00958
tmp_input.
resize(input.
length());
00959
tmp_input << input;
00960
use(
tmp_input,output);
00961 }
00962
00963
00964
00965
00966 void Learner::computeCostsFromOutputs(
const VVec& input,
const Vec& output,
00967
const VVec& target,
const VVec& weight,
00968
Vec& costs)
00969 {
00970
tmp_input.
resize(input.
length());
00971
tmp_input << input;
00972
tmp_target.
resize(target.
length());
00973
tmp_target << target;
00974
computeCost(input, target, output, costs);
00975
00976
int nw = weight.
length();
00977
if(nw>0)
00978 {
00979
tmp_weight.
resize(nw);
00980
tmp_weight << weight;
00981
if(nw==1)
00982 costs *=
tmp_weight[0];
00983
else if(nw==costs.
length())
00984 costs *= tmp_weight;
00985
else
00986
PLERROR(
"In computeCostsFromOutputs: don't know how to handle cost-weight vector of length %d while output vector has length %d", nw, output.
length());
00987 }
00988 }
00989
00990
00991 void Learner::computeOutputAndCosts(
const VVec& input,
VVec& target,
const VVec& weight,
00992
Vec& output,
Vec& costs)
00993 {
00994
computeOutput(input, output);
00995
computeCostsFromOutputs(input, output, target, weight, costs);
00996 }
00997
00998 void Learner::computeCosts(
const VVec& input,
VVec& target,
VVec& weight,
00999
Vec& costs)
01000 {
01001
tmp_output.
resize(
outputsize());
01002
computeOutputAndCosts(input, target, weight,
tmp_output, costs);
01003 }
01004
01005
01006 void Learner::newtrain(
VecStatsCollector& stats)
01007 {
PLERROR(
"newtrain not yet implemented for this learner"); }
01008
01009
01010 void Learner::newtest(
VMat testset,
VecStatsCollector& test_stats,
01011
VMat testoutputs,
VMat testcosts)
01012 {
01013
PLERROR(
"Learner::newtrain not yet implemented");
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049 }
01050
01051
01052 }
01053