完整记录ijcai2016参赛过程

最近刚刚完成了毕业论文,闲着也是闲着,做个比赛找回点学习的感觉,对比了几个比赛,感觉ijcai2016这个比较对胃口。想想马上要毕业了,大概,这是毕业前参加的最后一个比赛了,不追求取得多好的名次,完全是探索性地做一下,把自己的一些思考记录在这里,算是留作纪念吧。

1. 赛题理解

简单来说,整个比赛的任务就是,给定2015/07/01~2015/11/30期间用户分别在线上的交互行为和线下实体店的购买行为,来预测2015年12月份指定用户在指定地点可能购买的商家,同时线下实体店商家的预算做了限制。

全部的数据包含4个表。表1是用户在线上的点击购买行为,包含[user_id, seller_id, item_id, category_id, action_id, time]6个字段。表2是用户在线下的消费信息,包含[user_id, merchant_id, location_id, time]4个字段,表3是线下商家的location信息以及budget限制,包含[merchant_id, budget, location_id_list]3个字段,表4是需要预测的[user, location] pair。

评价指标则是,基于微平均F1值的变种(主要是强调了budget的限制)。

upload/venn1.png_3b95e1c83a1786146cf30dec93df44f1

首先看线上和线下的数据之间的联系,线上用户数为963923,而线下的用户数为645375(其中训练集230496和测试集465366,二者的交集为50487),线上用户数据和线下总的用户的交集为509098。具体的韦恩图如上图所示(需要注意的是,这个图是自动生成的,由于需要借助面积来表示数据量大小,koubeitrain 与koubeitest的交集50487人中仍有(50487-40853)不在taobao数据中,这部分在图中没有表示出来),这意味着:

  1. 现在要对46万用户进行线下消费预测,但是约1/5(89347/465366)的用户既没有过线上消费记录,也没有线下的消费记录。这一点需要在设计模型的时候格外考虑。

  2. 待预测的用户中只有约1/10(40853/465366)的用户是拥有线下消费历史数据的,相对来说,这部分用户更容易预测一些。剩下的7/10(325532/465366)用户拥有线上的数据。

2. 数据分析

先来对数据做一些简单的分析,以加深对整个数据集的感性认识。

2.1 线上数据分析

首先是线上数据的流量图: upload/.png_e0b9e9cb5f5f7da672e866fde8a98585

其中,11/01~11/20的数据缺失,赛题的数据说明里提到,主要是为了避免双十一数据带来的干扰,除了周期性比较明显这点之外,没有太多信息量。

再看看线上商品种类的分布,总共有72个类: upload/category.png_f4bb3e09529983acdc9c5b5d89b4d06e

其中,类别1的数据稍微有点异常,其它类别分布比较均衡,我猜是衣服类别,哈哈~

另外就是,线上卖家的流量直方图: upload/seller.png_1625d44888eaa04f4e0a2de3720e5dcf

其长尾比较明显,大多数卖家5个月内的流量在5000以内。

线上数据分析先不做进一步深入,主要是还没有理清如何利用这部分信息。我们知道,线上数据与线下数据唯一的交集就是用户重叠。下一步分析的重点可能放在:

  1. 用户线上的消费习惯以及消费能力对线下消费有多大影响?(也就是那1/10的待预测用户)

  2. 线上消费行为相似的用户,在线下消费过程中是否也有指导意义?(用户迁移学习,也就是那7/10的用户)

2.2 线下数据分析

首先看一下线下的流量图: upload/liuliang2.png_7e53265f6dafa40ffba0cc37edbc47e3

可以看到,koubei数据几乎是爆发式增长。不过有点奇怪的是,11/01附近,流量出现了一个明显的下跌,我猜要么是那段时间没怎么发优惠券了,要么是商家有所调整。11月份开始,周期性变得更明显。然后我们按月看下流量的柱状图:

upload/liuliang3.png_6beb75faa0df56292b401a00b68dd6d0

保守估计,12月的累积流量应该增长到75000。因为,我清楚滴记得去年双十二线下的火爆场面,增长量应该比11月相对10月的增长量要更大。

3 解决方案

在对数据有了初步的认识后,如何解决这个问题呢?

初步来看,相比传统的推荐问题,这个问题复杂的地方在于,数据的缺失以及背景信息的丰富(这里指的是线上数据)。

我们不妨先把这个问题一点点简化,然后将其对应到熟悉的问题上去解决,在解决的过程中慢慢比较异同点并优化解决方案。

首先,我们把线上的数据先放一边。尽管,线上的数据量很大,但是线上的数据和线下数据之间的联系并不是特别强(直觉而已。。。),线上的卖家和线下的卖家是相互独立的,有交集的只是用户。那么现在手上只有7/01~11/30期间的线下用户消费数据,然后需要预测12月份用户在指定地点可能消费的商家。这样,12月份的用户又可以分为两部分,其中5万用户有历史消费记录,41万用户没有消费记录。显然,对于没有消费记录的用户,我们在对其做推荐的时候,可以把他当做是anonymous用户,这样,对该用户的推荐行为将只依赖于指定地点的商家(这里还有一个budget的问题,暂且不考虑)。对于有消费记录的5万用户,则需要结合其历史记录来综合推荐。

需要明确的一点是,对于anonymous用户而言,我们能唯一确定的是,其在指定地点一定发生了消费行为。因此,我们可以给每个用户推荐该地区最受欢迎的merchant。更细一点,这里有几点需要考虑的,一是给每个用户推荐多少个merchant,赛题要求不多于10个,实际上,这里我们可以简单的使用均值来确定给anonymous用户的推荐个数,该均值还未统计,不过可以预计是肯定不是一个整数,取其临近的整数即可。另外一个问题是,某一地区里,anonymous用户可能会很多,这导致该地区的热门merchant所发出的优惠超过了budget上限,因而涉及到一个用户筛选的问题。然而,在没有背景信息的情况下,只能采取随机筛选,不过借助线上的用户数据,可以简单的根据用户的购买力和活跃度作为排序标准。

对于有历史数据的用户,我们可以考虑:

  1. 用户是否在该区域消费过?如果是,优先推荐其消费过的merchant,如果没有,那么优先推荐与其消费喜好相似的店
  2. 超出merchant的budget了怎么办?由于有历史数据的用户是优质用户,所以理论上应该优先考虑,然后再考虑anonymous的用户。

4 训练集和测试集的划分

为了方便本地验证,需要从训练集里划分出本地的训练集和测试集(为了方便,以下分别称为trainset 和testset)。由于7月份的数据量不是很大,因此我们可以简单地将7~10月份的数据作为train-set,11月份的数据作为test-set。为了确认这样的划分相对于线上的测试集没有特别大的偏差,需要对本地的train-set和test-set中的用户交集情况以及与线上数据的交集情况做一个对比。

upload/venn2.png_f40c90d048ecb9bfe8d8ede3bf7e2d30

对比本地的train-set和test-set用户分布相比线上的训练集测试集来看,可以分析出以下几点:

  1. 11月份的时候,还有6万多的用户有历史数据,12月的时候就只有4万多了,说明用户流失有点严重;
  2. 12月份的时候,线上用户大量涌向线下。从6万增长到了32万。

另外,还统计了下面两条信息: 11月份的新用户中转化到12月份购买用户的数量: 17733; 7~10月份的老用户中转化到12月份购买用户的数量: 32754。 这里面的关系有点乱,暂时理不清了。。。

接下来,需要用实际的模型来检验这种划分的效果。

5 实验

5.1 如何衡量merchant的影响力

先不考虑线上的用户记录和线下的budget限制来思考这个问题。

已有数据:

  • train_set:7~10月份的用户线下购买记录,以及11月份用户实际购买的记录。

  • test_set:7~11月份的用户线下购买记录,需要预测12月份用户对 实际购买行为(加上约束)。

分两步走,首先是新用户的预测,其次是老顾客的预测。

新用户的预测在这里相对简单点,只需要考虑某一地区merchant信息。从先验的角度来讲,应该给每个用户推荐该地区最热门的merchant。那么哪些特征会影响merchant的热门程度呢?

  • 该merchant的历史用户量,当月用户量(这个应该算作弊吧。。。),用户购买频次,分店数量,日活,月活,增量,回头客等等(想到更多的了再补充)
  • 新店/老店,budget数量,
  • 该地区平均消费能力
  • 整体排名
  • 第一次到该地区的用户都选择了哪些店?

对于老顾客,为了简化问题,我们也将其看作是前一个问题的强化。对于有历史记录的用户,如果该用户曾经在指定location有过购买行为,先直接推荐,对于没有来过该地方的用户,我们将其退化成anonymous用户。

最后,我们需要结合budget做一些限定,这个需要结合具体的数据来确定。这样我们就得到了一个该解决问题的初步方案。先试试效果看~

这两天没有做太多的深入工作,一些基本问题的思考倒是对这个赛题有了一些新的认识。接着上面的实验说,当时抽取好特征之后,想的是衡量一个商店的热门程度。然而,抽完特征我才发现,之前都是理所当然地当做分类问题在思考,然而实际上,我们只有正样本的数据(用户发生了购买),却没有明显的负样本数据。唯一可以用来当做负样本的隐式数据是用户没有发生购买的区域内的店家。然而,我们抽取的特征是围绕商家来的,这样必然导致每一个商家既是正样本,也是负样本(当然,正负比例不同,与热门程度相关)。可不可以继续分类呢?也不是不行,但是总觉得不太合理。换个角度去想,不妨把这个问题看做是回归问题,我需要结合商家的历史数据去预测下个月该商家实际购买量(购买量直接反应商家的热门程度),这样就显得更合理了。这部分还没开始做,还需要结合budget的限制去处理(有点麻烦)。

说说另外一点,前面提到用线下11月的本地训练结果来模拟线上的分类结果,如何评估这种拟合是可行的呢?我先做了一个最简单的验证。从前面两个韦恩图可以看到,有部分用户是重复购买的用户,那么我只预测该部分用户,线上得到的f1-score 是0.16,那么线下用同样策略得到的是多少呢?0.453!具体的数据如下:

n_hit: 68403
n_predicts: 94009
n_hit_budget: 57818
precision: 0.727621823442
precision_with_budget: 0.615026220894
n_real: 195481
n_real_budget: 161186
recall: 0.349921475744
recall_with_budget: 0.358703609495
f1: 0.472575909358
f1_with_budget 0.453128000157

上面数据中的后缀withbudget表示考虑了budget限制后得到的结果。可以看到budget对准确率是降低的作用,对召回率有提升的作用,二者综合后,对f1的影响不大(显然,该结论的进一步推广有待验证)。

我想说的是,线下的预测和线上的预测之所以差别很大,原因是线下的重复购买用户所占比例接近1/2而线上数据的占比只有约1/10,所以相差很远。这也说明,这种用线下去拟合线上的方法不太靠谱。需要想想其它方法来训练模型。马上要去实习了,感觉花在这上面的时间不太多了呀。。。

=====update=====

最近没有做进一步深入分析,沿着上周的思路说点。前面提到,对于新用户,我们默认把他当做anonymous用户,那么最后会在哪些商店发生购买行为可以看做是有先验概率的随机分配问题。我们先做一些简单分析,n个用户和m个商家,由于m比较大(5k左右),而用户的平均购买只有1点几,这样显然命中率可以忽略不计。但是,我们面对的是一个有约束的问题,通过地点条件的约束,我们可以大大降低每个用户可选的商家数,然后,假设我们知道下个月每个商家实际购买量,那么,可以根据商家的销量排名,给每个用户按照先验比例随机推荐(或者全部推荐top商家,后面的实验部分实际上只取了top1商家),然而,实际上,我们并没有商家在12月的销量信息,不过,我们可以近似的使用商家上个月的销量信息。为了进一步降低可选商家的数量,统计发现商家销量在100次以上的商家约700个,占了全网总销量的87%,所以,不妨把商家范围缩小到这部分。按照这个思路,在线下测试11月份的数据 如下:

n_hit: 35998
n_predicts: 80529
n_hit_budget: 28815
precision: 0.447019086292
precision_with_budget: 0.357821405953
n_real: 195481
n_real_budget: 161186
recall: 0.184150889345
recall_with_budget: 0.178768627548
f1: 0.260845621535
f1_with_budget 0.238421281261

前面提到,线上和线下会有比较大的不同,不过这里仍然跑了下线下数据,是为了看budget对结果的影响是不是特别大。线下的数据显示,对准确率的影响稍微有点大。然后我在线上提交了同样方法得到的结果,f1-score为0.156。由于有交互和没有交互部分的数据是不重叠的,然后我把两部分数据融合在一起提交了下,f1-score为0.223。相比两部分单独提交都有所上升。感觉主要是因为召回率提高了。

稍微总结下,前面的分析,更多的都是对数据的一些感性认识,通过各种约束、估计、限制,得到了一点简单的结果,实际上,如何完整地构建一个模型来解决这个问题还没开始。晚上再好好思考下这个问题。