Some optimizations in trainer

This commit is contained in:
Simon Giraudot 2017-03-03 10:48:46 +01:00
parent eb4a3503a6
commit e1f4ff000b
1 changed files with 76 additions and 68 deletions

View File

@ -283,69 +283,74 @@ public:
double wmax; double wmax;
double factor; double factor;
}; };
std::vector<Feature_training> att_train; std::vector<Feature_training> feature_train;
std::size_t nb_trials = 100; std::size_t nb_trials = 100;
double wmin = 1e-5, wmax = 1e5; double wmin = 1e-5, wmax = 1e5;
double factor = std::pow (wmax/wmin, 1. / (double)nb_trials); double factor = std::pow (wmax/wmin, 1. / (double)nb_trials);
std::size_t att_used = 0; std::size_t feature_used = 0;
std::vector<std::pair<std::size_t, std::size_t> > sorted_features;
for (std::size_t j = 0; j < m_classifier->number_of_features(); ++ j) for (std::size_t j = 0; j < m_classifier->number_of_features(); ++ j)
{ {
Feature_handle att = m_classifier->feature(j); Feature_handle feature = m_classifier->feature(j);
best_weights[j] = att->weight(); best_weights[j] = feature->weight();
std::size_t nb_useful = 0; std::size_t nb_useful = 0;
double min = (std::numeric_limits<double>::max)(); double min = (std::numeric_limits<double>::max)();
double max = -(std::numeric_limits<double>::max)(); double max = -(std::numeric_limits<double>::max)();
att->set_weight(wmin); feature->set_weight(wmin);
for (std::size_t i = 0; i < 100; ++ i) for (std::size_t i = 0; i < 100; ++ i)
{ {
estimate_feature_effect(att); estimate_feature_effect(feature);
if (feature_useful(att)) if (feature_useful(feature))
{ {
CGAL_CLASSTRAINING_CERR << "#"; CGAL_CLASSTRAINING_CERR << "#";
nb_useful ++; nb_useful ++;
min = (std::min) (min, att->weight()); min = (std::min) (min, feature->weight());
max = (std::max) (max, att->weight()); max = (std::max) (max, feature->weight());
} }
else else
CGAL_CLASSTRAINING_CERR << "-"; CGAL_CLASSTRAINING_CERR << "-";
att->set_weight(factor * att->weight()); feature->set_weight(factor * feature->weight());
} }
CGAL_CLASSTRAINING_CERR << std::endl; CGAL_CLASSTRAINING_CERR << std::endl;
CGAL_CLASSTRAINING_CERR << att->name() << " useful in " CGAL_CLASSTRAINING_CERR << feature->name() << " useful in "
<< nb_useful << "% of the cases, in interval [ " << nb_useful << "% of the cases, in interval [ "
<< min << " ; " << max << " ]" << std::endl; << min << " ; " << max << " ]" << std::endl;
att_train.push_back (Feature_training()); feature_train.push_back (Feature_training());
att_train.back().skipped = false; feature_train.back().skipped = false;
att_train.back().wmin = min / factor; feature_train.back().wmin = min / factor;
att_train.back().wmax = max * factor; feature_train.back().wmax = max * factor;
if (nb_useful < 2) if (nb_useful < 2)
{ {
att_train.back().skipped = true; feature_train.back().skipped = true;
att->set_weight(0.); feature->set_weight(0.);
best_weights[j] = att->weight(); best_weights[j] = feature->weight();
} }
else if (best_weights[j] == 1.) else if (best_weights[j] == 1.)
{ {
att->set_weight(0.5 * (att_train.back().wmin + att_train.back().wmax)); feature->set_weight(0.5 * (feature_train.back().wmin + feature_train.back().wmax));
best_weights[j] = att->weight(); best_weights[j] = feature->weight();
++ att_used; sorted_features.push_back (std::make_pair (-nb_useful, j));
++ feature_used;
} }
else else
{ {
att->set_weight(best_weights[j]); feature->set_weight(best_weights[j]);
++ att_used; sorted_features.push_back (std::make_pair (-nb_useful, j));
++ feature_used;
} }
estimate_feature_effect(att); estimate_feature_effect(feature);
} }
std::size_t nb_trials_per_feature = 1 + (std::size_t)(nb_tests / (double)(att_used)); std::size_t nb_trials_per_feature = 1 + (std::size_t)(nb_tests / (double)(feature_used));
CGAL_CLASSIFICATION_CERR << "Trials = " << nb_tests << ", features = " << att_used CGAL_CLASSIFICATION_CERR << "Trials = " << nb_tests << ", features = " << feature_used
<< ", trials per att = " << nb_trials_per_feature << std::endl; << ", trials per feature = " << nb_trials_per_feature << std::endl;
for (std::size_t i = 0; i < att_train.size(); ++ i) for (std::size_t i = 0; i < feature_train.size(); ++ i)
if (!(att_train[i].skipped)) if (!(feature_train[i].skipped))
att_train[i].factor = std::pow (att_train[i].wmax / att_train[i].wmin, feature_train[i].factor = std::pow (feature_train[i].wmax / feature_train[i].wmin,
1. / (double)nb_trials_per_feature); 1. / (double)nb_trials_per_feature);
@ -358,21 +363,24 @@ public:
CGAL_CLASSIFICATION_CERR << 100. * best_score << "% (found at initialization)" << std::endl; CGAL_CLASSIFICATION_CERR << 100. * best_score << "% (found at initialization)" << std::endl;
std::size_t current_att_changed = 0; std::size_t current_feature_changed = 0;
CGAL::Timer teff, tconf, tscore; CGAL::Timer teff, tconf, tscore;
for (std::size_t i = 0; i < att_used; ++ i)
std::sort (sorted_features.begin(), sorted_features.end());
for (std::size_t i = 0; i < sorted_features.size(); ++ i)
{ {
while (att_train[current_att_changed].skipped) current_feature_changed = sorted_features[i].second;
{ // while (feature_train[current_feature_changed].skipped)
++ current_att_changed; // {
if (current_att_changed == m_classifier->number_of_features()) // ++ current_feature_changed;
current_att_changed = 0; // if (current_feature_changed == m_classifier->number_of_features())
} // current_feature_changed = 0;
// }
std::size_t nb_used = 0; std::size_t nb_used = 0;
for (std::size_t j = 0; j < m_classifier->number_of_features(); ++ j) for (std::size_t j = 0; j < m_classifier->number_of_features(); ++ j)
{ {
if (j == current_att_changed) if (j == current_feature_changed)
continue; continue;
m_classifier->feature(j)->set_weight(best_weights[j]); m_classifier->feature(j)->set_weight(best_weights[j]);
@ -382,14 +390,14 @@ public:
if (feature_useful(m_classifier->feature(j))) if (feature_useful(m_classifier->feature(j)))
nb_used ++; nb_used ++;
} }
Feature_handle current_att = m_classifier->feature(current_att_changed); Feature_handle current_feature = m_classifier->feature(current_feature_changed);
const Feature_training& tr = att_train[current_att_changed]; const Feature_training& tr = feature_train[current_feature_changed];
current_att->set_weight(tr.wmin); current_feature->set_weight(tr.wmin);
for (std::size_t j = 0; j < nb_trials_per_feature; ++ j) for (std::size_t j = 0; j < nb_trials_per_feature; ++ j)
{ {
teff.start(); teff.start();
estimate_feature_effect(current_att); estimate_feature_effect(current_feature);
teff.stop(); teff.stop();
tconf.start(); tconf.start();
@ -405,18 +413,18 @@ public:
best_confidence = worst_confidence; best_confidence = worst_confidence;
CGAL_CLASSIFICATION_CERR << 100. * best_score << "% (found at iteration " CGAL_CLASSIFICATION_CERR << 100. * best_score << "% (found at iteration "
<< (i * nb_trials_per_feature) + j << "/" << nb_tests << ", " << (i * nb_trials_per_feature) + j << "/" << nb_tests << ", "
<< nb_used + (feature_useful(current_att) ? 1 : 0) << nb_used + (feature_useful(current_feature) ? 1 : 0)
<< "/" << m_classifier->number_of_features() << " feature(s) used)" << std::endl; << "/" << m_classifier->number_of_features() << " feature(s) used)" << std::endl;
for (std::size_t k = 0; k < m_classifier->number_of_features(); ++ k) for (std::size_t k = 0; k < m_classifier->number_of_features(); ++ k)
{ {
Feature_handle att = m_classifier->feature(k); Feature_handle feature = m_classifier->feature(k);
best_weights[k] = att->weight(); best_weights[k] = feature->weight();
} }
} }
current_att->set_weight(current_att->weight() * tr.factor); current_feature->set_weight(current_feature->weight() * tr.factor);
} }
++ current_att_changed; ++ current_feature_changed;
} }
std::cerr << "Estimation of effects = " << teff.time() << std::endl std::cerr << "Estimation of effects = " << teff.time() << std::endl
@ -425,8 +433,8 @@ public:
for (std::size_t i = 0; i < best_weights.size(); ++ i) for (std::size_t i = 0; i < best_weights.size(); ++ i)
{ {
Feature_handle att = m_classifier->feature(i); Feature_handle feature = m_classifier->feature(i);
att->set_weight(best_weights[i]); feature->set_weight(best_weights[i]);
} }
estimate_features_effects(); estimate_features_effects();
@ -437,22 +445,22 @@ public:
std::size_t nb_removed = 0; std::size_t nb_removed = 0;
for (std::size_t i = 0; i < best_weights.size(); ++ i) for (std::size_t i = 0; i < best_weights.size(); ++ i)
{ {
Feature_handle att = m_classifier->feature(i); Feature_handle feature = m_classifier->feature(i);
CGAL_CLASSTRAINING_CERR << "FEATURE " << att->name() << ": " << best_weights[i] << std::endl; CGAL_CLASSTRAINING_CERR << "FEATURE " << feature->name() << ": " << best_weights[i] << std::endl;
att->set_weight(best_weights[i]); feature->set_weight(best_weights[i]);
Classification::Feature::Effect side = m_classifier->label(0)->feature_effect(att); Classification::Feature::Effect side = m_classifier->label(0)->feature_effect(feature);
bool to_remove = true; bool to_remove = true;
for (std::size_t j = 0; j < m_classifier->number_of_labels(); ++ j) for (std::size_t j = 0; j < m_classifier->number_of_labels(); ++ j)
{ {
Label_handle clabel = m_classifier->label(j); Label_handle clabel = m_classifier->label(j);
if (clabel->feature_effect(att) == Classification::Feature::FAVORING) if (clabel->feature_effect(feature) == Classification::Feature::FAVORING)
CGAL_CLASSTRAINING_CERR << " * Favored for "; CGAL_CLASSTRAINING_CERR << " * Favored for ";
else if (clabel->feature_effect(att) == Classification::Feature::PENALIZING) else if (clabel->feature_effect(feature) == Classification::Feature::PENALIZING)
CGAL_CLASSTRAINING_CERR << " * Penalized for "; CGAL_CLASSTRAINING_CERR << " * Penalized for ";
else else
CGAL_CLASSTRAINING_CERR << " * Neutral for "; CGAL_CLASSTRAINING_CERR << " * Neutral for ";
if (clabel->feature_effect(att) != side) if (clabel->feature_effect(feature) != side)
to_remove = false; to_remove = false;
CGAL_CLASSTRAINING_CERR << clabel->name() << std::endl; CGAL_CLASSTRAINING_CERR << clabel->name() << std::endl;
} }
@ -612,7 +620,7 @@ private:
estimate_feature_effect (m_classifier->feature(i)); estimate_feature_effect (m_classifier->feature(i));
} }
void estimate_feature_effect (Feature_handle att) void estimate_feature_effect (Feature_handle feature)
{ {
std::vector<double> mean (m_classifier->number_of_labels(), 0.); std::vector<double> mean (m_classifier->number_of_labels(), 0.);
@ -620,7 +628,7 @@ private:
{ {
for (std::size_t k = 0; k < m_training_sets[j].size(); ++ k) for (std::size_t k = 0; k < m_training_sets[j].size(); ++ k)
{ {
double val = att->normalized(m_training_sets[j][k]); double val = feature->normalized(m_training_sets[j][k]);
mean[j] += val; mean[j] += val;
} }
mean[j] /= m_training_sets[j].size(); mean[j] /= m_training_sets[j].size();
@ -634,16 +642,16 @@ private:
for (std::size_t k = 0; k < m_training_sets[j].size(); ++ k) for (std::size_t k = 0; k < m_training_sets[j].size(); ++ k)
{ {
double val = att->normalized(m_training_sets[j][k]); double val = feature->normalized(m_training_sets[j][k]);
sd[j] += (val - mean[j]) * (val - mean[j]); sd[j] += (val - mean[j]) * (val - mean[j]);
} }
sd[j] = std::sqrt (sd[j] / m_training_sets[j].size()); sd[j] = std::sqrt (sd[j] / m_training_sets[j].size());
if (mean[j] - sd[j] > 0.5) if (mean[j] - sd[j] > 0.75)
clabel->set_feature_effect (att, Classification::Feature::FAVORING); clabel->set_feature_effect (feature, Classification::Feature::FAVORING);
else if (mean[j] + sd[j] < 0.5) else if (mean[j] + sd[j] < 0.25)
clabel->set_feature_effect (att, Classification::Feature::PENALIZING); clabel->set_feature_effect (feature, Classification::Feature::PENALIZING);
else else
clabel->set_feature_effect (att, Classification::Feature::NEUTRAL); clabel->set_feature_effect (feature, Classification::Feature::NEUTRAL);
} }
} }
@ -702,11 +710,11 @@ private:
return std::make_pair (worst_confidence, worst_score); return std::make_pair (worst_confidence, worst_score);
} }
bool feature_useful (Feature_handle att) bool feature_useful (Feature_handle feature)
{ {
Classification::Feature::Effect side = m_classifier->label(0)->feature_effect(att); Classification::Feature::Effect side = m_classifier->label(0)->feature_effect(feature);
for (std::size_t k = 1; k < m_classifier->number_of_labels(); ++ k) for (std::size_t k = 1; k < m_classifier->number_of_labels(); ++ k)
if (m_classifier->label(k)->feature_effect(att) != side) if (m_classifier->label(k)->feature_effect(feature) != side)
return true; return true;
return false; return false;
} }