/anti-12

Primary LanguagePython

安泰杯 —— 跨境电商智能算法大赛

竞赛题目

今天许多**互联网公司都在响应***主席一带一路的号召积极开拓海外市场。在我们开拓海外市场时往往会遭遇到用户习惯与国内不同造成国内的优秀策略难以在海外奏效等问题。即使成功开拓了某一国的市场,当需要进一步向更多国家扩张时,也会遇到不同国家的用户心智不统一的问题。

AliExpress是**最大出口B2C电商平台,2010 年平台成立至今已过 8 年,高速发展,日趋成熟。我们覆盖全球 230 个国家和地区,支持世界 18 种语言站点,22 个行业囊括日常消费类目,商品备受海外消费者欢迎;海外装机量超过 6亿,入围全球应用榜单 TOP 10;目前的主要交易市场为俄、美、西、巴、法等国。

对于AliExpress来说,目前某些国家的用户群体比较成熟。这些成熟国家的用户在AliExpress尽享买买买之乐的同时,为我们沉淀了大量的该国用户的行为数据。这些沉淀下来的用户数据被我们挖掘利用后形成我们的推荐算法,用来更好的服务于该国用户。

但是还有一些待成熟国家的用户在AliExpress上的行为比较稀疏,对于这些国家用户的推荐算法如果单纯不加区分的使用全网用户的行为数据,可能会忽略这些国家用户的一些独特的心智;而如果只使用这些国家的用户的行为数据,由于数据过于稀疏,不具备统计意义,会难以训练出正确的模型。于是怎样利用已成熟国家的稠密用户数据和待成熟国家的稀疏用户数据训练出对于待成熟国家用户的正确模型对于我们更好的服务待成熟国家用户具有非常重要的意义。

本次比赛给出若干日内来自成熟国家的部分用户的行为数据,以及来自待成熟国家的A部分用户的行为数据,以及待成熟国家的B部分用户的行为数据去除每个用户的最后一条购买数据,让参赛人预测B部分用户的最后一条行为数据。

思路: 由于用户和商品的组合数巨大,因此尝试预测任意商品和用户的组合在irank1发生的概率是不现实的。 我们的模型分两个阶段:

  1. 召回
  2. 排序 在召回阶段,我们通过基于规则、协同过滤、相似用户的行为、相似商品共现、用户最常购买的商店的热门商品,用户最后一条记录所在种类的热门商品,低价商品等多个方面,分别进行粗糙的预测,由每一路预测推出最有可能的top50。 然后,在第二阶段,将召回阶段的结果整理为(用户,商品)对的二元组的形式的样本,然后提取用户侧,商品侧,以及上下文信息的手工特征,把irank为1的用户商品对认为是正样本,其他的都认为是负样本,把问题转化为一个二分类问题,然后使用分类器进行求解。 最后再按预测得到的概率值重新排列组织结果,对每个用户推出top30的预测,如果有推荐量不够的情况,则使用用户最后一条记录所在当日的热门商品补全top30。

具体来说: 我们的召回分为以下几路(以yy国为例,zz国同):

  1. 我们受到协同过滤的启发,统计用户的相似性,以及商品的相似性,然后把和目标用户相似的用户所喜欢的商品的相似商品推送给目标用户,相当于是对usercf和itemcf的结合 由于我们发现同时使用xx国和yy国的数据统计相似性做协同过滤的与只用yy国数据做协同过滤相比会有不错的收益,所以我们在协同过滤的召回部分有 1.1 xx+yy->yy 1.2 yy->yy 1.3 yy+zz ->yy 2.目标用户最后一次行为记录当天的热门商品 3.目标用户最后一次行为的商店在当天的热门商品 4.目标用户最后一次行为的种类在当天的热门商品 5.目标用户最后一次行为的商店的热门商品 6.目标用户最后一次行为的种类的热门商品

7.用户最后一次行为所在种类的和最后一次行为的商品价格最接近的商品 8.用户最后一次行为所在商店的和最后一次行为的商品价格最接近的商品 9.用户最常行为的种类的和最后一次行为的商品价格最接近的商品 10.用户最常行为的商店的和最后一次行为的商品价格最接近的商品

11.用户最后一次购买的商品所在种类的和最后一次购买记录的商品价格最接近的价格的商品 12.用户最后一次购买的商品所在商店的和最后一次购买记录的商品价格最接近的价格的商品

13.用户最常购买的商品所在种类的和最后一次购买记录的商品价格最接近的价格的商品 14.用户最常购买的商品所在商店的和最后一次购买记录的商品价格最接近的价格的商品 15.用户购买过的商品按时间顺序逆序排列(我们发现大量的得分都来自这一路召回,其他路的召回只是对它做了很小的补充) 每一路召回都把最好的top50保留下来,由于实际上不同路的召回中有大量的重复,因此我们可以对这些用户样本对更确信它可能会被用户将来购买,因为它在多路召回中都出现并且排名靠前,它们互为一种排名信息上的补充。也同样因为多路召回中的重复很多,最后形成的样本数不会爆炸。 最终我们对yy国训练集召回了约2000万个样本,zz国的训练集召回了1800万个样本,测试集则只有600万左右的规模。

(对于某个样本 <用户,商品>)我们提取的特征包括: 1.该样本所对应的的(用户,商品)对在召回阶段各路召回中的排名或打分。如果没出现则为NaN 2.该用户活跃度 3.该商品价格与该用户对该商品种类的最后一次行为的差价 4.该商品的回头客数量(我们简单的定义 忽略同一天的多次购买,如果一个用户对该商品的购买行为量仍然大于1,则认为该用户是一个回头客,商品的回头客定义为该商品的回头用户数量) 5店铺的回头客(定义和上述相似) 6.商品所在种类的商品数 7.商品所在商店的商品数 8.商店被多少人喜欢 9.这个商品在这个商店的这个种类的销售占比 10.该种类商品的价格标准差 11.该店有多少该种类的商品 12.该店有多少种类 13.该种类有多大比例的商品在该店是存在的 14.该种类的商品在多少店有 15.上皮你被多少人购买过 16.和该用户的最后一次行为的差价 17.和该用户最后一次购买的差价 18.该商品是否和用户的最后一次行为记录为同一个种类 19.该商品是否和用户的最后一次购买记录为同一个种类 20.该商品是否和用户的最后一次行为记录为同一个店铺 21.该商品是否和用户的最后一次购买记录为同一个店铺 22.该商品与该用户对该种类查看过的最低价的差价 23.该商品和该用户对该商店查看过的最低价的差价 24.该商品和用户对该种类商品购买过得最低价的差价 25.该商品和用户对该商店商品购买过得最低价的差价 26.该商品和用户对该种类商品查看过的最高的差距 27.该商品和用户对该商店商品查看过的最高价的差距 28.该商品和用户对该种类商品买过的最高价的差距 29.该商品和用户对该商店商品买过的最高价的差距 30-35. 商品所在种类/商店在用户最后三天的行为/购买次数 36.该商品价格和用户最后一天行为/购买的平均价的差价

我们按用户随机切分为4分,做4折交叉验证,然后把四折的线下分数的平均分数当做线下的最终评价分数。在交叉验证的同时也对测试集数据做了4次预测,我们把这四次预测的平均概率作为最终的线上提交结果排序的依据。(可以理解为是为了让结果更鲁棒而对数据集做了扰动) 线下输出的评价结果为一个四元组(a,b,c,d),a表示在所有要求被预测的用户上计算的map得分,b表示排除掉没有做任何预测的用户后的map得分,c表示在所有要求被预测的用户上对召回到了正确答案的用户的百分比,d表示排除了没有做任何召回的用户后,对召回到了正确答案的用户的百分比。 最终,我们最优结果的线下得分为: yy国:0. 60236,召回为0.70973 zz国:0.58857,召回为0.70744 线上得分为:0.5999

一个小缺陷: 由于xgb在gpu_hist的tree_method模式下牺牲了一定的精度来换取运行速度,因此解有一定随机性,即使在完全同样的输入和随机数种子下,也不能得到完全相同的解。 因此,我们将使用线上最优的模型参数跑多次结果,取线下得分最高的一次认为是对线上结果的最好复现。 经过我的测试,一般跑15次(大约需要两到三小时)得到的最好结果能和线上的最优结果对应的线下得分在0.00005的范围内。

从最原始的数据集到切分为不同国家,清洗数据,多路召回,构造样本集,提取特征,训练模型,搜索参数,做出预测,再将二分类的概率结果重新整理为对每个用户的推荐排序。全过程大约需要15个小时左右。 完整的运行流程见源代码中的pipe.py文件。

附: 我们的运行环境如下: Windows64位机 i7,16G内存 6Ggpu 使用python3,并使用了如下的第三方包以及它们所依赖的包: Numpy Pandas Matplotlib Sklearn Xgboost

运行方法: 在工作目录下,将复赛数据放在同一文件夹下,然后python pipe.py 即可。

最终结果为to_submit.csv