前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >2020 KDD Cup:Debiasing phase4 baseline 0.25

2020 KDD Cup:Debiasing phase4 baseline 0.25

作者头像
Coggle数据科学
发布2020-05-06 23:32:00
6340
发布2020-05-06 23:32:00
举报
文章被收录于专栏:Coggle数据科学Coggle数据科学

写在前面

"该赛道的数据集强调电商推荐系统的公平性,尤其是流量较少的广大中小商家所面临的“有好货缺无人问津”的困境。数据横跨十余天,中间还穿插了某次全网促销活动,涵盖了一些商品从上新时无人问津、到逐渐成为高潜力爆款的历程。欲获胜的队伍需格外关注曝光不足的商品上的推荐准确度,需探索“如何抵消掉历史点击数据的选择性偏差以便避免只推爆款”、“如何注意数据分布随时间的变化以便及时发现高潜力冷门好货”、“如何利用多模态图文商品信息来辅助商品冷启动”等重要课题。"--解题关键

首先感谢青禹小生的开源,本文是在其基础上进行更多的细化, 也将对更多优化方向和建模思路进行简单介绍。

关联商品打分

代码语言:javascript
复制
def get_sim_item(df_, user_col, item_col, use_iif=False):

    df = df_.copy()
    user_item_ = df.groupby(user_col)[item_col].agg(list).reset_index()
    user_item_dict = dict(zip(user_item_[user_col], user_item_[item_col]))

    user_time_ = df.groupby(user_col)['time'].agg(list).reset_index() # 引入时间因素
    user_time_dict = dict(zip(user_time_[user_col], user_time_['time']))

    sim_item = {}  
    item_cnt = defaultdict(int)  # 商品被点击次数
    for user, items in tqdm(user_item_dict.items()):  
        for loc1, item in enumerate(items):  
            item_cnt[item] += 1  
            sim_item.setdefault(item, {})  
            for loc2, relate_item in enumerate(items):  
                if item == relate_item:  
                    continue  
                t1 = user_time_dict[user][loc1] # 点击时间提取
                t2 = user_time_dict[user][loc2]
                sim_item[item].setdefault(relate_item, 0)  
                if not use_iif:  
                    if loc1-loc2>0:
                        sim_item[item][relate_item] += 1 * 0.7 * (0.8**(loc1-loc2-1)) * (1 - (t1 - t2) * 10000) / math.log(1 + len(items)) # 逆向
                    else:
                        sim_item[item][relate_item] += 1 * 1.0 * (0.8**(loc2-loc1-1)) * (1 - (t2 - t1) * 10000) / math.log(1 + len(items)) # 正向
                else:  
                    sim_item[item][relate_item] += 1 / math.log(1 + len(items))

    sim_item_corr = sim_item.copy() # 引入AB的各种被点击次数  
    for i, related_items in tqdm(sim_item.items()):  
        for j, cij in related_items.items():  
            sim_item_corr[i][j] = cij / ((item_cnt[i] * item_cnt[j]) ** 0.2)

    return sim_item_corr, user_item_dict

这里在原有基础上考虑了两点因素,关联位置因素和关联时间因素。强关联的发生是有向的、有位置的和有时间的。

  • 比如我们先买了手机,那下一次买手机壳的关联,和先买手机壳再买手机的关联,这两种很明显,A到B大于B到A,这是有向性;
  • 我先买了手机,然后买了手机壳,又买了耳机,很明显,手机和手机壳的关联性大于手机与耳机的关联性,这是位置性;
  • 那么如果再加上时间这层因素,时间相隔越远的关联性肯定是不高的。

这三点因素就可以组成我们的优化思路,有向性打分*位置打分*时间打分,得到最终关联打分。

交互行为打分

代码语言:javascript
复制
def recommend(sim_item_corr, user_item_dict, user_id, top_k, item_num):

    rank = {}  
    interacted_items = user_item_dict[user_id] 
    interacted_items = interacted_items[::-1]
    for loc, i in enumerate(interacted_items):  
        for j, wij in sorted(sim_item_corr[i].items(), reverse=True)[0:top_k]:  
            if j not in interacted_items:  
                rank.setdefault(j, 0)  
                rank[j] += wij * (0.7**loc) 
     
     return sorted(rank.items(), key=lambda d: d[1], reverse=True)[:item_num]

这里的优化也很符合我们的主观认识,距离下次点击月近的行为,相关性越接近,所有可以根据位置远近考虑重要性,添加权重因子。当然还可以添加时间权重因子。

优化方向

切勿陷入思维定势,也许我的优化方向和baseline会使大家产生一个误区。就像之前安泰杯的比赛,决赛中评委也说到了baseline,很大程度影响的大家的思维方向。没有说baseline不好,而这只能作为无数解题思路中的一小部分,一个分支。不是沿着这个分支走下去,而是去创造更多分支。这就如同多路召回,之将其当作融合的一部分罢了。

目前只是从关联的角度解决问题,这个角度可以做的更细。也可以考虑其它方向,目前大家做的还都是起点,而不是终点。向量召回、模型召回,以及后面的排序都需要进一步尝试。

建模思路

没有相关经验的同学可能会问正负样本怎么来,那其实很简单,需要我们去构造label。这里分为两步:

  • 样本提取。我们线下验证的时候,一般是用户最后一次点击进行验证,会进行召回50个商品,然后观察召回率。这样的50个商品及对应的用户就是样本数据。
  • 样本打标。召回的50个商品中是最后一次点击的商品labael是1,反之为0。

这样我们就能得到训练集,测试集构造方式一样,只不过需要去预测其label,最后将label的概率进行排序,top50就是最终建模得到的结果。

为了防止数据泄露,构造特征时一定要用历史的点击行为进行构造。最后我们就可以像一般的二分类问题进行解题了。

完整代码

代码语言:javascript
复制
import pandas as pd
from tqdm import tqdm
from collections import defaultdict
import math

# fill user to 50 items  
def get_predict(df, pred_col, top_fill):  
    top_fill = [int(t) for t in top_fill.split(',')]  
    scores = [-1 * i for i in range(1, len(top_fill) + 1)]  
    ids = list(df['user_id'].unique())  
    fill_df = pd.DataFrame(ids * len(top_fill), columns=['user_id'])  
    fill_df.sort_values('user_id', inplace=True)  
    fill_df['item_id'] = top_fill * len(ids)  
    fill_df[pred_col] = scores * len(ids)  
    df = df.append(fill_df)  
    df.sort_values(pred_col, ascending=False, inplace=True)  
    df = df.drop_duplicates(subset=['user_id', 'item_id'], keep='first')  
    df['rank'] = df.groupby('user_id')[pred_col].rank(method='first', ascending=False)  
    df = df[df['rank'] <= 50]  
    df = df.groupby('user_id')['item_id'].apply(lambda x: ','.join([str(i) for i in x])).str.split(',', expand=True).reset_index()  
    return df  

now_phase = 4
train_path = './data/underexpose_train'  
test_path = './data/underexpose_test'  
recom_item = []  

whole_click = pd.DataFrame()  
for c in range(now_phase + 1):  
    print('phase:', c)  
    click_train = pd.read_csv(train_path + '/underexpose_train_click-{}.csv'.format(c), header=None,  names=['user_id', 'item_id', 'time'])  
    click_test = pd.read_csv(test_path + '/underexpose_test_click-{}.csv'.format(c,c), header=None,  names=['user_id', 'item_id', 'time'])  

    all_click = click_train.append(click_test)  
    whole_click = whole_click.append(all_click)  
    whole_click = whole_click.drop_duplicates(subset=['user_id','item_id','time'],keep='last')
    whole_click = whole_click.sort_values('time')

    item_sim_list, user_item = get_sim_item(whole_click, 'user_id', 'item_id', use_iif=False)  

    for i in tqdm(click_test['user_id'].unique()):  
        rank_item = recommend(item_sim_list, user_item, i, 500, 500)  
        for j in rank_item:  
            recom_item.append([i, j[0], j[1]])  
            
# find most popular items  
top50_click = whole_click['item_id'].value_counts().index[:50].values  
top50_click = ','.join([str(i) for i in top50_click])  

recom_df = pd.DataFrame(recom_item, columns=['user_id', 'item_id', 'sim'])  
result = get_predict(recom_df, 'sim', top50_click)  
result.to_csv('baseline.csv', index=False, header=None)

本文参与?腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客?前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与?腾讯云自媒体分享计划? ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 写在前面
  • 关联商品打分
  • 交互行为打分
  • 优化方向
  • 建模思路
  • 完整代码
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
http://www.vxiaotou.com