From d32b4738551b7d8fbfe0657cf8cf16ee022aa807 Mon Sep 17 00:00:00 2001 From: Franck Dary <franck.dary@etu.univ-amu.fr> Date: Mon, 3 Dec 2018 13:55:38 +0100 Subject: [PATCH] Added error detector decoder --- error_correction/CMakeLists.txt | 5 + .../src/macaon_decode_error_detector.cpp | 160 ++++++++++++++++++ .../src/macaon_train_error_detector.cpp | 38 ++++- 3 files changed, 194 insertions(+), 9 deletions(-) create mode 100644 error_correction/src/macaon_decode_error_detector.cpp diff --git a/error_correction/CMakeLists.txt b/error_correction/CMakeLists.txt index e5db282..6cfa2b5 100644 --- a/error_correction/CMakeLists.txt +++ b/error_correction/CMakeLists.txt @@ -9,3 +9,8 @@ add_executable(macaon_train_error_detector src/macaon_train_error_detector.cpp) target_link_libraries(macaon_train_error_detector transition_machine) target_link_libraries(macaon_train_error_detector ${Boost_PROGRAM_OPTIONS_LIBRARY}) install(TARGETS macaon_train_error_detector DESTINATION bin) + +add_executable(macaon_decode_error_detector src/macaon_decode_error_detector.cpp) +target_link_libraries(macaon_decode_error_detector transition_machine) +target_link_libraries(macaon_decode_error_detector ${Boost_PROGRAM_OPTIONS_LIBRARY}) +install(TARGETS macaon_decode_error_detector DESTINATION bin) diff --git a/error_correction/src/macaon_decode_error_detector.cpp b/error_correction/src/macaon_decode_error_detector.cpp new file mode 100644 index 0000000..488fabf --- /dev/null +++ b/error_correction/src/macaon_decode_error_detector.cpp @@ -0,0 +1,160 @@ +/// @file macaon_decode_error_detector.cpp +/// @author Franck Dary +/// @version 1.0 +/// @date 2018-12-03 + +#include <cstdio> +#include <cstdlib> +#include <boost/program_options.hpp> +#include "BD.hpp" +#include "Config.hpp" +#include "TransitionMachine.hpp" + +namespace po = boost::program_options; + +/// @brief Get the list of mandatory and optional program arguments. +/// +/// @return The lists. +po::options_description getOptionsDescription() +{ + po::options_description desc("Command-Line Arguments "); + + po::options_description req("Required"); + req.add_options() + ("expName", po::value<std::string>()->required(), + "Name of this experiment") + ("tm", po::value<std::string>()->required(), + "File describing the Tape Machine to use") + ("bd", po::value<std::string>()->required(), + "BD file that describes the multi-tapes buffer") + ("mcd", po::value<std::string>()->required(), + "MCD file that describes the input") + ("input,I", po::value<std::string>()->required(), + "Input file formated according to the mcd"); + + po::options_description opt("Optional"); + opt.add_options() + ("help,h", "Produce this help message") + ("debug,d", "Print infos on stderr") + ("printEntropy", "Print entropy for each sequence") + ("sequenceDelimiterTape", po::value<std::string>()->default_value("EOS"), + "The name of the buffer's tape that contains the delimiter token for a sequence") + ("sequenceDelimiter", po::value<std::string>()->default_value("1"), + "The value of the token that act as a delimiter for sequences") + ("showFeatureRepresentation", po::value<bool>()->default_value(false), + "For each state of the Config, show its feature representation") + ("lang", po::value<std::string>()->default_value("fr"), + "Language you are working with"); + + desc.add(req).add(opt); + + return desc; +} + +/// @brief Store the program arguments inside a variables_map +/// +/// @param od The description of all the possible options. +/// @param argc The number of arguments given to this program. +/// @param argv The values of arguments given to this program. +/// +/// @return The variables map +po::variables_map checkOptions(po::options_description & od, int argc, char ** argv) +{ + po::variables_map vm; + + try {po::store(po::parse_command_line(argc, argv, od), vm);} + catch(std::exception& e) + { + std::cerr << "Error: " << e.what() << "\n"; + od.print(std::cerr); + exit(1); + } + + if (vm.count("help")) + { + std::cout << od << "\n"; + exit(0); + } + + try {po::notify(vm);} + catch(std::exception& e) + { + std::cerr << "Error: " << e.what() << "\n"; + od.print(std::cerr); + exit(1); + } + + return vm; +} + +/// @brief Uses a pre-trained TransitionMachine to predict and add information to a structured input file. +/// +/// @param argc The number of arguments given to this program. +/// @param argv[] Array of arguments given to this program. +/// +/// @return 0 if there was no crash. +int main(int argc, char * argv[]) +{ + auto od = getOptionsDescription(); + + po::variables_map vm = checkOptions(od, argc, argv); + + ProgramParameters::expName = vm["expName"].as<std::string>(); + ProgramParameters::tmName = vm["tm"].as<std::string>(); + ProgramParameters::bdName = vm["bd"].as<std::string>(); + ProgramParameters::input = vm["input"].as<std::string>(); + ProgramParameters::mcdName = vm["mcd"].as<std::string>(); + ProgramParameters::debug = vm.count("debug") == 0 ? false : true; + ProgramParameters::printEntropy = vm.count("printEntropy") == 0 ? false : true; + ProgramParameters::lang = vm["lang"].as<std::string>(); + ProgramParameters::sequenceDelimiterTape = vm["sequenceDelimiterTape"].as<std::string>(); + ProgramParameters::sequenceDelimiter = vm["sequenceDelimiter"].as<std::string>(); + ProgramParameters::showFeatureRepresentation = vm["showFeatureRepresentation"].as<bool>(); + + const char * MACAON_DIR = std::getenv("MACAON_DIR"); + std::string slash = "/"; + ProgramParameters::expPath = MACAON_DIR + slash + ProgramParameters::lang + slash + "bin/" + ProgramParameters::expName + slash; + + ProgramParameters::tmFilename = ProgramParameters::expPath + ProgramParameters::tmName; + ProgramParameters::bdFilename = ProgramParameters::expPath + ProgramParameters::bdName; + ProgramParameters::mcdFilename = ProgramParameters::mcdName; + + TransitionMachine tm(false); + + BD bd(ProgramParameters::bdFilename, ProgramParameters::mcdFilename); + Config config(bd); + + File input(ProgramParameters::input, "r"); + FILE * inputPtr = input.getDescriptor(); + + int isError, errorIndex; + while (fscanf(inputPtr, "%d\t%d\n", &isError, &errorIndex) == 2) + { + config.loadFromFile(input); + + TransitionMachine::State * currentState = tm.getCurrentState(); + Classifier * classifier = currentState->classifier; + config.setCurrentStateName(¤tState->name); + Dict::currentClassifierName = classifier->name; + classifier->initClassifier(config); + + auto weightedActions = classifier->weightActions(config); + std::string pAction = ""; + + for (auto & it : weightedActions) + if (it.first) + if (pAction == "") + { + pAction = it.second.second; + break; + } + + Action * action = classifier->getAction(pAction); + + action->apply(config); + + } + + return 0; +} + diff --git a/error_correction/src/macaon_train_error_detector.cpp b/error_correction/src/macaon_train_error_detector.cpp index 1a621b4..8238cc1 100644 --- a/error_correction/src/macaon_train_error_detector.cpp +++ b/error_correction/src/macaon_train_error_detector.cpp @@ -213,30 +213,53 @@ std::map<std::string, std::pair<float, std::pair<float, float> > > getScoreOnDev classifierName = classifier->name; } + int pred1Hyp0 = 0; + int pred0Hyp1 = 0; + int pred0Hyp0 = 0; + int pred1Hyp1 = 0; + for (unsigned int i = 0; i < devIsErrors.size(); i++) { if (devIsErrors[i] == 0) { counts[classifierName].first++; if (predictions[i] == 0) + { counts[classifierName].second++; + pred0Hyp0++; + } + else + pred1Hyp0++; } else if (i > 0 && devIsErrors[i] == 1 && devIsErrors[i-1] == 0) { counts[classifierName].first++; unsigned int j; + bool found = false; for (j = i; devIsErrors[j] == 1 && j < devIsErrors.size(); j++) { if (predictions[j] == 1) { counts[classifierName].second++; + pred1Hyp1++; + found = true; break; } } i = j; + if (!found) + pred0Hyp1++; } } + fprintf(stderr, "Class 0 nbExemples : %d\n", pred0Hyp0+pred1Hyp0); + fprintf(stderr, "Class 0 precision : %.2f\n", 100.0*pred0Hyp0 / (pred0Hyp0+pred1Hyp0)); + fprintf(stderr, "Class 0 recall : %.2f\n\n", 100.0*pred0Hyp0 / (pred0Hyp0+pred0Hyp1)); + + fprintf(stderr, "Class 1 nbExemples : %d\n", pred0Hyp1+pred1Hyp1); + fprintf(stderr, "Class 1 precision : %.2f\n", 100.0*pred1Hyp1 / (pred1Hyp1+pred0Hyp1)); + fprintf(stderr, "Class 1 recall : %.2f\n", 100.0*pred1Hyp1 / (pred1Hyp1+pred1Hyp0)); + std::map<std::string, std::pair<float,std::pair<float,float> > > scores; for (auto & it : counts) @@ -260,18 +283,15 @@ void printScoresAndSave(FILE * output, std::map< std::string, std::pair<int, int auto devScores = getScoreOnDev(tm, devConfigs, devIsErrors, devErrorIndexes); - if (true) + for (auto & it : devScores) { - for (auto & it : devScores) + if (bestScores.count(it.first) == 0 || bestScores[it.first] < it.second.first) { - if (bestScores.count(it.first) == 0 || bestScores[it.first] < it.second.first) - { - bestScores[it.first] = it.second.first; - saved[it.first] = true; - } - else - saved[it.first] = false; + bestScores[it.first] = it.second.first; + saved[it.first] = true; } + else + saved[it.first] = false; } auto classifiers = tm.getClassifiers(); -- GitLab