1 #ifndef BAYES_CLASSIFIER_HPP 2 #define BAYES_CLASSIFIER_HPP 3 4 #include <cmath> 5 6 #include <utility> 7 #include <vector> 8 9 #include <boost/math/constants/constants.hpp> 10 11 namespace osrm 12 { 13 namespace engine 14 { 15 namespace map_matching 16 { 17 18 struct NormalDistribution 19 { NormalDistributionosrm::engine::map_matching::NormalDistribution20 NormalDistribution(const double mean, const double standard_deviation) 21 : mean(mean), standard_deviation(standard_deviation) 22 { 23 } 24 25 // FIXME implement log-probability version since it's faster Densityosrm::engine::map_matching::NormalDistribution26 double Density(const double val) const 27 { 28 using namespace boost::math::constants; 29 30 const double x = val - mean; 31 return 1.0 / (std::sqrt(two_pi<double>()) * standard_deviation) * 32 std::exp(-x * x / (standard_deviation * standard_deviation)); 33 } 34 35 double mean; 36 double standard_deviation; 37 }; 38 39 struct LaplaceDistribution 40 { LaplaceDistributionosrm::engine::map_matching::LaplaceDistribution41 LaplaceDistribution(const double location, const double scale) 42 : location(location), scale(scale) 43 { 44 } 45 46 // FIXME implement log-probability version since it's faster Densityosrm::engine::map_matching::LaplaceDistribution47 double Density(const double val) const 48 { 49 const double x = std::abs(val - location); 50 return 1.0 / (2. * scale) * std::exp(-x / scale); 51 } 52 53 double location; 54 double scale; 55 }; 56 57 template <typename PositiveDistributionT, typename NegativeDistributionT, typename ValueT> 58 class BayesClassifier 59 { 60 public: 61 enum class ClassLabel : unsigned 62 { 63 NEGATIVE, 64 POSITIVE 65 }; 66 using ClassificationT = std::pair<ClassLabel, double>; 67 BayesClassifier(PositiveDistributionT positive_distribution,NegativeDistributionT negative_distribution,const double positive_apriori_probability)68 BayesClassifier(PositiveDistributionT positive_distribution, 69 NegativeDistributionT negative_distribution, 70 const double positive_apriori_probability) 71 : positive_distribution(std::move(positive_distribution)), 72 negative_distribution(std::move(negative_distribution)), 73 positive_apriori_probability(positive_apriori_probability), 74 negative_apriori_probability(1. - positive_apriori_probability) 75 { 76 } 77 78 // Returns label and the probability of the label. classify(const ValueT & v) const79 ClassificationT classify(const ValueT &v) const 80 { 81 const double positive_postpriori = 82 positive_apriori_probability * positive_distribution.Density(v); 83 const double negative_postpriori = 84 negative_apriori_probability * negative_distribution.Density(v); 85 const double norm = positive_postpriori + negative_postpriori; 86 87 if (positive_postpriori > negative_postpriori) 88 { 89 return std::make_pair(ClassLabel::POSITIVE, positive_postpriori / norm); 90 } 91 92 return std::make_pair(ClassLabel::NEGATIVE, negative_postpriori / norm); 93 } 94 95 private: 96 PositiveDistributionT positive_distribution; 97 NegativeDistributionT negative_distribution; 98 double positive_apriori_probability; 99 double negative_apriori_probability; 100 }; 101 } // namespace map_matching 102 } // namespace engine 103 } // namespace osrm 104 105 #endif // BAYES_CLASSIFIER_HPP 106