Round relevance (plus refactor)

This commit is contained in:
Juan Ignacio Sánchez Lara
2018-07-17 13:56:01 +02:00
parent d060bd8229
commit b90d402fa9
7 changed files with 42 additions and 38 deletions
@@ -6,13 +6,17 @@ from collections import namedtuple
import json import json
METADATA_RELEVANCE = 'relevance'
METADATA_PRECISION = 'precision'
METADATA_MATCH_TYPES = 'match_types'
PRECISION_PRECISE = 'precise' PRECISION_PRECISE = 'precise'
PRECISION_INTERPOLATED = 'interpolated' PRECISION_INTERPOLATED = 'interpolated'
def geocoder_metadata(relevance, precision, match_types):
return {
'relevance': round(relevance, 2),
'precision': precision,
'match_types': match_types
}
def compose_address(street, city=None, state=None, country=None): def compose_address(street, city=None, state=None, country=None):
return ', '.join(filter(None, [street, city, state, country])) return ', '.join(filter(None, [street, city, state, country]))
@@ -4,7 +4,7 @@
from urlparse import parse_qs from urlparse import parse_qs
from exceptions import MalformedResult from exceptions import MalformedResult
from cartodb_services.geocoder import compose_address, METADATA_RELEVANCE, METADATA_PRECISION, METADATA_MATCH_TYPES, PRECISION_PRECISE, PRECISION_INTERPOLATED from cartodb_services.geocoder import compose_address, geocoder_metadata, PRECISION_PRECISE, PRECISION_INTERPOLATED
from cartodb_services.google.exceptions import InvalidGoogleCredentials from cartodb_services.google.exceptions import InvalidGoogleCredentials
from client_factory import GoogleMapsClientFactory from client_factory import GoogleMapsClientFactory
@@ -82,11 +82,11 @@ class GoogleMapsGeocoder():
partial_factor = PARTIAL_FACTOR if partial_match else 1 partial_factor = PARTIAL_FACTOR if partial_match else 1
match_types = [MATCH_TYPE_BY_MATCH_LEVEL.get(match_level, None) match_types = [MATCH_TYPE_BY_MATCH_LEVEL.get(match_level, None)
for match_level in result['types']] for match_level in result['types']]
return { return geocoder_metadata(
METADATA_RELEVANCE: base_relevance * partial_factor, base_relevance * partial_factor,
METADATA_PRECISION: PRECISION_BY_LOCATION_TYPE[location_type], PRECISION_BY_LOCATION_TYPE[location_type],
METADATA_MATCH_TYPES: filter(None, match_types) filter(None, match_types)
} )
def _build_optional_parameters(self, city=None, state=None, def _build_optional_parameters(self, city=None, state=None,
@@ -8,7 +8,7 @@ from collections import namedtuple
from requests.adapters import HTTPAdapter from requests.adapters import HTTPAdapter
from cartodb_services import StreetPointBulkGeocoder from cartodb_services import StreetPointBulkGeocoder
from cartodb_services.here import HereMapsGeocoder from cartodb_services.here import HereMapsGeocoder
from cartodb_services.geocoder import METADATA_RELEVANCE, METADATA_PRECISION, METADATA_MATCH_TYPES from cartodb_services.geocoder import geocoder_metadata
from cartodb_services.metrics import Traceable from cartodb_services.metrics import Traceable
from cartodb_services.tools.exceptions import ServiceException from cartodb_services.tools.exceptions import ServiceException
@@ -138,11 +138,11 @@ class HereMapsBulkGeocoder(HereMapsGeocoder, StreetPointBulkGeocoder):
match_type = self.MATCH_TYPE_BY_MATCH_LEVEL.get(row['matchLevel'], None) match_type = self.MATCH_TYPE_BY_MATCH_LEVEL.get(row['matchLevel'], None)
results.append((row['recId'], results.append((row['recId'],
[row['displayLongitude'], row['displayLatitude']], [row['displayLongitude'], row['displayLatitude']],
{ geocoder_metadata(
METADATA_RELEVANCE: float(row['relevance']), float(row['relevance']),
METADATA_PRECISION: precision, precision,
METADATA_MATCH_TYPES: [match_type] if match_type else [] [match_type] if match_type else []
})) )))
return results return results
@@ -6,7 +6,7 @@ import requests
from requests.adapters import HTTPAdapter from requests.adapters import HTTPAdapter
from exceptions import * from exceptions import *
from cartodb_services.geocoder import METADATA_RELEVANCE, METADATA_PRECISION, METADATA_MATCH_TYPES, PRECISION_PRECISE, PRECISION_INTERPOLATED from cartodb_services.geocoder import PRECISION_PRECISE, PRECISION_INTERPOLATED, geocoder_metadata
from cartodb_services.metrics import Traceable from cartodb_services.metrics import Traceable
class HereMapsGeocoder(Traceable): class HereMapsGeocoder(Traceable):
@@ -146,8 +146,8 @@ class HereMapsGeocoder(Traceable):
precision = self.PRECISION_BY_MATCH_TYPE[ precision = self.PRECISION_BY_MATCH_TYPE[
result.get('MatchType', 'pointAddress')] result.get('MatchType', 'pointAddress')]
match_type = self.MATCH_TYPE_BY_MATCH_LEVEL.get(result['MatchLevel'], None) match_type = self.MATCH_TYPE_BY_MATCH_LEVEL.get(result['MatchLevel'], None)
return { return geocoder_metadata(
METADATA_RELEVANCE: result['Relevance'], result['Relevance'],
METADATA_PRECISION: precision, precision,
METADATA_MATCH_TYPES: [match_type] if match_type else [] [match_type] if match_type else []
} )
@@ -5,7 +5,7 @@ Python client for the Mapbox Geocoder service.
import json import json
import requests import requests
from mapbox import Geocoder from mapbox import Geocoder
from cartodb_services.geocoder import METADATA_RELEVANCE, METADATA_PRECISION, METADATA_MATCH_TYPES, PRECISION_PRECISE, PRECISION_INTERPOLATED from cartodb_services.geocoder import PRECISION_PRECISE, PRECISION_INTERPOLATED, geocoder_metadata
from cartodb_services.metrics import Traceable from cartodb_services.metrics import Traceable
from cartodb_services.tools.exceptions import ServiceException from cartodb_services.tools.exceptions import ServiceException
from cartodb_services.tools.qps import qps_retry from cartodb_services.tools.qps import qps_retry
@@ -92,11 +92,11 @@ class MapboxGeocoder(Traceable):
match_types = [MATCH_TYPE_BY_MATCH_LEVEL.get(match_level, None) match_types = [MATCH_TYPE_BY_MATCH_LEVEL.get(match_level, None)
for match_level in result['place_type']] for match_level in result['place_type']]
return { return geocoder_metadata(
METADATA_RELEVANCE: self._normalize_relevance(float(result['relevance'])), self._normalize_relevance(float(result['relevance'])),
METADATA_PRECISION: precision, precision,
METADATA_MATCH_TYPES: filter(None, match_types) filter(None, match_types)
} )
def _normalize_relevance(self, relevance): def _normalize_relevance(self, relevance):
return 1 if relevance >= 0.99 else relevance return 1 if relevance >= 0.99 else relevance
@@ -5,7 +5,7 @@ import json
import requests import requests
from uritemplate import URITemplate from uritemplate import URITemplate
from math import tanh from math import tanh
from cartodb_services.geocoder import METADATA_RELEVANCE, METADATA_PRECISION, METADATA_MATCH_TYPES, PRECISION_PRECISE, PRECISION_INTERPOLATED from cartodb_services.geocoder import PRECISION_PRECISE, PRECISION_INTERPOLATED, geocoder_metadata
from cartodb_services.metrics import Traceable from cartodb_services.metrics import Traceable
from cartodb_services.tools.exceptions import ServiceException from cartodb_services.tools.exceptions import ServiceException
from cartodb_services.tools.qps import qps_retry from cartodb_services.tools.qps import qps_retry
@@ -144,11 +144,11 @@ class TomTomGeocoder(Traceable):
def _extract_metadata_from_result(self, result): def _extract_metadata_from_result(self, result):
score = self._normalize_score(result['score']) score = self._normalize_score(result['score'])
match_type = MATCH_TYPE_BY_MATCH_LEVEL.get(result['type'], None) match_type = MATCH_TYPE_BY_MATCH_LEVEL.get(result['type'], None)
return { return geocoder_metadata(
METADATA_RELEVANCE: score, score,
METADATA_PRECISION: self._precision_from_score(score), self._precision_from_score(score),
METADATA_MATCH_TYPES: [match_type] if match_type else [] [match_type] if match_type else []
} )
def _normalize_score(self, score): def _normalize_score(self, score):
return tanh(score * SCORE_NORMALIZATION_FACTOR) return tanh(score * SCORE_NORMALIZATION_FACTOR)
+4 -4
View File
@@ -87,14 +87,14 @@ class TestStreetFunctionsSetUp(TestCase):
'Plaza España, Barcelona': 'Plaza España, Barcelona':
{'relevance': 0.85, 'precision': 'precise', 'match_types': ['street']}, {'relevance': 0.85, 'precision': 'precise', 'match_types': ['street']},
'Santiago Rusiñol 123, Valladolid': 'Santiago Rusiñol 123, Valladolid':
{'relevance': 0.448283494533, 'precision': 'interpolated', 'match_types': ['street']} {'relevance': 0.45, 'precision': 'interpolated', 'match_types': ['street']}
} }
MAPBOX_METADATAS = { MAPBOX_METADATAS = {
'Plaza España, Barcelona': 'Plaza España, Barcelona':
{'relevance': 0.666, 'precision': 'precise', 'match_types': ['point_of_interest']}, {'relevance': 0.67, 'precision': 'precise', 'match_types': ['point_of_interest']},
'Santiago Rusiñol 123, Valladolid': 'Santiago Rusiñol 123, Valladolid':
{'relevance': 0.666, 'precision': 'precise', 'match_types': ['point_of_interest']} # TODO: wrong {'relevance': 0.67, 'precision': 'precise', 'match_types': ['point_of_interest']} # TODO: wrong
} }
METADATAS = { METADATAS = {
@@ -410,7 +410,7 @@ class TestBulkStreetFunctions(TestStreetFunctionsSetUp):
def assert_metadata(metadata, expected): def assert_metadata(metadata, expected):
relevance = metadata['relevance'] relevance = metadata['relevance']
expected_relevance = expected['relevance'] expected_relevance = expected['relevance']
assert_true(isclose(relevance, expected_relevance, 0.05), assert_true(isclose(relevance, expected_relevance, 0.02),
'{} not close to {}'.format(relevance, expected_relevance)) '{} not close to {}'.format(relevance, expected_relevance))
assert_equal(metadata['precision'], expected['precision']) assert_equal(metadata['precision'], expected['precision'])