原文发表于:天池-第三届Apache Flink极客挑战赛第2名方案和代码
欢迎关注微信公众号:YueTan
背景
参赛动机:
- 不喜欢996拿着955极低的工资,突然发现自己的时间变成了每天刷剧,心有愧疚。
- 想了解大数据,Flink作为当红的实时计算引擎,比赛还有官方大佬帮忙解答问题,是很难得的学习机会。
结果:
- 拿到第2超出预期。工程加算法赛,其实每个人都是在工程能力的枷锁下进行探索,我属于枷锁极重的那个,只能在极小范围里辗转腾挪优化,运气流选手。
- 注:文章发表时还没有答辩,最终成绩也没确定。之前写过答辩的攻略,我对答辩虽擅长却越发无感,这种态度就容易降名次,甚至答辩前就公开了这篇文章。标题说自己是第2的方案,万一答辩完后只有第5不要觉得我沽名钓誉了。真正好的方案是接受时间检验的,为了创新而创新是不对的,为了让自己显得创新而硬说自己创新是更不对的。平心而论,我觉得此次的方案平平无奇,若要找出什么出彩的地方,我比较喜欢数据增强那一环节。
任务背景:
- 部分商家通过刻意点击热门和自家东西来让推荐系统误以为二者是高度相关,从而蹭到了热点。感兴趣可以搜索co-visit attck of recommentation system,很多论文还介绍了其他攻击方法,挺有意思。
框架
整体涉及到的框架较多,参赛完让我独立开发还是做不到,但至少有个模糊的概念。本次使用的组件主要有:flink AI flow,occlum,cluster serving,kafka等,下面是我画的一个结构图:
数据
很多特征和模型的改进,需要匹配以相应的工程改进。但是数据处理,是可以直接提现的,所以我做了一些样本选择、数据增强的工作。在那之前,我可以说一下我对业务的理解。我的设想是某些用户其实才是检测的重点,因为像我一样天资愚钝,根本想不到这种抱大腿的攻击方法。为了让系统推荐自家商品,能想到连续点击热门商品和自家商品的人,了不得。所以一开始,我就把重点放在了用户特征上。
初赛线上有100万训练数据、10万测试数据,可以下载的有50万训练数据和5万测试数据。作为一个分类任务,首先查看其类别分布:
- 50万训练集:负样本450000,正样本50000
- 5万测试集:负样本45000,正样本5000
证明测试集是经过精确采样的,所以正负样本比例完全一致。然后就是查看ID类,物品ID分布如下图。可知,大多数测试集都是新的item。
用户ID分布如下图,大多数测试集中也都是新的测试集。同时,业务中其实对用户ID可以建立黑名单和白名单制,因此针对user ID可以有更多的操作。建立特征时,也可以考虑id的历史成绩,毕竟一些ID可能都是种子选手了。
ID的时间关系。去掉visit time为负数的训练样本后,可知大多数时间都在1-10万左右,最大时间409599,总样本50万,可知很多样本是同一时间的。
而测试集时间,大多都在90万以上,证明中间还是间隔了不少时间的。最小时间:114054 最大时间:950485。因此可以部分得出结论:测试集几乎都是新的样本与物品,在一段新的时间,对模型泛化能力要求较高。
同时初赛提供了75个匿名特征,复赛152。其中前m个是商品特征,后面的是用户特征。所以如何确定这个m呢?根据其独特个数来判断即可,如下代码所示。同时可以看出即使是同为商品特征,也可以分为大概两组。一组的nunique大概是20左右,另一组大概是70左右。大概可以想象提供的数据大概是embedding数据和count。nunique大概就是类别个数。在embedding中,同一个类别还是对应着同一个embedding数据,其中embedding维度就是70对应的维度个数,肉眼可见大概embed_size是15,而类别个数则是70。同理,另一组对应的embed_size也是15,类别个数则是20。
而对测试集而言,同样可知embed_size当然是没有变的15,而类别则不同。测试集中一个类别数量为50,一个为8。至于这50和8与训练集是子集或非集,需要向数据挖掘中的frenquency encoding一样,把训练集和测试集合在一起再计算一次。
同时,后半部分为用户特征,同理可以画出用户特征的nunique。
比较奇怪的地方出现了,在测试集中用户的类别比训练集中还要多。
因此首先区分用户特征和商品特征。毕竟感觉赛题方提供的是半匿名数据,告诉了笼统,但是如何进一步区分则需要对数据进一步深挖才可以。这道题目既然给了user特征和item特征,可以参考的方法就有点击率预估、文本匹配等大方向。点击率预估中最重要的特征可以有类别count特征、目标编码特征和embedding特征。
我觉得自己做的比较有意思的部分就是数据增强了。主要借鉴了推荐系统和对比学习中,对正样本和负样本的重视,尝试了一些操作。
模型
模型比较简单,我最终用的就是常规的双塔模型。虽然也尝试了各种优化,但还是最开始的简单模型效果最好。详情可以参考我的十月比赛流水,里面详细记录了我每天的想法和操作,应当是这些特征本身已经比较强。
我的第一部分优化是细节优化。增加交互特征F1确实提分了,但是导致延时多了不少,因此得不偿失。SE没起作用,反而是加个BatchNorm和Dropout好用的不得了。
第二部分优化是增加多任务,自编码任务优化。自编码部分使用100万数据,分类部分使用10万数据。本以为这个AE-DNN可以有所作为的,但其实没啥效果。
训练细节和上分路径如下。分层学习率,label smoothing都是起作用的。
结论部分,当然是自夸一波,自己人就不多说了。
开源代码
开源代码地址:https://github.com/LongxingTan/Data-competitions/tree/master/tianchi-flink-aaig
谢谢关注,我是YueTan。