早上在公司楼下咖啡店点单,手机弹出‘附近3家评分4.8+的早餐铺’;下班路过地铁口,App自动推送隔壁写字楼刚上线的瑜伽体验课——这些不是巧合,是同城推荐算法在悄悄干活。而真正让它‘认得清人、找得准地、推得对味’的,靠的是扎实的数据处理功夫。
数据从哪来?不是随便抓一把就用
真实场景里,同城推荐的数据源很杂:用户GPS定位(带精度和时间戳)、商户经纬度+营业状态+品类标签、历史点击/收藏/到店打卡记录、甚至天气、节假日、早晚高峰时段。但原始数据常带着‘毛边’:比如定位漂移500米把朝阳大悦城标成通州某小区;又比如商户地址写‘西二旗地铁旁’,系统却没解析成坐标。这时候得先做清洗和标准化。
一个实用的小技巧:用高德或腾讯地图API批量地理编码(Geocoding),再加一层人工校验规则——比如同一商圈内商户坐标距离小于50米的,只保留主门店,其余合并。代码逻辑可以这样写:
def dedupe_nearby_shops(shops, radius_m=50):
clusters = []
for shop in shops:
found = False
for cluster in clusters:
if haversine_distance(shop['lat'], shop['lng'], cluster['center_lat'], cluster['center_lng']) < radius_m:
cluster['members'].append(shop)
cluster['center_lat'] = (cluster['center_lat'] + shop['lat']) / 2
cluster['center_lng'] = (cluster['center_lng'] + shop['lng']) / 2
found = True
break
if not found:
clusters.append({'center_lat': shop['lat'], 'center_lng': shop['lng'], 'members': [shop]})
return clusters用户行为不能只看‘点了什么’,要看‘为什么点’
小王上周六晚10点搜‘深夜食堂’,结果点了3公里外一家烧烤摊;但周三中午12:15他搜‘快餐’,选了公司楼下那家盖饭。表面都是‘搜索+点击’,背后意图天差地别。数据处理时得打上上下文标签:时间粒度切到小时级,结合POI类型(餐饮/健身/美甲)、用户实时位置与常驻地距离、是否在通勤路径上……这些特征组合起来,模型才分得清‘临时解馋’和‘日常刚需’。
冷启动不是等出来的,是‘借’出来的
新用户没行为?新商家没曝光?硬推容易翻车。我们试过用‘同城相似人群’迁移特征:比如海淀区新注册用户,先匹配近7天海淀活跃用户中性别、年龄、设备型号最接近的100人,取他们点击最多的前5类商户作为初始推荐池。数据处理脚本里,用Redis做实时相似度缓存,响应压到200ms以内。上线后新用户次日留存涨了23%。
同城推荐算法不是玄学,它长在真实数据的泥土里——坐标不准,推荐就跑偏;时间没对齐,行为就失真;标签太粗,模型就瞎猜。把数据当菜洗,把特征当料配,火候到了,推荐才自然得像老街坊给你指路。