快手实习小结

工作岗位

快手数据算法工程师实习

工作内容简述

负责快影APP“一键出片”功能的开发,依需求确定所需的数据,建立合理的特征体系,进行相关数据清洗,负信号的选择,模型的选择与调优(二分类问题AUC值为:83%),召回策略的开发,线上部署与性能优化,AB测试;

内容详述

1、背景介绍

快影APP是一款视频制作软件,日活用户量级600w+,模板量级100w+,它的功能特点是,每个用户都可以制作视频模板上传到该APP上,其他用户可以直接选择这些模板,通过导入自己的素材来快速生成视频作品,大大降低了视频创作的技术要求,提升了日活用户量(DAU)和用户留存率

模板推荐功能是指,用户通过导入自己的素材,由平台在线进行智能识别,通过将识别结果和模板库进行匹配,给用户推荐合适的模板,从而减少用户搜索模板花费的时间。

2、特征体系

主要包含以下几类:模板特征、作品特征、用户特征、设备特征、转化率特征,以及基于以上特征衍生的交叉特征。(体系结构如下图所示,特征总计343个)

graph LR
%% 特征体系图
    %% 一级结构
    feature-system("Feature System") --> user-features("User Features")

    feature-system --> template-features("Template Features")
    
    feature-system --> video-features("Video Features")

    feature-system --> device-features("Device Features")

    
    %%二级结构
    template-features --> base-features("Base Features")

    template-features --> real-time-action-features("Real Time Action Features")
    
    template-features --> history-action-features("History Action Features")

    %%三级结构
    real-time-action-features --> transfermation-ratio-features("Transfermation Ratio Features")

    history-action-features --> transfermation-ratio-features("Transfermation Ratio Features")

    %% 四级结构
    user-features --> cross-features("Cross Features")
    device-features --> cross-features
    transfermation-ratio-features --> cross-features

2.1 模板特征

2.1.1 模板基础特征

模板创作时间至今的时间差、模板宽度、模板高度、模板支持素材数、模板时长、模板创作标签(例如:所属分栏(情感语录、风景、游戏、运动会等),画面风格标签(恶搞、甜美、文艺、反差、潮酷等),内容标签(生日、萌娃、萌宠、汽车等),玩法形式标签(九宫格、四宫格、变装等))。

2.1.2 模板行为特征(即时)

模板当日点赞、模板当日导出次数、模板当日分享到微信次数、模板当日分享到快手次数、模板当日分享到qq空间次数、…、模板直接导出次数、模板当日拉新用户数、模板当日拉活用户数、模板当日拉新设备数、模板当日拉活设备数、…、模板当日预览次数、模板当日导出作品数、…

2.1.3 模板行为特征(历史)

过去一周:模板点赞总次数、模板总导出总次数、模板分享到微信次数、模板分享到快手总次数、模板预览次数、模板导出作品数…

过去一月:模板点赞总次数、模板总导出总次数、模板分享到微信次数、模板分享到快手总次数、模板预览次数、模板导出作品数…

历史总计:模板点赞总次数、模板总导出总次数、模板分享到微信次数、模板分享到快手总次数、模板预览次数、模板导出作品数…

2.2 转化率特征

2.2.1 即时转化率

当日预览导出率=模板当日导出作品次数/模板当日预览次数
当日导出作品平均播放时长=作品当日总播放时长/导出作品当日播放总次数
当日导出分享率=当日导出并分享次数/当日导出总次数
当日预览点赞率=模板当日点赞次数/模板当日预览次数

2.2.2 历史转化率

过去一周:
过去一周预览导出率=模板过去一周导出作品次数/模板过去一周预览次数
过去一周导出作品平均播放时长=作品过去一周总播放时长/导出作品过去一周播放总次数
过去一周导出分享率=过去一周导出并分享次数/过去一周导出总次数
过去一周预览点赞率=模板过去一周点赞次数/模板过去一周预览次数

过去一月:
过去一月预览导出率=模板过去一月导出作品次数/模板过去一月预览次数
过去一月导出作品平均播放时长=作品过去一月总播放时长/导出作品过去一月播放总次数
过去一月导出分享率=过去一月导出并分享次数/过去一月导出总次数
过去一月预览点赞率=模板过去一月点赞次数/模板过去一月预览次数

历史总计:
历史预览导出率=模板历史导出作品次数/模板历史预览次数
历史导出作品平均播放时长=作品历史总播放时长/导出作品历史播放总次数
历史导出分享率=历史导出并分享次数/历史导出总次数
历史预览点赞率=模板历史点赞次数/模板历史预览次数

2.3 用户特征

性别、年龄、城市、文化程度、画像性别、画像年龄等

2.4 设备特征

设备机型、设备价格

2.5 交叉特征

用户特征*即时转化率特征
用户特征*历史转化率特征

设备特征*即时转化率特征
设备特征*历史转化率特征

3 数据清洗

主要包括以下几个内容:重复数据的剔除、低质量数据的转化、字段数据的解析、one-hot编码。

3.1 重复数据的剔除

由于所需特征较多,且数据库庞杂,绝大多数的数据表来源不同、使用目的不一致、命名规范不统一,因此,各表之间存在很多的重复数据。

数据重复形式大致分为以下几种:

(1) 字段名重复、字段值不同
这种情况下,需要向表的负责人进行询问表中相关字段的具体含义,以确定每一个字段的属性。因为,有可能两个字段都是自己需要的,也可能只有一个是需要的,这就需要从数据本身的属性去判断,哪个是真正需要的字段。

(2) 字段名不同、字段值重复
如果经核验之后,确认两个字段值是一致的,那么任选其一保留即可;
难点在于如何发现多个表中的重复字段值。(①从字段名出发,对字段名相似的字段进行排查,字段名相似的字段可能具有相似的意义,也就可能取相同的值;②筛选字段时,多注意字段的值,在遇到相似取值的字段时,认知敏感度会变高)

(3) 字段名重复、字段值重复
直接二选一即可

3.2 低质量数据的转化

例如,我们最初只有模板创建时间(时间戳,bigint类型),数据取值非常大,导致在建模分析时,该字段的增益值非常大,导致其他特征作用不显著,因此将他替换为创建时间至今的天数差值;
再例如,我们并不太关注用户的具体年龄,而是注重用户所属的年龄段,因为同一年龄段的用户具有相似的行为特征,因此我们需要找打合适年龄段划分区间来替代年龄;
类似地,设备的具体价格并不是我们关注的重点,但是,设备所属的价格区间具有一定代表性。

3.3 其他数据类型字段的解析

典型的如:String类型,jsonArray类型;

(1) String类型
① 取值个数较少,直接进行one-hot编码或者如果具有等级关系,则进行序数编码;

② IP地址类型的数据,将其解析为经纬度坐标(两列int类型);

③ 查看是否具有某个子串,进行0-1编码;

④ 取值较多时,随机分配数值,导入模型时,指明为分类特征,交给模型处理(lgb具有自动处理分类特征的能力,catboost再这方面能力更佳)。

(2) JsonArray类型:
自定义udf处理,或者python脚本中处理

3.4 one-hot编码

针对分类型字段进行处理,例如是否具有某个创作者标签,但如果这类特征较多,容易造成数据稀疏,影响模型的表现。

4 负信号选择

定义1: 在一条task中,只选取被预览的模板作为样本,其中,只被预览而没有导出作品的记为负样本,被预览且导出作品的记为正样本。(图示如下)

graph LR
    task("Task")-->template1("Preview Template 1 <br> Negtive Sasmple")-->template2("Preview Template 2 <br> Negtive Sample")-->dots("...")-->templaten("Preview Template n <br> Positive Sample")-->video("Export Video");

该定义下,若选取过去十天的数据,总样本量约7000w+,正、负样本比例约为1:25。

定义2: 在一条task中,只选取被曝光的模板作为样本,其中,只曝光而没有导出作品的记为负样本,曝光且导出作品的记为正样本。(图示如下)

graph LR
    task("Task")-->template1("Exposure Template 1 <br> Negtive Sample")-->template2("Exposure Template 2 <br> Negtive Sample")-->dots("...")-->templaten("Exposure Template n <br> Positive Sample")-->video("Export Video");

该定义下,若选取过去十天的数据,总样本量约9000w+,正、负样本比例约为1:36。

5 样本预处理

5.1 特征解释及重要性预估

例如:
预览导出率(即时+历史)反映了模板转化能力的强弱,转化能力越强,该模板被接受的概率越大,因此应该与样本标签具有最强的相关性;

用户特征*预览导出率反映了模板对不同人群的转化能力,能够在区分性别、年龄段的情况下,反映模板是否容易被用户接受;

诸如此类

5.2 采样

如4所述,正、负样本比例悬殊,如不加处理,容易造成过拟合。例如,在采用定义1的情况下,若不进行采样处理,即使模型将样本全部预测为负样本,正确率依然在90%以上,而如果进行1:1采样之后,模型的效能则会明显下降;因此需要对样本进行1:1下采样;

此外,我们的样本总量很大,若采用全部样本进行训练,一是会浪费大量的计算资源,二是会降低训练速度,三是会将所有模板考虑进去(实际上在最初的阶段只需要考虑高热度的模板)。因此,需要对样本总量进行限制;

综上,我们先保留所有正样本,然后按1:1的比例对负样本进行采样,得到正、负样本混合的样本550w+;然后通过完全随机采样,抽取100w的样本导入模型进行训练。采样后的正负样本比例约为46w:54w

5.3 数据集划分

我们使用了近十天的数据作为样本总体,以前十天–前三天的数据作为训练集,近三天的数据通过1:1随机划分产生验证集和测试集,即训练集:验证集:测试集合=7:1.5:1.5。

6 训练与调优

6.1 模型选择

① Logistic Regression(BaseLine)

② XGB

③ LightGBM

6.2 模型表现

LR < XGB < LightGBM

6.3 模型训练

某实验平台:训练模型流程图如下

graph TD

%% first layer
train(TrainSet Hive Table);
valid(ValidSet Hive Table);
test(TestSet Hive Table);

%% second layer
fillna1(Missing Values Filled);
fillna2(Missing Values Filled);

%% third layer
trainmodel(Train Model);

%% fourth layer
predict(Predict);

%% fifth layer
output(Output Hive Table)

%% construct graph
train --> fillna1;
valid --> fillna1;
fillna1 --> trainmodel;

test --> fillna2;

trainmodel --> predict;
fillna2 ---> predict;

predict --> output;

6.4 模型调优

6.4.1 特征调整

① 导出特征的重要性,与预期水平进行比较,将表现异常的特征列出;

② 若特征表现超过预期,考虑是否是对特征的解释有错误从而导致错误估计特征重要度(向相关同事进行咨询确认),是否是由于数量级太大造成的(若是,对该特征进行处理);
若特征表现低于预期,考虑是否是对特征的解释有错误从而导致错误估计特征重要度(向相关同事进行咨询确认),是否对特征的预处理方式不当(例如,由于进行one-hot编码使得一个特征分化为多个特征,作为一个特征时本应发挥较大作用,但分化后作用都不显著)。

③ 对于确认不是由于操作不当引起重要性与预期不符的特征,若特征重要性高的异常,进行后处理;若特征重要性低的异常,直接剔除。

④ 重复以上过程,直至模型特征稳定。

6.4.2 参数调整

lightGBM表现高于LR和XGB,因此选择lightGBM作为预测模型;

可调整参数:训练轮次、树的最大深度、最大叶子节点数、1\ell_{1} 正则化系数,2\ell_{2} 正则化系数。

7 召回策略

7.1 前置过滤

前置过滤是指,在把所有模板导入可用模板库之前进行一次过滤,以免不可用模板被推荐给用户。此过程在数据库中操作完成。

(1)上线模式过滤:库内模板分为“发布”、“预发布”、“审核中”,只保留“发布”状态的模板;

(2)云端模板过滤:部分模板存在云端,不参与召回,因此直接过滤;

(3)版本过滤:模板分为wg,ae,所有ae模板都过滤掉,wg模板版本号大于指定版本号的模板也过滤掉,防止低版本APP不兼容导致异常;

(4)片段数过滤:模板支持片段数和模板信息JsonArray字段解析出的片段数不一致的,直接过滤掉;支持片段数为0的模板,直接过滤掉;

(5)标签过滤:具有黑色意义标签的模板直接过滤掉(例如,自杀、离婚等),具有特定标签的模板过滤掉(例如,情感语录);

7.2 后置过滤

后置过滤是指,用户发起请求之后,通过解析用户请求数据,需要返回高度相关的模板而进行的过滤;此过程在工程开发中完成。

7.2.1 后置通用过滤

(1)片段数过滤:模板支持替换素材数小于用户上传素材数量不一致的,直接过滤掉;大于等于用户上传素材数的则保留;

(2)时长过滤:模板片段时长大于素材片段时长的(逐段比较,有一段不符合的,即过滤掉),直接过滤掉;(因为模板片段时长小于素材时长时,可以循环素材,反之不能)

(3)横竖屏过滤:识别为横屏(width > height)场景的,不能推荐竖屏(width < height)模板,反之亦然

7.2.2 召回场景

baby,male_young,female_young,male_middle,female_middle,male_old,female_old,outdoor,cat,dog,animal,food

7.2.3 召回条件

hot_condition = (export_mv_num > threshold1) and (export_mv_num_week > threshold2)

not_person_condition = (recog_not_person_ratio > threshold) and (recog_person_cnt < recog_not_person_cnt)

对不同场景实施不同的召回策略(简化版)
(1)baby:
(recog_baby_ratio > threshold) and hot_condition and (tab_mengwa == 1)

(12) food:
(recog_food_ratio > threshold) and not_person_condition and hot_condition and (tab_meishi == 1)

8 线上部署

8.1 部署工具

python(numpy/pandas/json/argparser/lightgbm),redis(模型及数据表存储、加载),git(版本控制、协作开发)

8.2 优化

8.2.1 表的存储

用户特征表、模板特征表、设备特征表分开存储,由redis加载到服务器后在线构造交叉特征,这么做便于后续表的调整(如果需要改动,只需要一张表一张表的调整,增加了稳定性和安全性,用户表和设备表几乎时不会变动的)。

8.2.2 模板数据的线上存储

将数据加载进来之后,模板库的数据量较大。如果在用户发起请求之后,对整个模板库进行过滤和召回,那么花费的时间会非常多(60+s),因此考虑将模板的过滤放在用户发起请求之前,排序放在用户发起请求之后。

如何实现在用户发起请求之前进行过滤?
因为场景是固定的(age+gender+item),因此我们将模板预先按照不同的场景进行划分,然后对不同的子集按照后置过滤规则进行筛选,这样就可以把模板分成十几个小的模板库,每个小的模板库中只含有几万个模板,对这样量级的模板库进行筛选就快很多了。

以上策略完成之后,从用户发起请求到用户拿到推荐结果,中间只间隔0.2s,这就达到可应用的水平了。但另一个问题是,加载数据表、划分子库进行过滤时会花费大量的时间,经过排查之后发现是由于pandas的dataframe数据类型拖慢了处理进程,因此改用numpy的ndarray类型,时间花销从3min30s减少到20+s,达到可接受的调试等待时间。

8.2.3 场景的匹配

前面说到,预先将模板分场景进行存储,那么我们时怎么通过解析用户请求来构造用户请求场景的?

首先看用户请求被解析后的形式(简化版):
{
“id”: *******,

“gender”:0,

“age”:23,

“scene”:{“female”,“young”,null},

“material”:{

{“duration”:5.2,“width”:1080,“height”:1920,“female”:0.95,“young”:0.84,“item”:0.0},

{“duration”:2.0,“width”:1080,“height”:1920,“female”:0.92,“young”:0.86,“item”:0.0},

{“duration”:8.1,“width”:1080,“height”:1920,“female”:0.97,“young”:0.63,“item”:0.0}

}

}

id即为用户id,gender即为用户性别(0女,1男),age为用户年龄,scene为识别出的场景信息,material为用户上传的素材信息(素材时长,素材长、宽,素材被识别各场景的概率(略写其他场景))

根据以上信息,构造用户请求的具体场景如下:
①优先人物场景,其次非人物,最后兜底默认场景

②首先识别用户年龄,对于baby场景不区分男女

③若有人物年龄信息(非baby),查看性别信息,可构造如femal_young,male_young场景;

若无人物年龄信息,直接进入item场景(包含food,outdoor,animal等)

④若以上信息均无,则进入默认场景兜底。


快手实习小结
https://www.lihaibao.cn/2022/04/14/快手实习小结/
Author
Seal Li
Posted on
April 14, 2022
Licensed under