void Decoder::readTable(const char filename[], double prune_threshold, unsigned int prune_count){ //==================Einlesen der Phrasentabelle============================ PTree< pair <unsigned int, double> > pruningTree; //speichert für jede Übersetzung die Anzahl der eingelesenen Übersetzungen und die beste Übersetzung pair <unsigned int, double> pruningStart; //die Startkombi für den PruningTree pruningStart.first=0; pruningStart.second=(1./0.); igzstream in(filename); std::string line,token; while(getline(in,line)){ std::stringstream ist(line); double relfreq_f, relfreq_e, source_to_target, target_to_source, unigram_sprachmodell; unsigned int singlecf, singlece; vector<uint> ephrase, fphrase; //Ausgabe: relfreq_f relfreq_e # quellphrase # zielphrase # singlecf singlece # source_to_target target_to_source # unigram-sprachmodell ist >> relfreq_f >> relfreq_e >>token; // token für "#" while(ist>>token && token != "#"){ fphrase.push_back(flex->getWord_or_add(token).wordId()); } while(ist>>token && token != "#"){ ephrase.push_back(elex->getWord_or_add(token).wordId()); } ist >> singlecf >> singlece >> token >> source_to_target >> target_to_source >> token >> unigram_sprachmodell; Cost kosten=Cost(); kosten.calc(relfreq_f, relfreq_e, fphrase, ephrase, singlecf, singlece, source_to_target, target_to_source, unigram_sprachmodell); double kosten_insgesamt=kosten.cost(); pair< unsigned int, double>* pruning_infos=&pruningTree.traverse(fphrase,true,pruningStart)->c; if (kosten_insgesamt > pruning_infos->second+prune_threshold || pruning_infos->first >prune_count) continue; //pruning ergibt, wir wollen es nicht in den Ptree mitaufnehmen //if (kosten_insgesamt< pruning_infos->second) pruning_infos->second=kosten_insgesamt; _jetzt irrelevant, da ich von einer geordneten eingabe ausgehe pruning_infos->first++; schwarz->traverse(fphrase,true)->c.traverse(ephrase,true,Cost(1./0.))->c = kosten; } //cerr << " schwarz erstellt" << endl; }
int main(int argc, char* argv[]) { if (argc != 4) { std::cout << "Aufruf mit Parametern: <französiche Trainigsdaten> <englische Trainingsdaten> <Alignment der Trainingsdaten>\n" << "Folgende Ausgabe: relfreq_f relfreq_e # quellphrase # zielphrase # singlecf singlece # source_to_target target_to_source # unigram-sprachmodell\n"; return 0; } Lexicon flex(french); Lexicon elex(english); PTree<std::pair<int, PTree<int> > > pTree; PTree<unsigned int> eSinglecount; uint eCount = 0; //Gesamtzahl der englischen Wörter std::unordered_map<uint,Wordinfo> ef_pair, fe_pair; //Einzelwortbasierte Übersetzungshäufigkeit von e nach f (und umgekehrt) igzstream f_in(argv[1]), e_in(argv[2]), a_in(argv[3]); std::string f_line, e_line, a_line; while (getline(f_in, f_line) && getline(e_in, e_line)) { /*==========Lies Wörter beider Sätze, sowie zugehörige Alignments aus entsprechenden Dateien aus==========*/ std::string token; std:: istringstream f_ist(f_line), e_ist(e_line); std::vector<std::pair<uint, std::vector<unsigned int> > > f_vec, e_vec; //Speichern alle Wörter jeweiliger Sprache und ihre Alignments //Füge alle französichen Wörter in ein Lexicon ein und schreibe ihre IDs in einen Vektor while(f_ist >> token) { uint id = flex.getWord_or_add(token); std::pair<uint, std::vector<unsigned int> > pair_tmp; pair_tmp.first = id; f_vec.push_back(pair_tmp); } //Füge alle englischen Wörter in ein Lexicon ein und schreibe ihre IDs in einen Vektor while (e_ist >> token) { uint id = elex.getWord_or_add(token); std::pair<uint, std::vector<unsigned int> > pair_tmp; pair_tmp.first = id; e_vec.push_back(pair_tmp); eCount++; } getline(a_in, a_line); //"SEND:" abfangen do { getline(a_in, a_line); if(a_line == "") break; //Alignment eine Satzes zu Ende else { std::istringstream a_ist(a_line); int f_ind, e_ind; std::string s; a_ist >> s >> f_ind >> e_ind; f_vec[f_ind].second.push_back(e_ind); //Speichere einzelnes Alignment in f_vec e_vec[e_ind].second.push_back(f_ind); //Speichere einzelnes Alignment in e_vec uint& f_id = f_vec[f_ind].first, e_id = e_vec[e_ind].first; fe_pair[f_id].pairs[e_id]++; //Paircount für f nach e erhöhen fe_pair[f_id].singlecount++; //Singlecount für f nach e erhöhen ef_pair[e_id].pairs[f_id]++; //Paircount für e nach f erhöhen ef_pair[e_id].singlecount++; //Singlecount für e nach f erhöhen } } while(true); /*==========Beide Sätze liegen nun in Vektoren gespeichert vor, die Alignments jedes Wortes sind in einem Vektor gespeichert========== *==========Führe darauf nun den vorgegebenen Algorithmus aus, um alle Phrasen zu finden und im Präfixbaum zu speichern==========*/ for(unsigned int j1 = 0; j1 < f_vec.size(); j1++) for(unsigned int j2 = j1; j2 < std::min(j1+3,(unsigned int)f_vec.size()); j2++) { //Länge der Quellphrase maximal 3 unsigned int i1, i2; bool set_i = false; //hält mit, ob i1 und i2 gesetzt wurden, oder nicht. for(unsigned int k = j1; k <= j2; k++) if(f_vec[k].second.size() && set_i) { i1 = std::min(i1, f_vec[k].second.front()); //Minimales Alignment innerhalb der Phrase finden => i1 i2 = std::max(i2, f_vec[k].second.back()); //Maximales Alignment innerhalb der Phrase finden => i2 } else if(f_vec[k].second.size() && !(set_i)) { i1 = f_vec[k].second.front(); i2 = f_vec[k].second.back(); set_i = true; } if (set_i){ //leere Phrasen werden nicht geprüft sondern direkt verworfen if(j1 == j2) { //Einzelwortphrasen auf Quellseite werden IMMER extrahiert std::vector<uint> f_vec_tmp, e_vec_tmp; for (unsigned int k = j1; k <= j2; k++) f_vec_tmp.push_back(f_vec[k].first); //Quellphrase in Vektor zusammenstellen for (unsigned int k = i1; k <= i2; k++) e_vec_tmp.push_back(e_vec[k].first); //Zielphrase in Vektor zusammenstellen std::pair<int, PTree<int> > pair_tmp; pair_tmp.first = 0; pTree.traverse(f_vec_tmp,true,pair_tmp)->c.first++; //Quellphrase in Baum einfügen pTree.traverse(f_vec_tmp,false)->c.second.traverse(e_vec_tmp,true,0)->c++; //Zielphrase in "Unter-Baum" einfügen eSinglecount.traverse(e_vec_tmp,true,0)->c++; } else if (i2-i1 < 4) { //Länge der Zielphrase maximal 4 unsigned int j1_test, j2_test; bool set_j_test = false; //hält mit, ob j1_test und j2_test gesetzt wurden, oder nicht for (unsigned int k = i1; k <= i2; k++) if (e_vec[k].second.size() && set_j_test) { j1_test = std::min(j1_test, e_vec[k].second.front()); j2_test = std::max(j2_test, e_vec[k].second.back()); } else if (e_vec[k].second.size() && !(set_j_test)) { j1_test = e_vec[k].second.front(); j2_test = e_vec[k].second.back(); set_j_test = true; } if (set_j_test) //leere Phrasen werden nicht geprüft sondern sofort verworfen if ((j1_test >= j1) && (j2_test <= j2)) { //Phrasen, die den Test bestehen, werden extrahiert std::vector<uint> f_vec_tmp, e_vec_tmp; for (unsigned int k = j1; k <= j2; k++) f_vec_tmp.push_back(f_vec[k].first); for (unsigned int k = i1; k <= i2; k++) e_vec_tmp.push_back(e_vec[k].first); std::pair<int, PTree<int> > pair_tmp; pair_tmp.first = 0; pTree.traverse(f_vec_tmp,true,pair_tmp)->c.first++; //Quellphrase in Baum einfügen pTree.traverse(f_vec_tmp,false)->c.second.traverse(e_vec_tmp,true,0)->c++; //Zielphrase in "Unter-Baum" einfügen eSinglecount.traverse(e_vec_tmp,true,0)->c++; } } } } /*==========Jetzt sind alle erlaubten Phrasen aus diesem Satzpaar im Präfixbaum gespeichert==========*/ /*==========Damit ist die Bearbeitung dieses Satzpaares abgeschlossen und das nächste rückt nach==========*/ } /*==========Nun sind alle erlaubten Phrasen aller Satzpaare - also der gesamten Testdaten - im Präfixbaum gespeichert==========*/ /*==========Im Anschluss muss also der Präfixbaum in eine Phrasentabelle ausgegeben werden==========*/ for (PTree<std::pair<int, PTree<int> > >::iterator itor1 = pTree.begin(); itor1 != pTree.end(); itor1++) { //Durchlaufe den Baum int singlecount_f = (&*itor1) -> c.first; //Zähler für Quellphrase auslesen if (singlecount_f) { std::vector<uint> source_id = (&*itor1) -> phrase();//Quellphrase (in IDs) auslesen std::string source_phrase = ""; for (unsigned int k = 0; k < source_id.size(); k++) //ID-Phrase in Stringphrase umwandeln source_phrase += flex.getString(source_id[k]) + " "; for(PTree<int>::iterator itor2 = (&*itor1) -> c.second.begin(); itor2 != (&*itor1) -> c.second.end(); itor2++) { //Durchlaufe den "Unter-Baum" int paircount = (&*itor2) -> c; //Zähler für Zielphrase auslesen if(paircount != 0) { std::vector<uint> target_id = (&*itor2) -> phrase();//Zielphrase (in IDs) auslesen std::string target_phrase = ""; for (unsigned int k = 0; k < target_id.size(); k++) //ID-Phrase in Stringphrase umwandeln target_phrase += elex.getString(target_id[k]) + " "; double source_to_target = 1; for (unsigned int k = 0; k < target_id.size(); k++) { double sum_stt = 0; for (unsigned int l = 0; l < source_id.size(); l++) { sum_stt += (double) fe_pair[source_id[l]].pairs[target_id[k]] / (double) fe_pair[source_id[l]].singlecount; } source_to_target *= sum_stt / source_id.size(); } source_to_target = -log(source_to_target); double target_to_source = 1; for (unsigned int k = 0; k < source_id.size(); k++) { double sum_tts = 0; for (unsigned int l = 0; l < target_id.size(); l++) { sum_tts += (double) ef_pair[target_id[l]].pairs[source_id[k]] / (double) ef_pair[target_id[l]].singlecount; } target_to_source *= sum_tts / target_id.size(); } target_to_source = -log(target_to_source); uint singlecount_e = eSinglecount.traverse(target_id)->c; double relFreqF = log(singlecount_f) - log(paircount); //Bestimmen der relativen Wahrscheinlichkeit (negativer Logarithmus) double relFreqE = log(singlecount_e) - log(paircount); double unigram = log(eCount) - log(singlecount_e); std::cout << relFreqF << " " << relFreqE << " # " << source_phrase << "# " << target_phrase << "# " << singlecount_f << " "<< singlecount_e << " # " << source_to_target << " " << target_to_source << " # " << unigram << "\n"; //Ausgabe } } } } return 0; }