From 1b16dd126bcbbde1b949712ba65164df529f3c50 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Sat, 7 Feb 2015 15:39:07 +0100 Subject: [PATCH] Actually compute and transmit confidence in the response --- algorithms/bayes_classifier.hpp | 5 +++-- plugins/map_matching.hpp | 40 ++++++++++++++++++++++++++++++++- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/algorithms/bayes_classifier.hpp b/algorithms/bayes_classifier.hpp index 1fc53937a..042259111 100644 --- a/algorithms/bayes_classifier.hpp +++ b/algorithms/bayes_classifier.hpp @@ -60,7 +60,7 @@ struct LaplaceDistribution } // FIXME implement log-probability version since its faster - double probabilityDensityFunction(const double val) + double probabilityDensityFunction(const double val) const { const double x = std::abs(val - location); return 1.0 / (2*scale) * std::exp(-x / scale); @@ -75,6 +75,7 @@ class BayesClassifier { public: enum class ClassLabel : unsigned {NEGATIVE = 0, POSITIVE}; + using ClassificationT = std::pair; BayesClassifier(const PositiveDistributionT& positive_distribution, const NegativeDistributionT& negative_distribution, @@ -89,7 +90,7 @@ public: /* * Returns label and the probability of the label. */ - std::pair classify(const ValueT& v) + ClassificationT classify(const ValueT& v) const { const double positive_postpriori = positive_apriori_probability * positive_distribution.probabilityDensityFunction(v); const double negative_postpriori = negative_apriori_probability * negative_distribution.probabilityDensityFunction(v); diff --git a/plugins/map_matching.hpp b/plugins/map_matching.hpp index 1838ab0b3..8c3c64a12 100644 --- a/plugins/map_matching.hpp +++ b/plugins/map_matching.hpp @@ -48,6 +48,9 @@ template class MapMatchingPlugin : public BasePlugin std::unordered_map descriptor_table; std::shared_ptr> search_engine_ptr; + using ClassifierT = BayesClassifier; + using TraceClassification = ClassifierT::ClassificationT; + public: MapMatchingPlugin(DataFacadeT *facade) : descriptor_string("match") @@ -69,6 +72,29 @@ template class MapMatchingPlugin : public BasePlugin const std::string GetDescriptor() const final { return descriptor_string; } + TraceClassification classify(double trace_length, const std::vector& matched_nodes, int removed_points) const + { + double matching_length = 0; + for (const auto current_node : osrm::irange(0, matched_nodes.size()-1)) + { + matching_length += coordinate_calculation::great_circle_distance( + matched_nodes[current_node].location, + matched_nodes[current_node + 1].location); + } + double distance_feature = -std::log(trace_length / matching_length); + + auto label_with_confidence = classifier.classify(distance_feature); + + // "second stage classifier": if we need to remove points there is something fishy + if (removed_points > 0) + { + label_with_confidence.first = ClassifierT::ClassLabel::NEGATIVE; + label_with_confidence.second = 1.0; + } + + return label_with_confidence; + } + int HandleRequest(const RouteParameters &route_parameters, JSON::Object &json_result) final { // check number of parameters @@ -84,6 +110,7 @@ template class MapMatchingPlugin : public BasePlugin double last_distance = coordinate_calculation::great_circle_distance( input_coords[0], input_coords[1]); + double trace_length = 0; for (const auto current_coordinate : osrm::irange(0, input_coords.size())) { if (0 < current_coordinate) @@ -91,6 +118,7 @@ template class MapMatchingPlugin : public BasePlugin last_distance = coordinate_calculation::great_circle_distance( input_coords[current_coordinate - 1], input_coords[current_coordinate]); + trace_length += last_distance; } if (input_coords.size()-1 > current_coordinate && 0 < current_coordinate) @@ -126,6 +154,16 @@ template class MapMatchingPlugin : public BasePlugin JSON::Object debug_info; search_engine_ptr->map_matching(candidate_lists, input_coords, uturn_indicators, matched_nodes, debug_info); + TraceClassification classification = classify(trace_length, matched_nodes, input_coords.size() - matched_nodes.size()); + if (classification.first == ClassifierT::ClassLabel::POSITIVE) + { + json_result.values["confidence"] = classification.second; + } + else + { + json_result.values["confidence"] = 1-classification.second; + } + InternalRouteResult raw_route; PhantomNodes current_phantom_node_pair; for (unsigned i = 0; i < matched_nodes.size() - 1; ++i) @@ -183,7 +221,7 @@ template class MapMatchingPlugin : public BasePlugin private: std::string descriptor_string; DataFacadeT *facade; - BayesClassifier classifier; + ClassifierT classifier; }; #endif /* MAP_MATCHING_PLUGIN_H */