阿里BST CTR预测模型复现练习

一.算法介绍

实践于阿里19年发布的paper,地址 https://arxiv.org/abs/1905.06874?context=cs.AI

关键字:pytorch, BST, 行为序列建模,推荐模型,Transformer

image

主要输入特征有Item Feature、用户画像、上下文特征、交叉特征经过Embedding 层后concat 在一起。用户行为序列包含Item ID类特征及对应的position 信息,进行Embedding 处理后输入到Transformer 层(Transformer 的Encoder 部分)捕获用户历史行为与Target Item 之间的相互关系得到用户行为兴趣表达,与其他特征embedding 向量concat 在一起,经过三层MLP层计算得到预测的点击率CTR

二.Implementation

①Data


from urllib.request import urlretrieve
from zipfile import ZipFile
urlretrieve("http://files.grouplens.org/datasets/movielens/ml-1m.zip", "movielens.zip")
ZipFile("movielens.zip", "r").extractall() 

②规则融合

def merge(elem1,elem2):
    elem1 = elem1.split('-')  # 将元素基于-分割,次数为没有后缀的情况,如果像我上面的实例有kg作为后缀,可以先对string将进行切片,如elem1[0:-2]
    elem2 = elem2.split('-')
    # 如果前一个元素的最大值等于后一个元素的最小值,则进行融合,返回融合值,否则返回空
    if  elem1[1] == elem2[0]: 
        return ''.join([elem1[0],'-',elem2[1]])
    
def mergelist(list):    
    res = []
    # 如果此input列表只有一个元素,则返回原列表
    if len(list) == 1:
        return list
    # 从列表后端遍历所有相邻元素对
    a = len(list)-2
    while a >= 0:
        new_elem = merge(list[a],list[a+1])
        # 如果可以融合,删除两元素,并在原位置插入新元素
        if merge(list[a],list[a+1]) is not None:
            list[a] = new_elem
            del list[a+1]
        a -= 1
    return list

# 如果存在'>100kg'这样的情况,可以先转换成'100-infikg'进行处理,结束后再统一反转
mergedinput = mergelist(input) # 融合

三.你可能还需要…

①融合前整合数据

我们拿到手的数据,都是松散的,所以需要我们先整合再进行上述融合操作,pandas库的groupby函数可以帮我们做到这一点

I:

name classify weight
小王 手表 0-1kg
小王 日用品 3-10kg
小李 手机 1-3kg
小王 日用品 1-3kg
小李 手机 <1kg
小李 手机 10-30kg
小李 手机 1-3kg

O:

name classify weight
小王 手表 0-1kg
小王 日用品 3-10kg,1-3kg
小李 手机 1-3kg,<1kg,10-30kg,1-3kg
outputDataframe = inputDataframe.groupby(['name','classify'])['weight'].apply(lambda x:x.str.cat(sep=',')).reset_index()

②融合后,无法融合的部分松散数据

对于无法融合成一条的多条规则,因为dataframe后续处理问题,我们也不能将这些规则继续挤在一行用逗号隔开,我们需要将他们拆成多行,保证每一行只有一个规则

I:

name classify weight
小王 手表 0-1kg
小王 日用品 1-10kg
小李 手机 0-3kg,10-30kg

O:

name classify weight
小王 手表 0-1kg
小王 日用品 1-10kg
小李 手机 0-3kg
小李 手机 10-30kg
'''
本质上,使用numpy来存储累加数据,再重新转为dataframe
'''
newvalues=np.dstack((np.repeat(inputDataframe.name.values,list(map(len,inputDataframe.weight.values))),np.repeat(inputDataframe.classify.values,list(map(len,inputDataframe.weight.values))),np.concatenate(inputDataframe.weight.values)))

outputDataframe = pd.DataFrame(data=newvalues[0],columns=inputDataframe.columns)

参考代码

https://github.com/D-Roberts/transformer-recommender

https://github.com/jiwidi/Behavior-Sequence-Transformer-Pytorch

https://github.com/nihalsangeeth/behaviour-seq-transformer

https://github.com/MaurizioFD/RecSys2019_DeepLearning_Evaluation