1305 lines
44 KiB
C++
1305 lines
44 KiB
C++
/*
|
|
|
|
EGYPT Toolkit for Statistical Machine Translation
|
|
Written by Yaser Al-Onaizan, Jan Curin, Michael Jahr, Kevin Knight, John Lafferty, Dan Melamed, David Purdy, Franz Och, Noah Smith, and David Yarowsky.
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation; either version 2
|
|
of the License, or (at your option) any later version.
|
|
|
|
This program 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 General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
|
USA.
|
|
|
|
*/
|
|
#include "model3.h"
|
|
#include "collCounts.h"
|
|
#include "Globals.h"
|
|
#include "utility.h"
|
|
#include "transpair_model5.h"
|
|
#include "transpair_modelhmm.h"
|
|
#include "Parameter.h"
|
|
|
|
#define TRICKY_IBM3_TRAINING
|
|
|
|
GLOBAL_PARAMETER(int,M4_Dependencies,"depm4","d_{=1}: &1:l, &2:m, &4:F, &8:E, d_{>1}&16:l, &32:m, &64:F, &128:E",PARLEV_MODELS,76)
|
|
;
|
|
GLOBAL_PARAMETER(int,M5_Dependencies,"depm5","d_{=1}: &1:l, &2:m, &4:F, &8:E, d_{>1}&16:l, &32:m, &64:F, &128:E",PARLEV_MODELS,68)
|
|
;
|
|
GLOBAL_PARAMETER4(int,Model3_Dump_Freq,"MODEL 345 DUMP FREQUENCY","MODEL 3 DUMP FREQUENCY","t3","t345","dump frequency of Model 3/4/5",PARLEV_OUTPUT,0)
|
|
;
|
|
|
|
/*model3::model3(model2& m2) :
|
|
model2(m2),dTable( amodel<PROB>(true)), dCountTable(true),
|
|
nTable( nmodel<PROB>(m2.getNoEnglishWords()+1, MAX_FERTILITY)),
|
|
nCountTable(m2.getNoEnglishWords()+1, MAX_FERTILITY),h(0)
|
|
{}*/
|
|
|
|
extern int Transfer_Dump_Freq;
|
|
|
|
model3::model3(model2& m2, amodel<PROB>& d, nmodel<PROB>& n) :
|
|
model2(m2), dTable(d), dCountTable(true), nTable(n),//m2.getNoEnglishWords()+1, MAX_FERTILITY),
|
|
nCountTable(m2.getNoEnglishWords()+1, MAX_FERTILITY), h(0)
|
|
{
|
|
ewordclasses = fwordclasses = NULL;
|
|
}
|
|
|
|
model3::model3(model3& m3, amodel<PROB>& d, nmodel<PROB>& n, amodel<COUNT>& a) :
|
|
model2(*(&m3), m3.aTable, a), dTable(d), dCountTable(true), nTable(n),//m2.getNoEnglishWords()+1, MAX_FERTILITY),
|
|
nCountTable(m3.getNoEnglishWords()+1, MAX_FERTILITY), h(0)
|
|
{
|
|
ewordclasses = fwordclasses = NULL;
|
|
}
|
|
|
|
void model3::load_tables(const char *nfile, const char *dfile,
|
|
const char *p0file)
|
|
{
|
|
cout << "Model3: loading n, d, p0 tables \n";
|
|
|
|
nTable.readNTable(nfile);
|
|
dTable.readTable(dfile);
|
|
ifstream inf(p0file);
|
|
if ( !inf)
|
|
cerr << "Can not open: " << p0file << '\n';
|
|
else {
|
|
cout << "Reading p0 value from " << p0file << "\n";
|
|
inf >> p0;
|
|
inf.close();
|
|
p1 = 1 - p0;
|
|
}
|
|
cout << "p0 is: " << p0 << " p1:" << p1 << '\n';
|
|
}
|
|
|
|
model3::~model3()
|
|
{
|
|
dTable.clear();
|
|
dCountTable.clear();
|
|
nTable.clear();
|
|
nCountTable.clear();
|
|
if(h==NULL && ewordclasses!=NULL && fwordclasses!=NULL) {
|
|
delete ewordclasses;
|
|
delete fwordclasses;
|
|
}
|
|
}
|
|
|
|
void model3::em(int noIterations, sentenceHandler& sHandler1)
|
|
{
|
|
|
|
LogProb all_prob, aprob, temp;
|
|
WordIndex i, j, l, m;
|
|
time_t it_st, st, it_fn, fn;
|
|
string tfile, dfile, nfile, p0file, afile, number;
|
|
|
|
st = time(NULL) ;
|
|
cout << "\n" << "Starting Model3: Training";
|
|
// sentenceHandler sHandler1(efFilename.c_str());
|
|
sHandler1.rewind();
|
|
for (int it=1; it <= noIterations; it++) {
|
|
it_st = time(NULL) ;
|
|
cout << "\n" << "Model3: Iteration " << it;
|
|
|
|
// set up the names of the files where the tables will be printed
|
|
const string number = represent_number(it);
|
|
tfile = Prefix + ".t3." + number;
|
|
afile = Prefix + ".a3." + number;
|
|
nfile = Prefix + ".n3." + number;
|
|
dfile = Prefix + ".d3." + number;
|
|
p0file = Prefix + ".p0_3." + number;
|
|
// tCountTable.clear();
|
|
dCountTable.clear();
|
|
nCountTable.clear();
|
|
p0_count = 0.0;
|
|
p1_count = 0.0;
|
|
all_prob = 0;
|
|
sentPair sent;
|
|
while (sHandler1.getNextSentence(sent)) {
|
|
Vector<WordIndex>& es = sent.eSent;
|
|
Vector<WordIndex>& fs = sent.fSent;
|
|
const float count = sent.getCount();
|
|
if ((sent.sentenceNo % 1000) == 0)
|
|
cout <<sent.sentenceNo << '\n';
|
|
Vector<WordIndex> A(fs.size(),/*-1*/0);
|
|
Vector<WordIndex> Fert(es.size(),0);
|
|
LogProb lcount=(LogProb)count;
|
|
l = es.size()-1;
|
|
m = fs.size()-1;
|
|
WordIndex x, y;
|
|
all_prob = prob_of_target_given_source(tTable, fs, es);
|
|
if (all_prob == 0)
|
|
cout << "\n" <<"all_prob = 0";
|
|
|
|
for (x = 0; x < pow(l+1.0, double(m)) ; x++) { // For all possible alignmets A
|
|
y = x;
|
|
for (j = 1; j <= m; j++) {
|
|
A[j] = y % (l+1);
|
|
y /= (l+1);
|
|
}
|
|
for (i = 0; i <= l; i++)
|
|
Fert[i] = 0;
|
|
for (j = 1; j <= m; j++)
|
|
Fert[A[j]]++;
|
|
if (2 * Fert[0] <= m) {
|
|
/* consider alignments that has Fert[0] less than
|
|
half the number of words in French sentence */
|
|
aprob = prob_of_target_and_alignment_given_source(A, Fert,
|
|
tTable, fs, es);
|
|
temp = aprob/all_prob;
|
|
LogProb templcount = temp*lcount;
|
|
|
|
for (j = 1; j <= m; j++) {
|
|
tTable.incCount(es[A[j]], fs[j], templcount);
|
|
if (0 != A[j])
|
|
dCountTable.addValue(j, A[j], l, m, templcount);
|
|
}
|
|
for (i = 0; i <= l; i++) {
|
|
nCountTable.addValue(es[i], Fert[i], templcount);
|
|
//cout << "AFTER INC2: " << templcount << " " << nCountTable.getRef(es[i], Fert[i]) << '\n';
|
|
}
|
|
p1_count += double(temp) * (Fert[0] * count);
|
|
p0_count += double(temp) * ((m - 2 * Fert[0]) * count);
|
|
}
|
|
} /* of looping over all alignments */
|
|
} /* of sentence pair E, F */
|
|
sHandler1.rewind();
|
|
|
|
// normalize tables
|
|
if (OutputInAachenFormat==1)
|
|
tTable.printCountTable(tfile.c_str(), Elist.getVocabList(),
|
|
Flist.getVocabList(), 1);
|
|
tTable.normalizeTable(Elist, Flist);
|
|
aCountTable.normalize(aTable);
|
|
dCountTable.normalize(dTable);
|
|
nCountTable.normalize(nTable, &Elist.getVocabList());
|
|
|
|
// normalize p1 & p0
|
|
|
|
if (p1_count + p0_count != 0) {
|
|
p1 = p1_count / (p1_count + p0_count );
|
|
p0 = 1 - p1;
|
|
} else {
|
|
p1 = p0 = 0;
|
|
}
|
|
// print tables
|
|
if (OutputInAachenFormat==0)
|
|
tTable.printProbTable(tfile.c_str(), Elist.getVocabList(),
|
|
Flist.getVocabList(), OutputInAachenFormat);
|
|
dTable.printTable(dfile.c_str());
|
|
nTable.printNTable(Elist.uniqTokens(), nfile.c_str(),
|
|
Elist.getVocabList(), OutputInAachenFormat);
|
|
ofstream of(p0file.c_str());
|
|
of << p0;
|
|
of.close();
|
|
it_fn = time(NULL) ;
|
|
cout << "\n" << "Model3 Iteration "<<it<<" took: " << difftime(it_fn,
|
|
it_st) << " seconds\n";
|
|
|
|
} /* of iterations */
|
|
fn = time(NULL) ;
|
|
cout << "\n" << "Entire Model3 Training took: " << difftime(fn, st)
|
|
<< " seconds\n";
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
/*
|
|
void simpleModel3Test()
|
|
{
|
|
PositionIndex l=6;
|
|
PositionIndex m=8;
|
|
alignment al(l,m);
|
|
al.set(1,1);
|
|
al.set(2,2);
|
|
al.set(3,3);
|
|
al.set(4,2);
|
|
al.set(5,0);
|
|
al.set(6,6);
|
|
al.set(7,3);
|
|
al.set(8,4);
|
|
cout << al;
|
|
PositionIndex prev_cept=0;
|
|
PositionIndex vac_all=m;
|
|
Vector<char> vac(m+1,0);
|
|
for(PositionIndex i=1;i<=l;i++)
|
|
{
|
|
PositionIndex cur_j=al.als_i[i];
|
|
cout << "LOOP: " << i << " " << cur_j << '\n';
|
|
PositionIndex prev_j=0;
|
|
PositionIndex k=0;
|
|
if(cur_j) { // process first word of cept
|
|
k++;
|
|
vac_all--;
|
|
assert(vac[cur_j]==0);
|
|
vac[cur_j]=1;
|
|
for(unsigned int q=0;q<vac.size();q++)cout << (vac[q]?'1':'0') << ' ';
|
|
cout << '\n';
|
|
cout << i << " " << cur_j << ": d1(" << vacancies(vac,cur_j) << "|" << vacancies(vac,al.get_center(prev_cept)) << "," << vac_all << "+" << -al.fert(i)<< "+" << +k << ")\n" << '\n';
|
|
prev_j=cur_j;
|
|
cur_j=al.als_j[cur_j].next;
|
|
}
|
|
while(cur_j) { // process following words of cept
|
|
k++;
|
|
vac_all--;
|
|
vac[cur_j]=1;
|
|
int vprev=vacancies(vac,prev_j);
|
|
cout << "PREV: " << prev_j << '\n';
|
|
for(unsigned int q=0;q<vac.size();q++)cout << (vac[q]?'1':'0') << ' ';
|
|
cout << '\n';
|
|
cout << i << " " << cur_j << ": d>1(" << vacancies(vac,cur_j) << "-" << vprev << "|" << vac_all<< "+" << -al.fert(i)<< "+" << +k << ")\n" << '\n';
|
|
prev_j=cur_j;
|
|
cur_j=al.als_j[cur_j].next;
|
|
}
|
|
assert(k==al.fert(i));
|
|
if( k )
|
|
prev_cept=i;
|
|
}
|
|
assert(vac_all==al.fert(0));
|
|
}
|
|
*/
|
|
|
|
extern short DoViterbiTraining;
|
|
|
|
struct m3_em_loop_t {
|
|
model3 *m;
|
|
int done;
|
|
int valid;
|
|
string alignfile;
|
|
string modelName;
|
|
int it;
|
|
bool dump_files;
|
|
char toModel, fromModel;
|
|
pthread_t thread;
|
|
d4model* d4;
|
|
d5model* d5;
|
|
bool is_final;
|
|
m3_em_loop_t() :
|
|
m(0), done(0), valid(0),d4(0),d5(0) {
|
|
}
|
|
;
|
|
};
|
|
|
|
void* m3_exe_emloop(void *arg)
|
|
{
|
|
m3_em_loop_t* em =(m3_em_loop_t *) arg;
|
|
em->m->viterbi_thread(em->it, em->alignfile, em->dump_files, *(em->d4),*(em->d5),em->is_final,em->fromModel,em->toModel,em->modelName);
|
|
em->done = -1;
|
|
return arg;
|
|
}
|
|
|
|
void model3::viterbi_thread(int it, string alignfile, bool dump_files,d4model& d4m,d5model& d5m,bool is_final,char fromModel,char toModel,string& modelName)
|
|
{
|
|
#define TRAIN_ARGS perp, trainViterbiPerp, sHandler1, dump_files, alignfile.c_str(), true, modelName,is_final
|
|
switch (toModel) {
|
|
case '3': {
|
|
switch (fromModel) {
|
|
case 'H':
|
|
viterbi_loop_with_tricks<transpair_modelhmm, const hmm>(TRAIN_ARGS,h,(void*)0);
|
|
break;
|
|
case '3':
|
|
viterbi_loop_with_tricks<transpair_model3>( TRAIN_ARGS, (void*)0,(void*)0);
|
|
break;
|
|
default:
|
|
abort();
|
|
}
|
|
break;
|
|
}
|
|
case '4': {
|
|
switch (fromModel) {
|
|
case 'H':
|
|
viterbi_loop_with_tricks<transpair_modelhmm, const hmm, d4model>(TRAIN_ARGS,h,&d4m);
|
|
break;
|
|
case '3':
|
|
viterbi_loop_with_tricks<transpair_model3, void, d4model>(TRAIN_ARGS, (void*)0,&d4m);
|
|
break;
|
|
case '4':
|
|
viterbi_loop_with_tricks<transpair_model4, d4model, d4model>(TRAIN_ARGS , &d4m,&d4m);
|
|
break;
|
|
default:
|
|
abort();
|
|
}
|
|
}
|
|
break;
|
|
case '5': {
|
|
switch (fromModel) {
|
|
case 'H':
|
|
viterbi_loop_with_tricks<transpair_modelhmm, const hmm, d5model>(TRAIN_ARGS,h,&d5m);
|
|
break;
|
|
case '3':
|
|
viterbi_loop_with_tricks<transpair_model3, void, d5model>(TRAIN_ARGS, (void*)0,&d5m);
|
|
break;
|
|
case '4':
|
|
viterbi_loop_with_tricks<transpair_model4, d4model, d5model>(TRAIN_ARGS, &d4m,&d5m);
|
|
break;
|
|
case '5':
|
|
viterbi_loop_with_tricks<transpair_model5, d5model, d5model>(TRAIN_ARGS, &d5m,&d5m);
|
|
break;
|
|
default:
|
|
abort();
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
abort();
|
|
}
|
|
|
|
}
|
|
extern short NCPUS;
|
|
|
|
int model3::viterbi(int noIterationsModel3, int noIterationsModel4,
|
|
int noIterationsModel5, int noIterationsModel6, const char* prev_d4,const char* prev_d4_2,bool dumpCount,
|
|
const char* dumpCountName, bool useString)
|
|
{
|
|
double minErrors=1.0;
|
|
int minIter=0;
|
|
if(ewordclasses==NULL)
|
|
ewordclasses = new WordClasses;
|
|
if(fwordclasses==NULL)
|
|
fwordclasses = new WordClasses;
|
|
d4model d4m(MAX_SENTENCE_LENGTH,*ewordclasses,*fwordclasses);
|
|
if(prev_d4) {
|
|
string previous_d4model = prev_d4;
|
|
|
|
string previous_d4model_1 = prev_d4_2;
|
|
cerr << "We are going to read d4 table from " << previous_d4model << "," << previous_d4model_1 << endl;
|
|
d4m.readProbTable(previous_d4model.c_str(),previous_d4model_1.c_str());
|
|
}
|
|
if(h==NULL)
|
|
d4m.makeWordClasses(Elist, Flist, SourceVocabClassesFilename,
|
|
TargetVocabClassesFilename,Elist,Flist);
|
|
|
|
d5model d5m(d4m);
|
|
//d5m.makeWordClasses(Elist, Flist, SourceVocabFilename+".classes",
|
|
// TargetVocabFilename+".classes");
|
|
time_t it_st, st, it_fn, fn;
|
|
bool dump_files;
|
|
string tfile, tfile_actual, dfile, afile, nfile, nfile_actual, p0file,
|
|
alignfile, number, test_alignfile, d4file, d5file, zeroFertFile;
|
|
st = time(NULL);
|
|
sHandler1.rewind();
|
|
if (testPerp && testHandler)
|
|
(*testHandler).rewind();
|
|
string trainingString;
|
|
|
|
trainingString+=(prev_d4 ? '4' : (h ? 'H' : '3'));
|
|
for (int i=0; i<noIterationsModel3; ++i)
|
|
trainingString+='3';
|
|
for (int i=0; i<noIterationsModel4; ++i)
|
|
trainingString+='4';
|
|
for (int i=0; i<noIterationsModel5; ++i)
|
|
trainingString+='5';
|
|
for (int i=0; i<noIterationsModel6; ++i)
|
|
trainingString+='6';
|
|
cout << "\n==========================================================\n";
|
|
cout << "Starting "<<trainingString<<": Viterbi Training";
|
|
cout << "\n "<<trainingString<<" Training Started at: "<< my_ctime(&st)
|
|
<< '\n';
|
|
|
|
|
|
vector<m3_em_loop_t> th;
|
|
th.resize(NCPUS);
|
|
|
|
int k;
|
|
|
|
for(k = 1; k< NCPUS; k++) {
|
|
th[k].m = this;
|
|
th[k].d4 = &d4m;
|
|
th[k].d5 = &d5m;
|
|
}
|
|
|
|
for (unsigned int it=1; it < trainingString.length(); it++) {
|
|
bool is_final=false;
|
|
if (it==trainingString.length()-1)
|
|
is_final=true;
|
|
string modelName;
|
|
char fromModel=trainingString[it-1], toModel=trainingString[it];
|
|
if (fromModel==toModel)
|
|
modelName=string("Model")+fromModel;
|
|
else
|
|
modelName=string("T")+fromModel+"To"+toModel;
|
|
it_st = time(NULL);
|
|
cout <<"\n---------------------\n"<<modelName<<": Iteration " << it
|
|
<<'\n';
|
|
dump_files = (is_final || ((Model3_Dump_Freq != 0) && ((it
|
|
% Model3_Dump_Freq) == 0))) && !NODUMPS;
|
|
string d4file2;
|
|
{
|
|
// set up the names of the files where the tables will be printed
|
|
const string number = (is_final ? "final" : represent_number(it));
|
|
tfile = Prefix + ".t3." + number;
|
|
tfile_actual = Prefix + ".actual.t3." + number;
|
|
afile = Prefix + ".a3." + number;
|
|
nfile = Prefix + ".n3." + number;
|
|
nfile_actual = Prefix + ".actual.n3." + number;
|
|
dfile = Prefix + ".d3." + number;
|
|
d4file = Prefix + ".d4." + number;
|
|
d4file2 = Prefix + ".D4." + number;
|
|
d5file = Prefix + ".d5." + number;
|
|
alignfile = Prefix + ".A3." + number;
|
|
test_alignfile = Prefix + ".tst.A3." + number;
|
|
p0file = Prefix + ".p0_3." + number;
|
|
}
|
|
// clear count tables
|
|
// tCountTable.clear();
|
|
dCountTable.clear();
|
|
aCountTable.clear();
|
|
initAL();
|
|
nCountTable.clear();
|
|
d4m.clear();
|
|
p0_count = p1_count = 0;
|
|
//dump_files=true;
|
|
|
|
sHandler1.rewind();
|
|
if (testPerp && testHandler)
|
|
(*testHandler).rewind();
|
|
|
|
for (k=1 ; k< NCPUS ; k++) {
|
|
th[k].m = this;
|
|
th[k].done = 0;
|
|
th[k].valid = 0;
|
|
th[k].it = it;
|
|
th[k].is_final = is_final;
|
|
th[k].alignfile = alignfile + ".part" + represent_number(k, 3);
|
|
th[k].dump_files = dump_files;
|
|
th[k].fromModel = fromModel;
|
|
th[k].toModel = toModel;
|
|
th[k].modelName = modelName;
|
|
th[k].valid = pthread_create(&(th[k].thread),NULL,m3_exe_emloop,&(th[k]));
|
|
if(th[k].valid) {
|
|
cerr << "Error starting thread " << k << endl;
|
|
}
|
|
}
|
|
alignfile = alignfile + ".part" + represent_number(0, 3);
|
|
|
|
#ifdef TRICKY_IBM3_TRAINING
|
|
|
|
#define TRAIN_ARGS perp, trainViterbiPerp, sHandler1, dump_files, alignfile.c_str(), true, modelName,is_final
|
|
#define TEST_ARGS *testPerp, *testViterbiPerp, *testHandler, dump_files, test_alignfile.c_str(),false, modelName,is_final
|
|
switch (toModel) {
|
|
case '3':
|
|
switch (fromModel) {
|
|
case 'H':
|
|
viterbi_loop_with_tricks<transpair_modelhmm, const hmm>(TRAIN_ARGS,h,(void*)0);
|
|
if (testPerp && testHandler)
|
|
viterbi_loop_with_tricks<transpair_modelhmm, const hmm>(TEST_ARGS, h,(void*)0);
|
|
break;
|
|
case '3':
|
|
viterbi_loop_with_tricks<transpair_model3>( TRAIN_ARGS, (void*)0,(void*)0);
|
|
if (testPerp && testHandler)
|
|
viterbi_loop_with_tricks<transpair_model3>( TEST_ARGS, (void*)0,(void*)0);
|
|
break;
|
|
default:
|
|
abort();
|
|
}
|
|
break;
|
|
case '4': {
|
|
switch (fromModel) {
|
|
case 'H':
|
|
viterbi_loop_with_tricks<transpair_modelhmm, const hmm, d4model>(TRAIN_ARGS,h,&d4m);
|
|
if (testPerp && testHandler)
|
|
viterbi_loop_with_tricks<transpair_modelhmm, const hmm,
|
|
d4model>(TEST_ARGS, h,&d4m);
|
|
break;
|
|
case '3':
|
|
viterbi_loop_with_tricks<transpair_model3, void, d4model>(TRAIN_ARGS, (void*)0,&d4m);
|
|
if (testPerp && testHandler)
|
|
viterbi_loop_with_tricks<transpair_model3, void, d4model>( TEST_ARGS , (void*)0,&d4m);
|
|
break;
|
|
case '4':
|
|
viterbi_loop_with_tricks<transpair_model4, d4model, d4model>(TRAIN_ARGS , &d4m,&d4m);
|
|
if (testPerp && testHandler)
|
|
viterbi_loop_with_tricks<transpair_model4, d4model, d4model>( TEST_ARGS, &d4m,&d4m);
|
|
break;
|
|
default:
|
|
abort();
|
|
}
|
|
if(dumpCount && it == trainingString.length()-1) {
|
|
string realD4TableName = dumpCountName;
|
|
realD4TableName += ".d4.count";
|
|
string realD4bTableName = realD4TableName+".b";
|
|
if(!d4m.dumpCount(realD4TableName.c_str(),realD4bTableName.c_str()))
|
|
cerr <<"Error writing count file to" << realD4TableName << endl;
|
|
}
|
|
d4m.normalizeTable();
|
|
if (dump_files)
|
|
d4m.printProbTable(d4file.c_str(), d4file2.c_str());
|
|
}
|
|
break;
|
|
case '5': {
|
|
switch (fromModel) {
|
|
case 'H':
|
|
viterbi_loop_with_tricks<transpair_modelhmm, const hmm, d5model>(TRAIN_ARGS,h,&d5m);
|
|
if (testPerp && testHandler)
|
|
viterbi_loop_with_tricks<transpair_modelhmm, const hmm,
|
|
d5model>(TEST_ARGS, h,&d5m);
|
|
break;
|
|
case '3':
|
|
viterbi_loop_with_tricks<transpair_model3, void, d5model>(TRAIN_ARGS, (void*)0,&d5m);
|
|
if (testPerp && testHandler)
|
|
viterbi_loop_with_tricks<transpair_model3, void, d5model>( TEST_ARGS , (void*)0,&d5m);
|
|
break;
|
|
case '4':
|
|
viterbi_loop_with_tricks<transpair_model4, d4model, d5model>(TRAIN_ARGS, &d4m,&d5m);
|
|
if (testPerp && testHandler)
|
|
viterbi_loop_with_tricks<transpair_model4, d4model, d5model>( TEST_ARGS, &d4m,&d5m);
|
|
break;
|
|
case '5':
|
|
viterbi_loop_with_tricks<transpair_model5, d5model, d5model>(TRAIN_ARGS, &d5m,&d5m);
|
|
if (testPerp && testHandler)
|
|
viterbi_loop_with_tricks<transpair_model5, d5model, d5model>( TEST_ARGS, &d5m,&d5m);
|
|
break;
|
|
default:
|
|
abort();
|
|
}
|
|
if(dumpCount && it == trainingString.length()-1) {
|
|
string realD4TableName = dumpCountName;
|
|
realD4TableName += ".d4";
|
|
string realD4bTableName = realD4TableName+".b";
|
|
if(!d5m.d4m.dumpCount(realD4TableName.c_str(),realD4bTableName.c_str()))
|
|
cerr <<"Error writing count file to" << realD4TableName << endl;
|
|
}
|
|
d5m.d4m.normalizeTable();
|
|
if (dump_files)
|
|
d5m.d4m.printProbTable(d4file.c_str(), d4file2.c_str());
|
|
d5m.normalizeTable();
|
|
if (dump_files) {
|
|
ofstream d5output(d5file.c_str());
|
|
d5output << d5m;
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
abort();
|
|
}
|
|
|
|
#else
|
|
viterbi_loop(perp, trainViterbiPerp, sHandler1, dump_files,
|
|
alignfile.c_str(), true, model);
|
|
if (testPerp && testHandler)
|
|
viterbi_loop(*testPerp, *testViterbiPerp, *testHandler,
|
|
dump_files, test_alignfile.c_str(), false, model);
|
|
#endif
|
|
for (k=1; k<NCPUS; k++) {
|
|
pthread_join((th[k].thread),NULL);
|
|
cerr << "Thread " << k << "done" << endl;
|
|
}
|
|
if (errorsAL()<minErrors) {
|
|
minErrors=errorsAL();
|
|
minIter=it;
|
|
}
|
|
// now normalize count tables
|
|
// dump_files = true;
|
|
if (dump_files&&OutputInAachenFormat==1)
|
|
tTable.printCountTable(tfile.c_str(), Elist.getVocabList(),
|
|
Flist.getVocabList(), 1);
|
|
perp.record(modelName);
|
|
errorReportAL(cerr, modelName);
|
|
trainViterbiPerp.record(modelName);
|
|
|
|
if(dumpCount && it == trainingString.length()-1) {
|
|
string realTableName = dumpCountName;
|
|
realTableName += ".t.count";
|
|
tTable.printCountTable(realTableName.c_str(),Elist.getVocabList(),Flist.getVocabList(),useString);
|
|
string realATableName = dumpCountName;
|
|
realATableName += ".a.count";
|
|
aCountTable.printRealTable(realATableName.c_str());
|
|
string realDTableName = dumpCountName;
|
|
realDTableName += ".d.count";
|
|
dCountTable.printRealTable(realDTableName.c_str());
|
|
string realNTableName = dumpCountName;
|
|
realNTableName += ".n.count";
|
|
nCountTable.printRealNTable(Elist.uniqTokens(),realNTableName.c_str(),Elist.getVocabList(),useString);
|
|
}
|
|
|
|
tTable.normalizeTable(Elist, Flist);
|
|
aCountTable.normalize(aTable);
|
|
dCountTable.normalize(dTable);
|
|
nCountTable.normalize(nTable, &Elist.getVocabList());
|
|
sHandler1.rewind();
|
|
//testHandler->rewind();
|
|
// cout << "tTable contains " <<
|
|
// tTable.getHash().bucket_count() << " buckets and "<<
|
|
//tTable.getHash().size() << " entries.\n";
|
|
|
|
// normalize p1 & p0
|
|
|
|
cout << "p0_count is " << p0_count << " and p1 is " << p1_count << "; ";
|
|
if (P0!=-1.0) {
|
|
p0 = P0;
|
|
p1 = 1-P0;
|
|
} else {
|
|
if (p1_count + p0_count != 0) {
|
|
p1 = p1_count / (p1_count + p0_count );
|
|
p0 = 1 - p1;
|
|
} else {
|
|
p1 = p0 = 0;
|
|
cerr << "ERROR: p0_count+p1_count is zero!!!\n";
|
|
}
|
|
}
|
|
|
|
cout << "p0 is " << p0 << " p1: " << p1 << '\n';
|
|
|
|
cout << modelName<<": TRAIN CROSS-ENTROPY " << perp.cross_entropy()
|
|
<< " PERPLEXITY " << perp.perplexity() << '\n';
|
|
if (testPerp && testHandler)
|
|
cout << modelName << ":("<<it<<" TEST CROSS-ENTROPY " << (*testPerp).cross_entropy() << " PERPLEXITY " << (*testPerp).perplexity() << " sum: " << (*testPerp).getSum()<< " wc: " << (*testPerp).word_count() << '\n';
|
|
cout << modelName << ": ("<<it<<") TRAIN VITERBI CROSS-ENTROPY "
|
|
<< trainViterbiPerp.cross_entropy() << " PERPLEXITY "
|
|
<< trainViterbiPerp.perplexity() << '\n';
|
|
if (testPerp && testHandler)
|
|
cout << modelName << ": ("<<it<<")TEST VITERBI CROSS-ENTROPY "
|
|
<< (*testViterbiPerp).cross_entropy() << " PERPLEXITY "
|
|
<< (*testViterbiPerp).perplexity() << " Sum: " << (*testViterbiPerp).getSum() << " wc: " << (*testViterbiPerp).word_count() << '\n';
|
|
//dump_files = true;
|
|
if (dump_files) {
|
|
if (OutputInAachenFormat==0)
|
|
tTable.printProbTable(tfile.c_str(), Elist.getVocabList(),
|
|
Flist.getVocabList(), OutputInAachenFormat);
|
|
aTable.printTable(afile.c_str());
|
|
dTable.printTable(dfile.c_str());
|
|
nTable.printNTable(Elist.uniqTokens(), nfile.c_str(),
|
|
Elist.getVocabList(), OutputInAachenFormat);
|
|
ofstream of(p0file.c_str());
|
|
of << p0;
|
|
of.close();
|
|
}
|
|
it_fn = time(NULL) ;
|
|
cout << "\n" << modelName << " Viterbi Iteration : "<<it<< " took: "
|
|
<< difftime(it_fn, it_st) << " seconds\n";
|
|
} /* of iterations */
|
|
fn = time(NULL);
|
|
cout << trainingString <<" Training Finished at: " << my_ctime(&fn) << "\n";
|
|
cout << "\n" << "Entire Viterbi "<<trainingString<<" Training took: "
|
|
<< difftime(fn, st) << " seconds\n";
|
|
cout << "==========================================================\n";
|
|
if (noIterationsModel4||noIterationsModel5)
|
|
minIter-=noIterationsModel3;
|
|
if (noIterationsModel5)
|
|
minIter-=noIterationsModel4;
|
|
return minIter;
|
|
}
|
|
|
|
int model3::viterbi_hto3()
|
|
{
|
|
|
|
double minErrors=1.0;
|
|
int minIter=0;
|
|
bool dump_files = false;
|
|
string tfile, tfile_actual, dfile, afile, nfile, nfile_actual, p0file,
|
|
alignfile, number, test_alignfile, d4file, d5file, zeroFertFile;
|
|
time_t st = time(NULL);
|
|
cout << "Starting HMM To Model 3 Viterbi Training";
|
|
cout << "\n hto3 Training Started at: "<< my_ctime(&st) << '\n';
|
|
string modelName="H23";
|
|
//cout <<"\n---------------------\n"<<modelName<<": Iteration " << it<<'\n';
|
|
int it = 1;
|
|
bool is_final =false;
|
|
///ump_files = true;
|
|
dump_files = (is_final || ((Model3_Dump_Freq != 0) && ((it % Model3_Dump_Freq)
|
|
== 0))) && !NODUMPS;
|
|
string d4file2;
|
|
{
|
|
// set up the names of the files where the tables will be printed
|
|
const string number = (is_final ? "final" : represent_number(it));
|
|
tfile = Prefix + ".t3." + number;
|
|
tfile_actual = Prefix + ".actual.t3." + number;
|
|
afile = Prefix + ".a3." + number;
|
|
nfile = Prefix + ".n3." + number;
|
|
nfile_actual = Prefix + ".actual.n3." + number;
|
|
dfile = Prefix + ".d3." + number;
|
|
d4file = Prefix + ".d4." + number;
|
|
d4file2 = Prefix + ".D4." + number;
|
|
d5file = Prefix + ".d5." + number;
|
|
alignfile = Prefix + ".AH3_";
|
|
alignfile += represent_number(iter, 3);
|
|
alignfile += ".part" + represent_number(part, 3);
|
|
test_alignfile = Prefix + ".tst.A3." + number;
|
|
test_alignfile = Prefix + ".tst.A3." + number;
|
|
p0file = Prefix + ".p0_3." + number;
|
|
}
|
|
// clear count tables
|
|
// tCountTable.clear();
|
|
dCountTable.clear();
|
|
aCountTable.clear();
|
|
initAL();
|
|
nCountTable.clear();
|
|
p0_count = p1_count = 0;
|
|
|
|
#ifdef TRICKY_IBM3_TRAINING
|
|
|
|
#define TRAIN_ARGS perp, trainViterbiPerp, sHandler1, true, alignfile.c_str(), true, modelName,is_final
|
|
#define TEST_ARGS *testPerp, *testViterbiPerp, *testHandler, dump_files, test_alignfile.c_str(),false, modelName,is_final
|
|
viterbi_loop_with_tricks<transpair_modelhmm, const hmm>(TRAIN_ARGS,h,(void*)0);
|
|
if (testPerp && testHandler)
|
|
viterbi_loop_with_tricks<transpair_modelhmm, const hmm>(TEST_ARGS, h,(void*)0);
|
|
|
|
#else
|
|
viterbi_loop(perp, trainViterbiPerp, sHandler1, dump_files,
|
|
alignfile.c_str(), true, model);
|
|
if (testPerp && testHandler)
|
|
viterbi_loop(*testPerp, *testViterbiPerp, *testHandler,
|
|
dump_files, test_alignfile.c_str(), false, model);
|
|
#endif
|
|
if (errorsAL()<minErrors) {
|
|
minErrors=errorsAL();
|
|
minIter=it;
|
|
}
|
|
return minIter;
|
|
}
|
|
|
|
int model3::viterbi_3to3()
|
|
{
|
|
bool is_final = false;
|
|
double minErrors=1.0;
|
|
int minIter=0;
|
|
bool dump_files = false;
|
|
string tfile, tfile_actual, dfile, afile, nfile, nfile_actual, p0file,
|
|
alignfile, number, test_alignfile, d4file, d5file, zeroFertFile;
|
|
time_t st = time(NULL);
|
|
cout << "Starting HMM To Model 3 Viterbi Training";
|
|
cout << "\n hto3 Training Started at: "<< my_ctime(&st) << '\n';
|
|
string modelName="H23";
|
|
int it = 1;
|
|
|
|
// cout <<"\n---------------------\n"<<modelName<<": Iteration " << it<<'\n';
|
|
|
|
dump_files = (is_final || ((Model3_Dump_Freq != 0) && ((it % Model3_Dump_Freq)
|
|
== 0))) && !NODUMPS;
|
|
dump_files = true;
|
|
string d4file2;
|
|
{
|
|
// set up the names of the files where the tables will be printed
|
|
const string number = (is_final ? "final" : represent_number(it));
|
|
tfile = Prefix + ".t3." + number;
|
|
tfile_actual = Prefix + ".actual.t3." + number;
|
|
afile = Prefix + ".a3." + number;
|
|
nfile = Prefix + ".n3." + number;
|
|
nfile_actual = Prefix + ".actual.n3." + number;
|
|
dfile = Prefix + ".d3." + number;
|
|
d4file = Prefix + ".d4." + number;
|
|
d4file2 = Prefix + ".D4." + number;
|
|
d5file = Prefix + ".d5." + number;
|
|
alignfile = Prefix + ".A3_";
|
|
alignfile += represent_number(iter, 3);
|
|
alignfile += ".part" + represent_number(part, 3);
|
|
test_alignfile = Prefix + ".tst.A3." + number;
|
|
p0file = Prefix + ".p0_3." + number;
|
|
}
|
|
// clear count tables
|
|
// tCountTable.clear();
|
|
dCountTable.clear();
|
|
aCountTable.clear();
|
|
initAL();
|
|
nCountTable.clear();
|
|
p0_count = p1_count = 0;
|
|
|
|
#ifdef TRICKY_IBM3_TRAINING
|
|
|
|
#define TRAIN_ARGS perp, trainViterbiPerp, sHandler1, true, alignfile.c_str(), true, modelName,is_final
|
|
#define TEST_ARGS *testPerp, *testViterbiPerp, *testHandler, dump_files, test_alignfile.c_str(),false, modelName,is_final
|
|
viterbi_loop_with_tricks<transpair_model3>( TRAIN_ARGS, (void*)0,(void*)0);
|
|
if (testPerp && testHandler)
|
|
viterbi_loop_with_tricks<transpair_model3>( TEST_ARGS, (void*)0,(void*)0);
|
|
|
|
#else
|
|
viterbi_loop(perp, trainViterbiPerp, sHandler1, dump_files,
|
|
alignfile.c_str(), true, model);
|
|
if (testPerp && testHandler)
|
|
viterbi_loop(*testPerp, *testViterbiPerp, *testHandler,
|
|
dump_files, test_alignfile.c_str(), false, model);
|
|
#endif
|
|
if (errorsAL()<minErrors) {
|
|
minErrors=errorsAL();
|
|
minIter=it;
|
|
}
|
|
return minIter;
|
|
}
|
|
|
|
d4model* model3::viterbi_3to4()
|
|
{
|
|
double minErrors=1.0;
|
|
bool is_final = false;
|
|
bool dump_files = false;
|
|
if(ewordclasses==NULL)
|
|
ewordclasses = new WordClasses;
|
|
if(fwordclasses==NULL)
|
|
fwordclasses = new WordClasses;
|
|
|
|
d4model *dm1 = new d4model(MAX_SENTENCE_LENGTH,*ewordclasses,*fwordclasses);
|
|
d4model& d4m = *dm1;
|
|
//d4m.makeWordClasses(Elist, Flist, SourceVocabFilename+".classes",
|
|
// TargetVocabFilename+".classes");
|
|
|
|
string tfile, tfile_actual, dfile, afile, nfile, nfile_actual, p0file,
|
|
alignfile, number, test_alignfile, d4file, d5file, zeroFertFile;
|
|
time_t st = time(NULL);
|
|
cout << "Starting Model 3 To Model 4 Viterbi Training";
|
|
cout << "\n hto3 Training Started at: "<< my_ctime(&st) << '\n';
|
|
string modelName="34";
|
|
int it = 1;
|
|
//cout <<"\n---------------------\n"<<modelName<<": Iteration " << it<<'\n';
|
|
|
|
dump_files = (is_final || ((Model3_Dump_Freq != 0) && ((it % Model3_Dump_Freq)
|
|
== 0))) && !NODUMPS;
|
|
dump_files = true;
|
|
string d4file2;
|
|
{
|
|
// set up the names of the files where the tables will be printed
|
|
const string number = (is_final ? "final" : represent_number(it));
|
|
tfile = Prefix + ".t3." + number;
|
|
tfile_actual = Prefix + ".actual.t3." + number;
|
|
afile = Prefix + ".a3." + number;
|
|
nfile = Prefix + ".n3." + number;
|
|
nfile_actual = Prefix + ".actual.n3." + number;
|
|
dfile = Prefix + ".d3." + number;
|
|
d4file = Prefix + ".d4." + number;
|
|
d4file2 = Prefix + ".D4." + number;
|
|
d5file = Prefix + ".d5." + number;
|
|
alignfile = Prefix + ".A34_";
|
|
alignfile += represent_number(iter, 3);
|
|
alignfile += ".part" + represent_number(part, 3);
|
|
test_alignfile = Prefix + ".tst.A3." + number;
|
|
p0file = Prefix + ".p0_3." + number;
|
|
}
|
|
// clear count tables
|
|
// tCountTable.clear();
|
|
dCountTable.clear();
|
|
aCountTable.clear();
|
|
initAL();
|
|
nCountTable.clear();
|
|
p0_count = p1_count = 0;
|
|
|
|
#ifdef TRICKY_IBM3_TRAINING
|
|
|
|
#define TRAIN_ARGS perp, trainViterbiPerp, sHandler1, true, alignfile.c_str(), true, modelName,is_final
|
|
#define TEST_ARGS *testPerp, *testViterbiPerp, *testHandler, dump_files, test_alignfile.c_str(),false, modelName,is_final
|
|
viterbi_loop_with_tricks<transpair_model3, void, d4model>(TRAIN_ARGS, (void*)0,&d4m);
|
|
if (testPerp && testHandler)
|
|
viterbi_loop_with_tricks<transpair_model3, void, d4model>( TEST_ARGS , (void*)0,&d4m);
|
|
|
|
#else
|
|
viterbi_loop(perp, trainViterbiPerp, sHandler1, dump_files,
|
|
alignfile.c_str(), true, model);
|
|
if (testPerp && testHandler)
|
|
viterbi_loop(*testPerp, *testViterbiPerp, *testHandler,
|
|
dump_files, test_alignfile.c_str(), false, model);
|
|
#endif
|
|
if (errorsAL()<minErrors) minErrors=errorsAL();
|
|
return dm1;
|
|
}
|
|
|
|
int model3::viterbi_4to4(d4model& d4m)
|
|
{
|
|
double minErrors=1.0;
|
|
int minIter=0;
|
|
bool dump_files = false;
|
|
|
|
//d4model d4m(MAX_SENTENCE_LENGTH);
|
|
//d4m.makeWordClasses(Elist, Flist, SourceVocabFilename+".classes",
|
|
// TargetVocabFilename+".classes");
|
|
|
|
string tfile, tfile_actual, dfile, afile, nfile, nfile_actual, p0file,
|
|
alignfile, number, test_alignfile, d4file, d5file, zeroFertFile;
|
|
|
|
cout << "Starting Model4 To Model 4 Viterbi Training";
|
|
int it = 1;
|
|
bool is_final = false;
|
|
dump_files = (is_final || ((Model3_Dump_Freq != 0) && ((it % Model3_Dump_Freq)
|
|
== 0))) && !NODUMPS;
|
|
dump_files = true;
|
|
|
|
string modelName="H23";
|
|
//cout <<"\n---------------------\n"<<modelName<<": Iteration " << it<<'\n';
|
|
string d4file2;
|
|
{
|
|
// set up the names of the files where the tables will be printed
|
|
const string number = represent_number(it);
|
|
tfile = Prefix + ".t3." + number;
|
|
tfile_actual = Prefix + ".actual.t3." + number;
|
|
afile = Prefix + ".a3." + number;
|
|
nfile = Prefix + ".n3." + number;
|
|
nfile_actual = Prefix + ".actual.n3." + number;
|
|
dfile = Prefix + ".d3." + number;
|
|
d4file = Prefix + ".d4." + number;
|
|
d4file2 = Prefix + ".D4." + number;
|
|
d5file = Prefix + ".d5." + number;
|
|
alignfile = Prefix + ".A4_";
|
|
alignfile += represent_number(iter, 3);
|
|
alignfile += ".part" + represent_number(part, 3);
|
|
test_alignfile = Prefix + ".tst.A3." + number;
|
|
p0file = Prefix + ".p0_3." + number;
|
|
}
|
|
// clear count tables
|
|
// tCountTable.clear();
|
|
dCountTable.clear();
|
|
aCountTable.clear();
|
|
initAL();
|
|
nCountTable.clear();
|
|
p0_count = p1_count = 0;
|
|
|
|
#ifdef TRICKY_IBM3_TRAINING
|
|
|
|
#define TRAIN_ARGS perp, trainViterbiPerp, sHandler1, true, alignfile.c_str(), true, modelName,is_final
|
|
#define TEST_ARGS *testPerp, *testViterbiPerp, *testHandler, dump_files, test_alignfile.c_str(),false, modelName,is_final
|
|
|
|
viterbi_loop_with_tricks<transpair_model4, d4model, d4model>(TRAIN_ARGS , &d4m,&d4m);
|
|
|
|
if (testPerp && testHandler)
|
|
viterbi_loop_with_tricks<transpair_model4, d4model, d4model>( TEST_ARGS, &d4m,&d4m);
|
|
|
|
#else
|
|
viterbi_loop(perp, trainViterbiPerp, sHandler1, dump_files,
|
|
alignfile.c_str(), true, model);
|
|
if (testPerp && testHandler)
|
|
viterbi_loop(*testPerp, *testViterbiPerp, *testHandler,
|
|
dump_files, test_alignfile.c_str(), false, model);
|
|
#endif
|
|
if (errorsAL()<minErrors) {
|
|
minErrors=errorsAL();
|
|
minIter=it;
|
|
}
|
|
return minIter;
|
|
}
|
|
|
|
struct model3_align_struct {
|
|
model3 *m;
|
|
int part;
|
|
int iter;
|
|
int valid;
|
|
pthread_t thread;
|
|
int done;
|
|
d4model *d4;
|
|
int result;
|
|
model3_align_struct() :
|
|
m(NULL), part(0), iter(0), valid(0), done(0), d4(NULL) {
|
|
}
|
|
|
|
};
|
|
|
|
void* em_thread_h23(void *arg)
|
|
{
|
|
model3_align_struct * m3 = (model3_align_struct*) arg;
|
|
m3->m->initAL();
|
|
m3->result = m3->m->viterbi_hto3();
|
|
m3->done = 1;
|
|
return m3;
|
|
}
|
|
|
|
void* em_thread_323(void *arg)
|
|
{
|
|
model3_align_struct * m3 = (model3_align_struct*) arg;
|
|
m3->m->initAL();
|
|
m3->result = m3->m->viterbi_3to3();
|
|
m3->done = 1;
|
|
return m3;
|
|
}
|
|
|
|
void* em_thread_324(void *arg)
|
|
{
|
|
model3_align_struct * m3 = (model3_align_struct*) arg;
|
|
m3->m->initAL();
|
|
m3->d4 = m3->m->viterbi_3to4();
|
|
m3->done = 1;
|
|
return m3;
|
|
}
|
|
|
|
void* em_thread_424(void *arg)
|
|
{
|
|
model3_align_struct * m3 = (model3_align_struct*) arg;
|
|
m3->m->initAL();
|
|
m3->result = m3->m->viterbi_4to4(*(m3->d4));
|
|
m3->done = 1;
|
|
return m3;
|
|
}
|
|
|
|
void multi_thread_m34_em(model3& m3, int ncpu, int Model3_Iterations,
|
|
int Model4_Iterations)
|
|
{
|
|
string tfile, tfile_actual, dfile, afile, nfile, nfile_actual, p0file,
|
|
alignfile, number, test_alignfile, d4file, d5file, zeroFertFile;
|
|
vector<model3_align_struct> threads;
|
|
bool dump_files;
|
|
threads.resize(ncpu);
|
|
time_t it_st, st, it_fn, fn;
|
|
int i, j;
|
|
ncpu=1;
|
|
vector<amodel<COUNT> > counts;
|
|
counts.resize(ncpu);
|
|
m3.part=0;
|
|
for (i=1; i<ncpu; i++) {
|
|
threads[i].m = new model3(m3,m3.dTable,m3.nTable,counts[i]);
|
|
threads[i].m->setHMM(m3.h);
|
|
threads[i].m->part = i;
|
|
}
|
|
d4model *d4m= NULL;
|
|
st = time(NULL);
|
|
|
|
string trainingString;
|
|
trainingString+=(m3.h ? 'H' : '3');
|
|
for (int i=0; i<Model3_Iterations; ++i)
|
|
trainingString+='3';
|
|
for (int i=0; i<Model4_Iterations; ++i)
|
|
trainingString+='4';
|
|
cout << "\n==========================================================\n";
|
|
cout << "Starting "<<trainingString<<": Viterbi Training";
|
|
cout << "\n "<<trainingString<<" Training Started at: "<< my_ctime(&st)
|
|
<< '\n';
|
|
|
|
for (i=0; i<Model3_Iterations+Model4_Iterations; i++) {
|
|
m3.perp.clear();
|
|
m3.trainViterbiPerp.clear();
|
|
m3.iter = i;
|
|
bool is_final = (i==Model3_Iterations-1 || i == Model4_Iterations
|
|
+Model3_Iterations-1);
|
|
dump_files = (is_final || ((Model3_Dump_Freq != 0) && ((i
|
|
% Model3_Dump_Freq) == 0))) && !NODUMPS;
|
|
m3.sHandler1.rewind();
|
|
m3.perp.clear() ; // clears cross_entrop & perplexity
|
|
m3.trainViterbiPerp.clear() ; // clears cross_entrop & perplexity
|
|
string modelName;
|
|
it_st = time(NULL);
|
|
dump_files = (is_final || ((Model3_Dump_Freq != 0) && ((i
|
|
% Model3_Dump_Freq) == 0))) && !NODUMPS;
|
|
string d4file2;
|
|
{
|
|
// set up the names of the files where the tables will be printed
|
|
const string number = (is_final ? "final": represent_number(i));
|
|
tfile = Prefix + ".t3." + number;
|
|
tfile_actual = Prefix + ".actual.t3." + number;
|
|
afile = Prefix + ".a3." + number;
|
|
nfile = Prefix + ".n3." + number;
|
|
nfile_actual = Prefix + ".actual.n3." + number;
|
|
dfile = Prefix + ".d3." + number;
|
|
d4file = Prefix + ".d4." + number;
|
|
d4file2 = Prefix + ".D4." + number;
|
|
d5file = Prefix + ".d5." + number;
|
|
alignfile = Prefix + ".A3." + number;
|
|
test_alignfile = Prefix + ".tst.A3." + number;
|
|
p0file = Prefix + ".p0_3." + number;
|
|
}
|
|
if (m3.testPerp && m3.testHandler) {
|
|
m3.testHandler->rewind();
|
|
m3.testPerp->clear();
|
|
m3.testViterbiPerp->clear();
|
|
}
|
|
|
|
for (j=1; j<ncpu; j++) {
|
|
threads[j].m->p0 = m3.p0;
|
|
threads[j].m->p1 = m3.p1;
|
|
threads[j].m->p0_count = 0;
|
|
threads[j].m->p1_count = 0;
|
|
threads[j].m->nCountTable.clear();
|
|
threads[j].m->dCountTable.clear();
|
|
threads[j].m->aCountTable.clear();
|
|
threads[j].m->iter = i;
|
|
if (threads[j].d4) {
|
|
*(threads[j].d4) = *d4m;
|
|
threads[j].d4->clear();
|
|
}
|
|
}
|
|
if (i==0) { // H23
|
|
for (j=1; j<ncpu; j++) {
|
|
threads[j].valid = pthread_create(&(threads[j].thread), NULL,
|
|
em_thread_h23, &(threads[j]));
|
|
if (threads[j].valid) {
|
|
cerr << "Error Starting Thread " << j << endl;
|
|
}
|
|
}
|
|
modelName = "HTO3";
|
|
m3.viterbi_hto3();
|
|
while (1) {
|
|
bool done = true;
|
|
for (j=1; j<ncpu; j++) {
|
|
//pthread_join((args[j].thread),NULL);
|
|
// Start normalization as soon as possible
|
|
if (threads[j].done==1) {
|
|
threads[j].done = 2;
|
|
m3.aCountTable.merge(threads[j].m->aCountTable);
|
|
m3.dCountTable.merge(threads[j].m->dCountTable);
|
|
m3.nCountTable.merge(threads[j].m->nCountTable,
|
|
m3.Elist.uniqTokens(), m3.Elist.getVocabList());
|
|
m3.p0_count += threads[j].m->p0_count;
|
|
m3.p1_count += threads[j].m->p1_count;
|
|
} else if (threads[j].done==2) {
|
|
// Nothing
|
|
} else if (threads[j].done==0) {
|
|
done = false;
|
|
}
|
|
}
|
|
if (done)
|
|
break;
|
|
}
|
|
} else if (i>0 && i< Model3_Iterations) {
|
|
modelName = "3TO3";
|
|
for (j=1; j<ncpu; j++) {
|
|
threads[j].valid = pthread_create(&(threads[j].thread), NULL,
|
|
em_thread_323, &(threads[j]));
|
|
if (threads[j].valid) {
|
|
cerr << "Error Starting Thread " << j << endl;
|
|
}
|
|
}
|
|
m3.viterbi_3to3();
|
|
while (1) {
|
|
bool done = true;
|
|
for (j=1; j<ncpu; j++) {
|
|
//pthread_join((args[j].thread),NULL);
|
|
// Start normalization as soon as possible
|
|
if (threads[j].done==1) {
|
|
threads[j].done = 2;
|
|
m3.aCountTable.merge(threads[j].m->aCountTable);
|
|
m3.dCountTable.merge(threads[j].m->dCountTable);
|
|
m3.nCountTable.merge(threads[j].m->nCountTable,
|
|
m3.Elist.uniqTokens(), m3.Elist.getVocabList());
|
|
m3.p0_count += threads[j].m->p0_count;
|
|
m3.p1_count += threads[j].m->p1_count;
|
|
} else if (threads[j].done==2) {
|
|
// Nothing
|
|
} else if (threads[j].done==0) {
|
|
done = false;
|
|
}
|
|
}
|
|
if (done)
|
|
break;
|
|
}
|
|
} else if (i==Model3_Iterations) {
|
|
modelName = "3TO4";
|
|
for (j=1; j<ncpu; j++) {
|
|
threads[j].valid = pthread_create(&(threads[j].thread), NULL,
|
|
em_thread_324, &(threads[j]));
|
|
if (threads[j].valid) {
|
|
cerr << "Error Starting Thread " << j << endl;
|
|
}
|
|
}
|
|
d4m = m3.viterbi_3to4();
|
|
while (1) {
|
|
bool done = true;
|
|
for (j=1; j<ncpu; j++) {
|
|
//pthread_join((args[j].thread),NULL);
|
|
// Start normalization as soon as possible
|
|
if (threads[j].done==1) {
|
|
threads[j].done = 2;
|
|
m3.aCountTable.merge(threads[j].m->aCountTable);
|
|
m3.dCountTable.merge(threads[j].m->dCountTable);
|
|
m3.nCountTable.merge(threads[j].m->nCountTable,
|
|
m3.Elist.uniqTokens(), m3.Elist.getVocabList());
|
|
m3.p0_count += threads[j].m->p0_count;
|
|
m3.p1_count += threads[j].m->p1_count;
|
|
d4m->merge(*threads[j].d4);
|
|
} else if (threads[j].done==2) {
|
|
// Nothing
|
|
} else if (threads[j].done==0) {
|
|
done = false;
|
|
}
|
|
}
|
|
if (done)
|
|
break;
|
|
}
|
|
} else if (i>Model3_Iterations) {
|
|
modelName = "4TO4";
|
|
for (j=1; j<ncpu; j++) {
|
|
threads[j].valid = pthread_create(&(threads[j].thread), NULL,
|
|
em_thread_424, &(threads[j]));
|
|
if (threads[j].valid) {
|
|
cerr << "Error Starting Thread " << j << endl;
|
|
}
|
|
}
|
|
m3.viterbi_4to4(*d4m);
|
|
while (1) {
|
|
bool done = true;
|
|
for (j=1; j<ncpu; j++) {
|
|
//pthread_join((args[j].thread),NULL);
|
|
// Start normalization as soon as possible
|
|
if (threads[j].done==1) {
|
|
threads[j].done = 2;
|
|
m3.aCountTable.merge(threads[j].m->aCountTable);
|
|
m3.dCountTable.merge(threads[j].m->dCountTable);
|
|
m3.nCountTable.merge(threads[j].m->nCountTable,
|
|
m3.Elist.uniqTokens(), m3.Elist.getVocabList());
|
|
m3.p0_count += threads[j].m->p0_count;
|
|
m3.p1_count += threads[j].m->p1_count;
|
|
d4m->merge(*(threads[j].d4));
|
|
} else if (threads[j].done==2) {
|
|
// Nothing
|
|
} else if (threads[j].done==0) {
|
|
done = false;
|
|
}
|
|
}
|
|
if (done)
|
|
break;
|
|
}
|
|
}
|
|
m3.perp.record(modelName);
|
|
m3.errorReportAL(cerr, modelName);
|
|
m3.trainViterbiPerp.record(modelName);
|
|
|
|
m3.tTable.normalizeTable(m3.Elist, m3.Flist);
|
|
m3.aCountTable.normalize(m3.aTable);
|
|
m3.aCountTable.clear();
|
|
m3.dCountTable.normalize(m3.dTable);
|
|
m3.dCountTable.clear();
|
|
m3.nCountTable.normalize(m3.nTable, &(m3.Elist.getVocabList()));
|
|
m3.nCountTable.clear();
|
|
cout << "p0_count is " << m3.p0_count << " and p1 is " << m3.p1_count
|
|
<< "; ";
|
|
if (P0!=-1.0) {
|
|
m3.p0 = P0;
|
|
m3.p1 = 1-P0;
|
|
} else {
|
|
if (m3.p1_count + m3.p0_count != 0) {
|
|
m3.p1 = m3.p1_count / (m3.p1_count + m3.p0_count );
|
|
m3.p0 = 1 - m3.p1;
|
|
} else {
|
|
m3.p1 = m3.p0 = 0;
|
|
cerr << "ERROR: p0_count+p1_count is zero!!!\n";
|
|
}
|
|
}
|
|
m3.p0_count = m3.p1_count = 0;
|
|
cout << "p0 is " << m3.p0 << " p1: " << m3.p1 << '\n';
|
|
if (d4m) {
|
|
d4m->normalizeTable();
|
|
d4m->clear();
|
|
}
|
|
|
|
cout << modelName<<": TRAIN CROSS-ENTROPY " << m3.perp.cross_entropy()
|
|
<< " PERPLEXITY " << m3.perp.perplexity() << '\n';
|
|
if (m3.testPerp && m3.testHandler)
|
|
cout << modelName << ":("<<i<<" TEST CROSS-ENTROPY "
|
|
<< m3.testPerp->cross_entropy() << " PERPLEXITY "
|
|
<< m3.testPerp->perplexity() << " sum: "
|
|
<< m3.testPerp->getSum()<< " wc: "
|
|
<< m3.testPerp->word_count() << '\n';
|
|
cout << modelName << ": ("<<i<<") TRAIN VITERBI CROSS-ENTROPY "
|
|
<< m3.trainViterbiPerp.cross_entropy() << " PERPLEXITY "
|
|
<< m3.trainViterbiPerp.perplexity() << '\n';
|
|
bool dump_files = true;
|
|
if (dump_files) {
|
|
if (OutputInAachenFormat==0)
|
|
m3.tTable.printProbTable(tfile.c_str(),
|
|
m3.Elist.getVocabList(), m3.Flist.getVocabList(),
|
|
OutputInAachenFormat);
|
|
m3.aTable.printTable(afile.c_str());
|
|
m3.dTable.printTable(dfile.c_str());
|
|
m3.nTable.printNTable(m3.Elist.uniqTokens(), nfile.c_str(),
|
|
m3.Elist.getVocabList(), OutputInAachenFormat);
|
|
ofstream of(p0file.c_str());
|
|
of << m3.p0;
|
|
of.close();
|
|
}
|
|
it_fn = time(NULL);
|
|
cout << "\n" << modelName << " Viterbi Iteration : "<<i<< " took: "
|
|
<< difftime(it_fn, it_st) << " seconds\n";
|
|
}
|
|
fn = time(NULL);
|
|
cout << trainingString <<" Training Finished at: " << my_ctime(&fn) << "\n";
|
|
cout << "\n" << "Entire Viterbi "<<trainingString<<" Training took: "
|
|
<< difftime(fn, st) << " seconds\n";
|
|
cout << "==========================================================\n";
|
|
|
|
}
|
|
|