stone

IJCAI-18 阿里妈妈搜索广告转化预测赛后总结
做题过程本赛题是阿里提供了相关的电商广告,要求对用户 pCVR 进行预测,其中初赛要求预测日常的预测转换率,复赛要...
扫描右侧二维码阅读全文
13
2018/06

IJCAI-18 阿里妈妈搜索广告转化预测赛后总结

做题过程

本赛题是阿里提供了相关的电商广告,要求对用户 pCVR 进行预测,其中初赛要求预测日常的预测转换率,复赛要求预测特殊节日的转换率(双十一等),初赛数据的数据量太比较正常,复赛的数据量达到了 11G,处理起来还是不太容易。最后初赛 173/5204,复赛 18/500,成绩也比较满意,但是做得比较常规,所以没有特别的亮点。

先看看问题,题目提供了 pCVR 的计算方式: pCVR=p(conversion=1|query,user,ad,context,shop)

评估指标为 log_loss

提供的基本特征,可以分为下面五大类,基础数据,用户基本信息,商品基本信息,商店基本信息,点击上下文信息。通过以上数据,从下面的几个方面进行特征构造:

  • 基本信息的整理: 如同一类别的商品个数,该类别的历史成交率等等方面
  • 各类特征交叉的历史成交率: 用户点击某类商品的历史成交率,点击某类别,某店铺等等历史成成交率
  • 时间特征:这类特征效果特别好,主要体现在用户点击事件之间的时间差,反映了用户浏览的频率,如果短时间内用户浏览的频率较高,说明其点击的可能性也较大,有个 trick,对与只出现一次的用户,可以直接用缺省值,要将其和 0 进行区分
  • 排序特征: 这类特征是看复赛答辩的时候看到的,自己是没想到,主要是某个商品在同类别商品中价格排名,浏览次数排名等等
  • 滑窗特征:这个我们用了,但是作用不大,每个用户的点击数据较少,大部分只有几条,滑窗分析的意义不大,应该会出现大量的零值

最后我们提取并选取了 154 个特征,之后是对于模型的选择:

  • GBDT+LR:通过 GBDT 模型进行自动的特征组合,下层接 lr 模型,初赛的初期使用其构造了 baseline,但是其 baseline 成绩较比以下几种模型差距较大,所以后期没有继续使用
  • FFM:通过模型对输入特征进行组合,在 FM 的基础山增加了 field 的概念,把相同性质的特征归于同一个 field 特征必须转换成“field_id:feat_id:value”格式,field_id 代表特征所属 field 的编号,feat_id 是特征编号,value 是特征的值。数值型的特征比较容易处理,只需分配单独的 field 编号,如用户评论得分、商品的历史 CTR/CVR 等。categorical 特征需要经过 One-Hot 编码成数值型,编码产生的所有特征同属于一个 field,初赛过程中使用了 FFM 模型进行预测,并用其结果和 lgb 模型的结果进行了融合,效果较比单模型有所提高。复赛由于数据量增大,FFM 模型需要先转换数据格式才能进行训练,每次加入新特征的都需要重新转化数据,效率比较低。所以复赛后期没有继续使用。
  • xgboost/ligthGBM:均是集成树模型,可以很好的处理连续特征,其中 lgb 也可以直接处理类别特征,免去人工进行 onehot 编码,训练速度快,方便使用的同时预测结果比较准确。xgboost/ligthGBM 在初赛中表现相当,但是在复赛数据量增大的情况下,lgb 的速度更快。

问题思考

下面是对于一些问题的思考:

1. 比赛用什么模型来做

对于分类问题,不要想太多,直接上 lgb,lgb 速度快,特征要求少,不用做 onehot,是快速构建模型的最佳选择,虽然 xgb 精度比 lgb 高了一点点,但是可以忽略不计。

2. 样本分布不平衡

这个问题应该是不需要考虑的,lgb 支持不平衡数据的自动平衡,但是这种平衡的结果反而会导致结果的下降。样本这种不平衡的分布也是一种信息。

3. 特征选择的方法

虽然一般来说,特征越多越好,但是实际上应该是特征的质量越高越好,不好的特征只会给最终结果造成不少的干扰。所以进行特征选择是很有必要的。特征选择的几个方法:filter,wraper,embedded,pca

filter 是利用特征和结果之间的关系对特征进行筛选,例如特征的方差,互信息,卡方检验,相关系数等等
wraper 是就是我们平时用的土方法,对一个模型进行多轮训练,每一轮训练,都会去掉特征重要程度最差的几个
embedded 通过一些模型进行特征的自动选择,如 LR 模型,GBDT 模型等方法。LR 模型中带有正则项,特别是 L1 正则,通过系数,可以对特征进行一定的选择

4. 模型融合的方法

模型融合中,主要用了两种方法,average,stacking。在这个题中,加权平均效果是最好的,也十分的简单。stacking 相对来说复杂一点,其特点是可以学习每个模型的优点,在不同范围的数据上选择不同的模型进行加权融合,网上资料比较少,这里放一个经典图:

这里做法是这样的,将训练数据分为 5 份,用其中四份作为训练数据,预测第五份,将结果作为一个特征,另外是训练数据,直接求预测值的平均值,然后利用这个新的特征,来进行最后的预测。

5. 训练数据的划分

数据的划分方式对结果影响还是很大的,这个问题要认真思考。有这样的一个问题,在线下,我用了 90%的数据作为训练数据,剩下的 10%做验证集,那提交线上的时候,要不要重新用 100%的数据来训练模型,其实是没有必要的,只要分布一直,数据足够,其实 90%的数据和 100%的数据训练出来的模型都差不多。

经验分享

下面是一些经验吧:

  1. 当看到题目的时候,先不要想太多,以最快速度构建一个可运行版本,建立一个自己的 baseline
  2. 善于分析问题,从中提取实体,围绕着业务和实体进行特征的构建,特征工程离不开对业务的理解
  3. 分析结果,学会判断欠拟合和过拟合
  4. 保留做题过程中的所有模型,特征,参数,有了这三个东西就可以复现比赛的结果,后面就可以有比较多的模型来做模型融合
  5. 用好 pickle,可以提高做题的速度

最后贴一些这次学到的 python 技巧,这个还是相当的实用的

# pickle的使用,可以用来保存一些中间数据,节省计算的时间
pickle.load(open(path, 'rb'))
pickle.dump(obj, open(path, 'wb'), protocol=protocol)
# 将一些数据打包保存
data=[model,feature,in]

# pandas shift函数, 计算一些划窗特征
t = data11.sort_values(['user_id','predict_category_property','context_timestamp'])
t['user_id_pre'] = t['user_id'].shift(1)
t['predict_category_property_pre'] = t['predict_category_property'].shift(1)
t['context_timestamp_pre'] = t['context_timestamp'].shift(1)
t['user_id_search_pre_view'] = t['context_timestamp']- t['context_timestamp_pre']
t.loc[((t['predict_category_property_pre']==t['predict_category_property'])&(t['user_id']==t['user_id_pre']))==False,'user_id_search_pre_view'] = -1

# pandas 的pivot_table,agg,sort,groupby,reset_index都是很不错的工具

# pandas 强大的query函数!!!可用sql语句,也就是说可以用in,这个超级方便的
train = data11.query("(context_day==7 and context_hour>=0 and context_hour<=11)")
b = train.groupby('item_category_list')['is_trade'].mean().reset_index()
b.columns = ['item_category_list','category_pcvr']

# lgb的early_stop机制
lgb_cv = lgb.LGBMClassifier(
            objective='binary',
            learning_rate=0.1,
            seed=2018,
            colsample_bytree=0.7,
            subsample=0.7,
        #     reg_alpha=0.001,
            n_jobs=16,
            n_estimators=20000)
lgb_model = lgb_cv.fit(x_train_temp, y_train, eval_set=[(x_cv_temp, y_cv)],
                           early_stopping_rounds=100,verbose=False)
predict = lgb_model.predict_proba(x_cv_temp)[:, 1]
score = log_loss(y_cv,predict)

https://github.com/plantsgo/ijcai-2018/blob/master/eda_solve.ipynb
上面是第一个名的 ppt,和参考代码。

Last modification:September 7th, 2018 at 08:19 pm
If you think my article is useful to you, please feel free to appreciate

Leave a Comment