最近做的安卓日志告一段落,因此有了一些空闲时间,趁机回顾一下在上家公司做的一些有趣的项目,总结一下~

1.背景

上家公司是一个很大的O2O公司(国内最大吧),我在其一个事业部的数据组负责爬虫工作,爬虫稳定的时候我也会做一些其他项目。我们所做的这个行业目前竞争依然很激烈,基本是前两家分了70%份额,3、4两家紧追其后的局面,并且3、4家都实力不凡。做O2O就会有线下团队,他们主要负责谈商家拉客户做宣传,是公司一线最重要的战斗力。我们把全国划分成城市,每个城市划分成了更小的蜂窝;蜂窝是最小的管理单元,交由线下兄弟管理;其工作经费的发放需要根据其管理区域的情况来定,其工资和奖金则是根据业绩来定,也就是订单数;但是,对于不同的蜂窝,绩效规则可能不同,比如,当公司大力发展白领业务的时候,就会对在写字楼等白领消费的订单,补贴和奖励力度加大;而判断订单属于白领消费的方法,是看订单在哪个蜂窝产生,然后我们人工确定一下这个蜂窝的性质,作为这个订单的性质,比如,一个包含了清华大学的蜂窝,被人工标记为“校园”,那么在这个蜂窝产生的订单,自然不是白领性质。蜂窝的标记之前交由线下团队自己来做,但是这种绩效评判方法实施后,他们就有了将蜂窝性质故意标记错误的动机,以获得更多的补贴和奖金。针对这个问题,大佬们做了一些讨论,最后决定,订单性质由我们总部数据组来计算,替代之前通过蜂窝关联的方法。当时我负责的爬虫刚稳定下来,就接下了这个项目。

2.场景

输入:做这个项目的时候,我们一天的订单数大约220万,现在已经到了300万以上了。当时用户的画像还没有,可用的订单属性就两个,

latitude & longitude;   // 用户下单时的经纬度
address;                // 用户自己填的配送地址

输出:第一阶段的任务是要统计出每天蜂窝级别各类性质的订单数量,性质一共有4种---白领、校园、住宅、其他;然后交由一个页面来展示。

3. 调研

直观来看,这件事情就需要从地理信息来入手,后来这个事情也确实这么做的。订单可用的属性太少,但是可以把订单放入地图中,关联上地图数据,再从中找一些线索。调研后,发现确实可行。

3.1 地图POI

无论是高德、百度、还是腾讯地图,POI(Point of Interest)都是其核心数据。下图中浮在地图只上的那些 “文字+小标记” 就是POI,例如其中的“同德公园”、“山西大厦”、“洪荫小区”等。从POI的图标可以看到,不同性质的POI有不同的分类,例如“西城苑”和“洪荫小区”都是小区,所以是相同的图标,而“同德公园”是公园,则是另一种图标。从此可以得知,百度地图的POI是有一个自己的类别属性的,高德、腾讯都是如此。那么,思路就来了。我可以把订单关联到POI,然后利用地图POI自带的属性,来判断订单的性质。

3.1.1 获得高德地图poi

最终我选择了高德地图来做这件事,因为我们自己的app就是用的高德。首先,第一步目标我定为:获得所有需要的高德地图poi。高德地图提供在线服务,可以通过http的方式来请求到某一个点附近的k个POI信息(k大约是10或20)。我每天需要处理200万以上的订单,如果在处理每个订单时再临时调用http服务,会有严重的效率问题。所以我要把高德地图的数据搬到本地,在本地做索引,提供服务。

初期的目标,是要把我们自己蜂窝中的地图POI,全部获得。每个蜂窝有明确的多边形边界,全国一共有大约3000个蜂窝。我在这3000多个蜂窝中均匀地、按照相邻500米的密度,全都打上点。大约会产生50w个经纬度点;再将这50万个点调用高德服务(POI搜索->周边搜索,一个典型url是 [todo]),得到每个点附近的POI,调用50万次后,大约会产生1000万的poi数据;然后根据poi的自带id去重,最终我得到了200万左右的POI数据。一个POI的部分内容如下,可以看到,“type”字段标明了该POI的分类,是“餐饮服务;中餐厅;海鲜酒楼”。

{"id": "B0FFG93MUO","tag": "白汤河豚,阿拉斯加帝王蟹,象拔蚌,刺身龙虾,刺身澳洲鲍鱼,苏眉,东星斑,海参,基围虾,鲍鱼","name": "东海海鲜会馆","type": "餐饮服务;中餐厅;海鲜酒楼","typecode": "050119","biz_type": "diner","address": "贵宾楼饭店一楼西侧(北京饭店北京贵宾楼饭店欧美同学会)","location": "116.406960,39.908630","tel": "010-64810079","pcode": "110000","pname": "北京市","citycode": "010","cityname": "北京市","adcode": "110101","adname": "东城区","gridcode": "5916639201","distance": "160","business_area": "东单"}

3.1.2 高德地图poi的分类

统计一下这200万高德POI的type字段,大约有不到100个值,典型的值包括“写字楼”、“住宅小区”、“医院”、“大学”、“风景名胜”等。和需求方一起,我们把这100个type到订单4种性质的映射关系确定了下来,典型的映射例如,“大学”对“校园”、“中学”对“校园”、“医院”对“其他”等。

3.1.3 订单和POI关联

将地图POI搬到了本地之后,下面要将订单和POI做关联,以利用POI的分类。关联基于两种假设:1. 离订单距离越近的POI,越可能关联上,2. POI的地址和订单地址越相似,越可能关联上。所以,订单和POI的关联步骤如下:

(1) 输入订单经纬度,找到离订单最近的50个POI,作为候选集合(2) 分别计算订单和候选集合中每个POI的距离(3) 分别计算订单和候选集合中每个POI的地址相似度(4) 综合2,4步骤,选出得分最高的POI(5) 按照3.1.2中的映射关系,查找该POI类型对应的订单性质,即为最终结果

步骤(1)是一个二维K近邻的计算,先对所有POI进行索引,可以使用R树、KD树、4叉树等,这个项目中我使用了R树索引。对200wPOI建立索引后,进行100w次查找,耗时在5分钟以内,完全可以接受。步骤(2)则是两个经纬度点计算测地距离,这个计算方法可以参考 http://www.cnblogs.com/ycsfwhh/archive/2010/12/20/1911232.html。步骤(3)是计算两个字符串的相似度,这里使用了字符串的编辑距离来度量。

这样分类后,发现准确率还是不高,因为经纬度坐标本来就有误差,而且地址也不规范;会产生一些明显的错误,比如一个订单地址是“XXX第4教学楼”,经过距离和地址的加权,可能会和“XXX电影院”匹配上,而错过了正确的POI“XXX中学”。为更大程度避免这种情况,我增加了两种映射关系,来对匹配进行约束:

(1) 订单地址对POI类型的约束
(2) POI类型对订单地址的约束

约束(1)举个例子说明,假如有一个订单地址是“XXXXX公寓”,那么很显然,这个订单对应的POI只有几种可能----住宅小区、学生公寓、职工公寓等,其他类型比如“电影院”、“风景区”是完全不可能的;所以,利用这个约束条件,可以把候选的50个POI,排除掉一部分。约束(2)同样举一个例子,假如有一个POI的类型是“电影院”,那么其关联上的订单地址,一定会是类如“XXX电影”,“XXX影院”等,“影”关键字基本跑不掉,如果不是,那么这个订单和POI的关联关系很可能是错的;再利用这个条件,同样可以排除掉候选50个POI中的一部分。经过这样正反约束,50个候选POI基本上都会降到20个左右,正确率有提高。这两个约束关系大约各有20条规则,都是反复测试总结而来的。

经过这样来做,订单性质的正确率可以到75%左右,也就是说,大约4个订单,会有1个分类错误。这个比例当然不能忍,第一期目标是90%,那么继续。

3.2 地图带区域的POI

在使用百度地图搜索“清华大学”,会看到有清晰的学校边界,如下图。

那么,如果一个订单按照经纬度,落在了这个边界内,那就肯定是属于清华大学了,从而判定为“校园”性质,准确度很高。因此,我可以把地图所有带有区域的POI拿下来,来做订单性质识别。最终我选择了腾讯地图来做这件事,因为高德地图没有找到可用接口,而百度地图的经纬度体系和高德有差异,需要换算。具体的步骤如下:

(1) 将拿到的高德200w的Poi名称,在腾讯地图接口上请求区域信息(2) 返回的结果中,含有区域信息的,提取出来,作为高德POI的增加属性

经过对所有POI区域的抓取,最终有区域的数量在10w左右,大部分是校园和住宅小区,这是一个非常有用的数据。具体的接口和数据格式,现在我看了一下已经更改了,有时间可以再分析一下。

测试:拿几天的订单(大约一共1000万订单),往这10w区域里面落;可以落到范围内的有250万左右,抽取大约5000来做人工标记,正确率在95%左右。事实证明这是一个非常好的办法,解决了4分之一的订单,并且准确率奇高。但是,结合3.2和3.1,整体的准确率仍然到不了90%,所以继续。

3.3 人工关键词

在前面不停地测试->人工标注->测试->人工标注过程中,对数据质量和方法有了一些把握。人工判断时,基本是通过地址中的关键字眼来做,比如“XXXX中学”,就判断为校园订单,“XXX大厦”,就很有可能是白领订单。自然而然地,我想到用关键词的方法来做。这种方法一开始没有想到,是因为它完全抛弃了经纬度信息。

关键字的方法很简单,就是直接判断订单地址中是否包含关键字,包含则直接根据关键字性质来确定订单的性质。比如“北京大学”中包含“大学”关键字,则直接判定为校园订单,“同济医院”中包含“医院”关键字,则直接判定为“其他”类型订单。但是,有一个先后顺序在其中,例如“北京大学附属医院”既包括“大学”关键字又包括“医院”关键字,那么就取最后的一个,即“医院”作为最终关键字,因为越靠后越接近地址的最终含义。关键词库的创建完全是通过我人工来做,我标记了上万的订单数据后,总结出来大约50个关键词,作为一个宝贵的人工关键词库。

测试:拿1000万订单,用关键词进行分类,可以分类的大约有50%;抽取5000个分类结果人工判定,准确率在95%以上。这是一种最有效的分类方法,也最简单。现在,利用关键词->落POI区域->POI匹配,这个分类流程,经过测试,分类覆盖率有99%,准确率达到了91%左右。目标达成。

3.4 自动关键词

虽然达成了90%的目标,但是还有相当一批订单分类错误,这类订单的地址都不太标准,但是大多数会包含一些楼宇或者小区信息,例如“望京SOHO”、“南湖西园”之类,这类具体的楼宇和小区名称,很难用普遍的方法识别出来,我只能通过词库来做,但是数量又太大,所以,我考虑利用200w的地图poi来自动产生一批关键词。好在这200w地图POI都已经标记上了对应的订单性质,因此,我只要关注怎样提取关键词就可以了。最终,我提取出“白领”、“住宅”这两类自动词库,包含关键词大约50万,基本包含了绝大部分小区名称和相当多的楼宇名称。提取的方式比较简单原始,因为POI对应的地址比较标准,因此可以提取出小区对应的子串,例如,“北京市朝阳区世安家园小区”,直接可以提取出“世安家园小区”,然后把小区关键词去掉,则得到了“世安家园”关键词;楼宇的方法于此相同。

测试:和人工关键词相比,这自动词库关键词质量很一般,因此只能用来做最后的补充;利用这50万自动关键词,对前面分类失败的10%进行分类,可以正确分出五分之一左右,从而将整体的分类准确度提高到了92%~93%,并且每天的计算时间在30分钟以内,达到了第一阶段的要求。

4. 实现

4.1 最终算法

最终的算法流程如4.1所示,需要补充的是。这部分都使用Java来处理,数据库用Mysql;分类结果,被推到HDFS上,用Hive来做后续的ETL。

4.2 子项目和依赖

参考4.1中流程图,整个项目有以下几个子项目

(1) 地图POI抓取项目
(2) 地图POI区域抓取项目
(3) 自动关键词项目
(4) 订单分类主流程项目

第(1)个项目第一次需要全量抓取,后面需要增量维护,每天根据蜂窝区域的变化,来增加地图POI;第(2)个项目与此类似;第(1)和第(2)个项目数据的更新会触发第(3)个项目更新;第(4)个是主项目,每日计算一次。

4.3 测试

流程开发完成后,和PM一起测试,测试基本集中在分类正确率上,两个人每次抽取1000条分类结果进行检查,重复大约有20次左右后,准确率一直稳定在92%,可以上线了。

5. 总结

这个项目比较有意思,主要是使用很土的办法达成了目标,比较爽。研发只有我一个,另外有个PM和我一起讨论和测试;前期数据准备和调研花了3周左右,开发加上线3周左右,一共一个半月时间。后来,来了一个实习生,我和他一起商量了第二阶段的改进办法,准备使用机器学习来处理剩下那一部分相当困难的订单(主要是要从地址模式入手);可是一直有其他的项目在前,就一直没有做。

转载于:https://www.cnblogs.com/sparrowjack/p/5132291.html

【项目总结】订单性质识别相关推荐

  1. 【人工智能项目】MNIST手写体识别实验及分析

    [人工智能项目]MNIST数据集实验报告 这是之前接的小作业,现在分享出来,给大家以学习!!! [人工智能项目]MNIST手写体识别实验及分析 1.实验内容简述 1.1 实验环境 本实验采用的软硬件实 ...

  2. 项目经历 - 卷积网络识别古日文

    学校做的小项目: 卷积网络识别古日文 Kuzushiji-MNIST数据集(此数据集专注于草书日语)下载 古日文中很重要的一个特征并且不同于现代日语的一点就是古日语含有变体假名(Hentaigana) ...

  3. OpenCV实践小项目(一): 信用卡数字识别

    1. 写在前面 今天整理一个OpenCV实践的小项目, 前几天整理了一篇OpenCV处理图像的知识笔记,后面,就通过一些小项目把这些知识运用到实践中去,一个是加深理解,另一个是融会贯通,连成整体,因为 ...

  4. 【人工智能项目】Fashion Mnist识别实验

    [人工智能项目]Fashion Mnist识别实验 本次主要通过四个方法对fashion mnist进行识别实验,主要为词袋模型.hog特征.mlp多层感知器和cnn卷积神经网络.那么话不多说,走起来 ...

  5. 项目总结:人脸识别签到系统

    人脸识别签到系统项目总结 第一部分:项目简介 实验室人脸识别签到系统 第二部分:项目系统架构设计 2.1业务架构 2.2 技术架构 基础设施:主要是GPU,基于CUDA的开发 学习框架:主要是Dlib ...

  6. 项目的开始 —— 第二步识别干系人

    昨天咱们给大家讲到了,项目的开始分为两步.第一步是制定项目章程,第二步就是识别干系人. 那么今天就给大家讲讲第二步:识别干系人. 那么第一个问题:什么是干系人?所谓干系人就是和你项目有关的人. 比如: ...

  7. 黑马瑞吉外卖项目之订单明细的查询,分页,派送功能

    黑马瑞吉外卖项目之订单明细的查询,分页,派送功能 /*** 后台管理订单信息分页查询* @param page* @param pageSize* @return*/@GetMapping(" ...

  8. SAP Spartacus 基于行项目的订单取消功能(order cancel)实现

    进入Order History页面: http://localhost:4200/electronics-spa/en/USD/my-account/order/00001075 点击 Cancel ...

  9. SSH实现进销存(ERP)项目之订单管理模块解析(附源码地址)

    项目清单: 1,struts2.hibernate.spring 2,前后台传值使用json 3,数据库使用了Oracle 4,对员工表及采购单表采用了后端分页 5,使用了时间控件 项目结构,MVC模 ...

  10. 深度学习项目:男女性别识别【附完整源码】

    性别分类对于人机交互应用和计算机辅助生理或心理分析等商业领域的许多应用至关重要,因为它包含有关男女特征差异的广泛信息. 本次案例收集了接近二十万的男女数据集图片. 文章目录 性别分类简介 使用 Pyt ...

最新文章

  1. R语言将多个dataframe导出到excel的多个表单(sheet)实战
  2. java(9)并发编程
  3. 强基计划有计算机专业的学校,强基计划有计算机专业吗?强基计划毕业学生国家怎么安排的?...
  4. Android 设置Activity透明
  5. std::future和std::promise和std::packaged_task
  6. Day20:绑定方法与非绑定办法、多态和多态性
  7. XML 语法速查笔记
  8. java线程创建过程_Java创建线程的细节分析
  9. 【重定向 return “redirect:/***“的作用 】
  10. CentOs 设置静态IP 方法[测试没问题]
  11. 洛谷——P1597 语句解析(两种解法)
  12. 基于python的交通_基于Python的交通流数据清洗
  13. linux 删除开机密码,6种清除开机密码方法,总有一个适合你
  14. AUTOCAD——多段线命令
  15. typecho添加html5视频播放器,DPlayer-Typecho视频播放插件
  16. 从思维走向实践,数字化转型 IT 经营的成功路径
  17. sigmoid函数及其导数
  18. Ngnix+Tomcat配置负载均衡
  19. 防雷接地国家规范标准介绍与施工技术要点
  20. Visual Studio Code(VSCode) 编辑/编译/调试 C++ 代码

热门文章

  1. 如何在linux下运行php脚本,如何通过Linux命令行使用和运行PHP脚本
  2. loadGrid layui
  3. 建模算法(五)——图与网络
  4. 自动化测试===unittest和requests接口测试案例,测试快递查询api(二)
  5. Sybase数据库故障的修复方法
  6. [转载]DevOps建立全生命周期管理
  7. mysql 常用函数总计
  8. dev gridcontrol 单选框效果
  9. C#面向过程之编译原理、变量、运算符
  10. 【相机标定系列】标定工具仓库