一.算法介绍
实践于阿里19年发布的paper,地址 https://arxiv.org/abs/1905.06874?context=cs.AI
关键字:pytorch, BST, 行为序列建模,推荐模型,Transformer
主要输入特征有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