听云推荐系统贰

本文延续上一篇博文,继续介绍推荐离线层的一些策略设计

背景

  本文主要介绍关于推荐推荐策略的设计 , 以及简单介绍推荐中常用的ABtest分流验证策略(好坏)的方法
  
  本项目的实现代码在: Recommend Offline

离线层策略设计

  上一篇文章中简要提到了,我们的设计从大到小,按照如下几个等级称呼

1
产品线 --> 策略 --> 模型(算法)

  解释如下:一个产品线下可以配置多个策略,一个策略可以是单个模型(算法)计算得到的结果,也可以是混合得到 
  ABtest在其中的位置:对某个产品线中的多个策略,进行流量划分
  反馈:根据日志采集的结果指标,可视化之后对比各个策略的表现,调整ABtest中的流量划分,使得推荐效果最大化,单个策略则需要调整各个模型的占比

大体逻辑如下图
示例图1

设计实现

  那有了以上说的内容,我们将其逐步实现,以下我们均使用音乐推荐相关的维度来进行说明

model(算法)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
all_model=[
{
"id":18, #手动配置id,新增算法往后+1
"name":"cf_new", #算法名,用作解释
"version":"1.0.0", #版本号,暂未使用
"source":"1", #单一算法的策略值,不能与混合策略重复
"struct":"zset", #redis中存储数据类型,一般zset
"key":"cf_songnw_songid" #redis中存储的key格式,一般取得其前缀,拼接对应类型的基础数据(songid,albumid,singerid)
},
{
"id":19,
"name":"lrc_simiSong",
"version":"1.0.0",
"source":"1",
"struct":"zset",
"key":"lrc_simiSong_songid"
},
{ .... }, #新增model
{ .... }
]

  以上定义的一个model需要定义的部分内容,由于我们只需要使用它,生成它的算法不作讨论,所以这部分内容写在配置文件中即可,按照代码中说明添加即可

strategy(策略)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
product_strategy = {
"linear_similar_song":{
"name":"linear_similar_song",
"class":"song", #使用哪种类型的rdd(song,album,singer),基础数据
"key":"abtest_simSong_songid", #合并策略灌入redis 的结果key
"source":23,
"rerankid":2,
"strategy":[ #策略 混合多种model
{
"modelid":18,
"weight":2
},
{
"modelid":19,
"weight":2
}
]
},
"xxxxxx":{}, #新增策略
"xxxxxx":{}
}

  由于本项目在混合离线数据的时候,使用到了spark去获取并合并需要的算法结果,所以我们需要指定class – 表明加载哪种类型的基础数据(生成spark使用的rdd),去获取对应结果的redis数据整合

1
2
3
4
5
6
7
比如我需要取得是相似歌曲,即  -- 歌曲关联歌曲 

那对应的rdd class是: song , 因为是: song -- song

此时对应的strategy中配置的基础model应该也都是: song -- song 的算法,这个是我们主动配置的,比如
上面代码中的: cf_new -- cf_songnw_songid , 这个redis key中存放的是某首歌曲根据cf_new这个算
法得到的相似歌曲

  一般某个算法得到的离线结果都是list类型的,在redis中存储的格式为zset,我们可以使用zrange方法取到

  spark在这里相当于是一个加速的效果,使得混合大量离线数据结果的效率变快.

实际数据说明

  假设我需要知道一首歌: 《星月神话》的相似歌曲, 这首歌的songid是545076619, 存储在本地的 song_dict_path=”song.id.dat” 文件中
  
  这时候我们需要使用spark读取class == song 类型的基础数据, 将其load成rdd(需了解spark中rdd的概念,简单来说就是spark的一种数据定义,使用其能方便地利用内存集群去快速操作数据),我们的操作是查询每个歌曲关联的算法的redis结果,取出数据然后按照权重配置来合并并重新排序
  
  我们可以看到linear_similar_song(相似歌曲)的策略中有两个算法:18 / 19 , 比重均是2, 继续去看all_model 中modelid 18 和 19 的算法, 是:cf_new 和 lrc_simiSong ,那么对应的redis 的结果数据应该可按照如下方法查询到

1
2
3
4
5
6
7
127.0.0.1:6379> zrange cf_songnw_545076619 0 -1 withscores
1) "545076365"
2) "0.6"

127.0.0.1:6379> zrange lrc_simiSong_545076619 0 -1 withscores
1) "545076365"
2) "0.8"

  为了方便我只列举了同一首歌曲的score值,这里计算的过程如下:

1
2
3
4
5
6
7
8
9
model name			songid    : score

cf_songnw_545076619 545076365 : 0.6

lrc_simiSong_545076619 545076365 : 0.8

合并相同值的权重(weight = 2),和歌曲545076365 的关联最终score值

(0.6 * 2 + 0.8 * 2) / (2 + 2) = 0.7

  得到了最终的结果,我们就可以将其灌入redis,指定一个新的key值,查询结果如下

1
2
3
127.0.0.1:6379> zrange abtest_simSong_545076619 0 -1 withscores
1) "545076365"
2) "0.7"

  可以看到对应的:545076619 – 545076365 的final score值是0.7

ABtest

概念

  一种网站优化的方法,通过科学的:实验设计,采样样本代表性,流量分割,小流量测试等方式 , 来获取具有代表性的实验结论,并确信改结论推广到全部流量可信。
  
  简单来说:为同一个目标制定两套方案 (比如同一个网页),让一部分的用户使用A , 另外一部分使用B , 记录下使用(反馈)的情况,比如点击率,停留时长等等指标,看哪个更符合设计

总结

  关于ABtest这部分,就暂时不在这篇文章中再细聊,因为这部分一般都是在在线逻辑层去完成的,要想将其放到离线中,须新的设计,不仅仅是离线层能做的事情,还需要调整在线层使用数据的逻辑
  
  以上关于算法混合的部分均已经自动化,只需要按照配置在base_conf.py中添加,并且主动将依赖的redis数据灌入,再运行脚本即可得到结果

  但这部分数据仅仅只是按照配置将不同算法的数据结合的结果,要想得到更符合用户喜欢的结果,在线层还可以做的一些事:基于用户画像(喜好)二次排序 ,手动配置优质内容 …. 这些都是可选择的方法