osrm-backend/include/engine/map_matching/bayes_classifier.hpp

106 lines
2.8 KiB
C++
Raw Normal View History

2015-02-05 20:15:51 -05:00
#ifndef BAYES_CLASSIFIER_HPP
#define BAYES_CLASSIFIER_HPP
#include <cmath>
#include <utility>
2016-05-27 15:05:04 -04:00
#include <vector>
#include <boost/math/constants/constants.hpp>
2016-01-05 10:51:13 -05:00
namespace osrm
{
namespace engine
{
namespace map_matching
{
2015-02-05 20:15:51 -05:00
struct NormalDistribution
{
NormalDistribution(const double mean, const double standard_deviation)
: mean(mean), standard_deviation(standard_deviation)
2015-02-05 20:15:51 -05:00
{
}
2016-02-18 23:05:11 -05:00
// FIXME implement log-probability version since it's faster
double Density(const double val) const
2015-02-05 20:15:51 -05:00
{
using namespace boost::math::constants;
2015-02-05 20:15:51 -05:00
const double x = val - mean;
return 1.0 / (std::sqrt(two_pi<double>()) * standard_deviation) *
std::exp(-x * x / (standard_deviation * standard_deviation));
2015-02-05 20:15:51 -05:00
}
double mean;
double standard_deviation;
};
struct LaplaceDistribution
{
LaplaceDistribution(const double location, const double scale)
: location(location), scale(scale)
2015-02-05 20:15:51 -05:00
{
}
2016-02-18 23:05:11 -05:00
// FIXME implement log-probability version since it's faster
double Density(const double val) const
2015-02-05 20:15:51 -05:00
{
const double x = std::abs(val - location);
return 1.0 / (2. * scale) * std::exp(-x / scale);
2015-02-05 20:15:51 -05:00
}
double location;
double scale;
};
template <typename PositiveDistributionT, typename NegativeDistributionT, typename ValueT>
2015-02-05 20:15:51 -05:00
class BayesClassifier
{
public:
enum class ClassLabel : unsigned
{
NEGATIVE,
POSITIVE
};
using ClassificationT = std::pair<ClassLabel, double>;
2015-02-05 20:15:51 -05:00
BayesClassifier(PositiveDistributionT positive_distribution,
NegativeDistributionT negative_distribution,
2015-02-05 20:15:51 -05:00
const double positive_apriori_probability)
: positive_distribution(std::move(positive_distribution)),
negative_distribution(std::move(negative_distribution)),
positive_apriori_probability(positive_apriori_probability),
negative_apriori_probability(1. - positive_apriori_probability)
2015-02-05 20:15:51 -05:00
{
}
// Returns label and the probability of the label.
ClassificationT classify(const ValueT &v) const
2015-02-05 20:15:51 -05:00
{
const double positive_postpriori =
positive_apriori_probability * positive_distribution.Density(v);
const double negative_postpriori =
negative_apriori_probability * negative_distribution.Density(v);
2015-02-05 20:15:51 -05:00
const double norm = positive_postpriori + negative_postpriori;
if (positive_postpriori > negative_postpriori)
{
return std::make_pair(ClassLabel::POSITIVE, positive_postpriori / norm);
}
return std::make_pair(ClassLabel::NEGATIVE, negative_postpriori / norm);
}
private:
2015-02-05 20:15:51 -05:00
PositiveDistributionT positive_distribution;
NegativeDistributionT negative_distribution;
double positive_apriori_probability;
double negative_apriori_probability;
};
2016-01-05 10:51:13 -05:00
}
}
}
#endif // BAYES_CLASSIFIER_HPP