rec sys - 实习梳理

主要是对实习期间涉及到的知识进行梳理。

背景:视频推荐(手机端,TV端等)。
场景:feed 流,瀑布流(猜你喜欢),短视频 Tab 等。

召回涉及到的方法(以短视频 Tab 为例):
youtubednn u2i, 插播2i, 频道热门召回,up主2i, 热门内容,FM i2i等。

排序涉及到的方法 (以猜你喜欢为例):
afm, dcn, deepfm, wide&deep, deep_crossing, xgb等。

数据源表(自己日常接触到的表):
show(展示) click(点击) vv(播放次数) vt(播放时长)
都是hive分区表 通过 dt 和 scene 进行限制。

关注的线上指标:
一般情况下都是通过对不同的字段进行group by聚合来求不同维度下的指标。
通常用来聚合的字段有:channel_id(频道), bucket(实验分桶), app_version(版本) ,dt(日期)
通过show表求: show_pv , show_uv
通过click表求: click_pv , click_uv
通过vv表求:vv
通过vt表求:vt
ctr = click_pv / show_pv
uctr = click_uv / show_uv
ppui = vt / show_uv
次留

以端指标为核心,日常关注的方面:

  1. 召回,排序模型的优化。这其中包括 特征丰富,多场景,多目标,冷启动,实时性,指标加权,长尾分发,软保量硬保量,debiasing, 新颖性等。每个方面都值得之后再具体展开(更新中)。
  2. 对1中的方法设计实验,进行A/B test, 接下来几天再进行场景指标,端指标的观察和对比,验证实验的效果。
  3. 线上问题的跟踪与排查。拿到用户以及up主的负面反馈(bad case),对于具体的问题分析成因,设计实验方法进行改进。改进的方面无非也是1中那些方法。
  4. 在关注推荐系统用户消费指标之外,针对部分推荐场景,基于各产品的业务定位把评估体系进一步完善。

以参与过的TV端 猜你喜欢场景的A/B Test为例,主要为达成以下三个目标:
1.长视频端播放时长,端次留(也就是说这两个指标是核心指标,验证实验是否成功)
2.对电影/电视剧/综艺的分发量进行扶持
3.猜你喜欢场景同样存在追剧的席位,降低追剧占比,提升新颖性和探索性。

主要设计的实验如下:

规则层面:
1.追剧内容打压儿童、游戏策略实验(就是把儿童,游戏频道的追剧内容直接减少)
2.按小时兴趣频道提权,分时段重排减少儿童、游戏内容占比
3.保留前三卡追剧,后面位置个性化探索(该场景就是电视端的猜你喜欢的十多个栏位,把前三个拦住都设置为追剧,即用户最近在看的剧,后面的栏位自动分发。)

召回层面:
4.高消费指数召回
5.豆瓣高分召回

模型层面:
6.训练样本影剧综提权

之后再统计几天内每个实验桶下的场景指标和端指标,一般来讲时间越长说服力越好,单独拿某一天的指标进行实验的对比并没有什么意义。而且这里并没有使用置信度的概念。

短视频场景逻辑梳理:

image.png

拿到原始数据,先进行简单的过滤,例如付费内容,色情,政治敏感,时效性(去除老旧的内容)等,写入Corpus。

从Corpus中取数据进行多路召回,方法各种各样有很多,除了深度模型大多可以通过sql完成。
每路召回的数量也不一定(每种召回路径中的物料id也可作为之后模型学习的特征,如果该物料排名较好,可以理解为该路召回效果不错,可考虑加权重)
所有召回的内容加在一起,之后一起过粗排。

在做粗排前(pre_train),我们拿到了召回得到的物料id. 拿这些id去特征库中(couchbase)匹配,(特征是全部做好的,我们只需要拿召回结果去匹配就好了)。
同时我们还需要拿到label,在有的场景下,label可以自定义,比如说观看时长>15s的.
有的场景不适合这样定义。这时候就需要pingback了,我们可以通过pingback看用户是否点击了,进而拿来做label 0和1 。

拿到特征和label后(七天的数据)做特征的组合,生成train_dataset, 再生成tfrecord格式.
opal调用gitlab代码进行离线训练。训练完成后,保存模型。模型在http服务上进行预测
(预测时,也是从根据id从couchbase中拿到对应的特征,以及实时特征,直接送至模型进行预测)
得到粗排后的结果,是物料id 设备id 还有排序。

根据粗排得到的结果,再去cb中匹配特征,与粗排同样的步骤进行精排,模型在http服务上进行预测.
之后我们只需给引擎那边 http地址,他们就可以继续做下去,得到精排后的结果。
再进行重排,(MMR,强插等策略,最终可能只留下top5) 进行推荐。

特征回放好像就是指 特征到CB,根据id从CB中取特征的过程。(不确定)


(瞎BB版,不改动了,有很多逻辑梳理错误,理解错误的地方,回看的时候看能不能找到。刚好保留之前自己琢磨时陷入的思维陷阱 )

TV推荐场景

corpus根据什么来定义:

首先从 videoflow_al_da_snap_hive_episode_album_ppc_meta_latest_view 第一步筛选,
例如 过滤掉 推荐等级为0的,过滤掉 所有的付费内容, 过滤掉所有不可试看内容等等,这样生成了第一步基础的corpus -- tv_basic_short_corpus

在tv_basic_short_corpus中进一步限制掉 政治,色情的内容,并scene=‘short_tab’,生成短视频tab的高质量的corpus数据.

在tv_basic_short_corpus中进一步限制掉 政治,色情的内容,并scene=‘aiplay’,生成随心看的高质量的corpus数据.

把上面生成的两个 union all起来 后,对不同的频道需要控制 不同的 时效性。 有的频道需要限制在一周内,有的需要控制一个月内,有的则需要更久。
对时效性进行限制后,重写入 tv_basic_short_corpus

再通过几个 视频 质量分的特征 进一步筛选 高质量的视频 存入 tv_short_tab_corpus_quality

以上是corpus的生成过程。


之后进入召回流程:

召回分为 i2i 标签召回 TGI召回 模型召回 trigger 兜底召回 u2i
每个分类下面又有好多的方法。

(标签召回就很简单 从不同的维度取出 热度较高 的视频或者是 up主 再取出排名前100or前200的
这种方法是统一的 因为没有利用到 具体用户和视频的交互信息 所以做不到 个性化)

通过以上构建的tv_short_tab_corpus 进行多种标签召回 和 倒排 (例如 hot_up hot_channel hot_search hot_short)

以hot_up为例,用到这个语句,以粉丝量做排名 从多到少
row_number() over (partition by domain_name order by fans_following_count desc) as rank

粉丝量这个特征是从videoflow_al.videoflow_al_da_snap_hive_iqiyi_user_meta_view取得(这个源表中还有视频质量分等特征) 因此同时需要 corpus表和这个源表 做join

取出 up rank < 100的 domain, uploader_id 和其对应的quality_score 并存入 tv_dwd_dd_recall_invert_qiguan这张表。

同样的方法 根据其他几路召回的定义 取出 channel rank < 200的 channel-id, qipu_id, 以及其对应的hot 并存入tv_dwd_dd_recall_invert_qiguan这张表。 不同召回方式的数据 用 reverse_type = '' 做分区。 (不同的召回的方式 可以见 锋哥 以前发的截图)

还有一种up2up 通过该up进行相同domain其他up的推荐。

以上是标签召回 还有很多方式 具体见 babel - tv推荐 - 基础数据 - 标签召回及倒排

通过标签召回的数据都存入tv_dwd_dd_recall_invert_qiguan 的不同分区

以上是 标签召回的过程


(再以i2i 召回为例)

以 fm i2i为例 fm i2i 的路径分为两条 tv i2i 和 short tab i2i

tv i2i 用到了表 dwd_base_recall_i2i_fm_prediction_dd dwd_kpp_dump_column_related_rec_hh tv_dwd_dd_view_long_video_corpus 并写入 tv_dwd_dd_fm_i2i_recall

short tab i2i 用到了表 dwd_base_recall_i2i_fm_prediction_dd tv_short_tab_corpus 并写入 tv_dwd_dd_recall_i2i_qiguan 的某个分区

为了跟之前的逻辑对照 还是以短视频的这个路径为例
先看dwd_base_recall_i2i_fm_prediction_dd 哪来的 这个表是成都那边产的 。。

看一下该表的结构:
hive> desc dwd_base_recall_i2i_fm_prediction_dd;


tv_id string
rec_tv_id string
score double
channel_id int
dt string


即已经给出了 tv_id 和 根据其 推荐的 rec_tv_id 还有二者的得分 score

接着看 short_tab i2i 这里就很简单了 取出 dwd_base_recall_i2i_fm_prediction_dd中的 tv_id rec_tv_id score 并与 tv_short_tab_corpus中的qipu_eposide_id join

得到的 数据 写入到 tv_dwd_dd_recall_i2i_qiguan 的某个分区

以上是i2i召回的过程


(再以youtubednn召回为例)

从 tv_dwd_dd_user_click 拿到用户的点击记录 再与 tv_dwd_dd_corpus_merged 的前一天的数据 通过album_id join 之后再通过 tv_dwd_dd_black_device 限制设备

最后拿到 device_id ,entity_id , 1 as label, 1 as weight , concat('last_20_click:', concat_ws(',',collect_list(entity_id))) as cf . .存入tv_dwd_dd_train_dataset

根据entity_id 出现的次数 对其进行 row_number()排序 得到一列新特征 并连同之前的特征写入 tv_dwd_dd_train_dataset_merged中。

之后进入到 gen_data 模块 ,子工作流为 tv_common_sub_gen_train_data_without_sample_libsvm

gen_data模块:

对tv_dwd_dd_train_dataset_merged中的数据进行以下操作:

cate_fea > gen_idmapping > feature_field_extract > feature_field_to_mysql

num_fea > numerical_feature_info > update_numerical_columns > numerical_feature_column_to_mysql

之后join 再进行 tfrecord_gen 得到 clean_data 位于 hadoop fs -rm -r /data/bi_uaa/rec/tv-rec/tfrecord/{SCENE}/{DT_BEFORE}/

即通过模型召回得到的数据以 tfrecord格式 放在 hdfs上


前面的标签召回和i2i召回后 生成tv_dwd_dd_recall_i2i_qiguan ,这张表下一步紧接着干嘛呢 ?

tv_dwd_dd_recall_i2i_qiguan 生成后的步骤 暂没找到


进入排序模型训练部分

这一部分 包括 feature_extract label_extract train

这部分操作 都是用的 dwd_dd_show click vv等表 并没有用到corpus表

feature extract 从三个角度 entity_feature device_feature cross_feature 做特征 做的特征 通过feature_type 进行区分cate num
分别存入不同的表 并通过dt scene 进行分区

例如 tv_dwd_dd_entity_feature_by_scene
再进入一个子工作流 通过feature_type = num cate把num cate feature分别提取出来 用concat_ws 进行拼接 as categorical_featuers numerical_features
再存入 tv_dwd_dd_entity_feature_by_scene_combined 之后再跟一个 spark 模块 名为import 暂不清楚这个模块是不是用来生成 tfrecord 的。。

label_extract 也是通过定义 (t1.item is not null and t1.playtime > 15, 1, 0) as label 来进行label的定义。

train模块不只是train 主要包括以下几个模块 make_sample gen_data gen_tf_record

make_sample : 规范的从feature表和label表拿到每天的数据 拼接 写入tv_dwd_dd_train_dataset

gen_data:放在make_sample 之后, 从 tv_dwd_dd_train_dataset 拿到七天内的数据 ,写入到 tv_dwd_dd_train_dataset_merged

之后再进行 cate_fea > gen_idmapping > feature_field_extract > feature_field_to_mysql

num_fea > numerical_feature_info > update_numerical_columns > numerical_feature_column_to_mysql

再生成 tfrecord.


根据上面的总结 还存在几点问题 Corpus主要是用来干嘛的
应该是主要做 非模型的召回等方式的吧 做完生成tv_dwd_dd_recall_i2i_qiguan之后呢。

在线训练是从哪进行的 是从生成的tdrecord 开始训练的嘛 tfrecord不是存的7天数据吗。 在线训练的任务流在哪。

之后不是在opal上训练模型吗 模型的预测结果写入哪里了 是不是保存模型文件后 拿去线上预测 保存的模型文件不是用当天以及以前7天的数据训练的吗
拿到线上的话 不存在时间跨度的问题吗

还是说opal上的模型只是用来对模型离线训练 用来调整模型的结构和参数 等调好了 再拿到线上用吗 ? 线上还需要训练吗 还是直接调用模型进行预测 线上预测的代码在哪 是python实现的吗?

如果线上预测的代码不是python 是java的话 应该是把离线的模型 调用后 在java中预测给出预测结果把 或者不是java呢 这部分的代码在哪里呢

为啥我觉得做排序的时候 做train_dataset用的表不是 召回后的结果 而且直接用 dwd_dd_ click show ..detail表 加工而来的


往前看的话 用户进入app 有展示,点击,观看记录 经过开发岗的加工 我们才拿到比较干净的数据。。
此外 在模型上线前 我们经常需要找开发 进行沟通 是为了什么?


https://zhuanlan.zhihu.com/p/81752025 对于 推荐系统架构 文章的一些疑问:

如文章所说,模型存储在 在线存储模块(用于存储模型和模型需要的特征信息供实时计算模块调用), 预测的数据流接受业务的预测请求,通过 A/B 测试模块访问 实时计算模块 获取预测结果。

实时计算模块:(实时推荐模块的功能是对来自业务的新请求进行预测。1.获取用户特征;2.调用推荐模型;3.结果排序。)

那么app的 在线存储模块 和 实时计算模块在哪里(是什么平台) 代码又在哪里


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,837评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,551评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,417评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,448评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,524评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,554评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,569评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,316评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,766评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,077评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,240评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,912评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,560评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,176评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,425评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,114评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,114评论 2 352

推荐阅读更多精彩内容