实习经历

实习期间做了什么:

离线数据任务的迁移,主要是算子的迁移

迁移的原因

  1. 多方使用 —— 单业务出错,其他出错 —— 推出不合时宜的视频 or 视频被假限流
  2. 推荐是逐步推荐的过程 —— 候选、粗排、精排、混排 —— 候选&候选、其他&正排 —— 时间差 —— miss 比例
  3. 旧算子串行 —— 新算子并行 —— DAG
  4. 多业务方共用一个数据流处理,头条、懂车帝、问答等均在这里。那么一个业务方的代码出现了差错,会导致其他业务方处理错误。例如,某段代码没有进行异常检查,导致出现了异常,当前算子的后续逻辑就无法执行,那么可能就会造成一些不该被推荐的视频被推荐了出来,或者某些视频一直无法推荐,作者以为被限流了。
  5. 推荐架构是一个逐步推荐的过程,候选-粗排-精排-混排。候选用的候选属性,其他使用正排属性。在历史的数据流中,候选属性的处理和正排属性的处理是分开的。这看起来是没问题的,但对于新发布的视频会存在时间差。如果某个新视频在 1 点计算出了候选属性,在 1 点 10 分计算出了正排属性。而候选模型在 1 点 5 分时选择将这个新视频进行推荐,那么在后面的流程中,是无法及时获取这个视频的正排属性的,也就存在一些 miss 情况。根据在线服务的日志中,这个 miss 率大概处于 3000 条候选数据有 500 条正排属性缺失的 miss 比例。
  6. 在旧的数据处理框架中,算子是串行执行的。新的数据处理框架中,采用 DAG 图,让没有依赖关系的算子并行执行。

离线数据流介绍 —— 更清晰

我所处的部门负责的方向是协助算法同学将头条、抖音、西瓜等的内容推荐到 VIVO、OPPO、小米等厂商浏览器或视频 APP 上。其中这分为在线服务和离线数据处理两个部分,我负责的就是离线部分。以短视频为例,短视频可能包含视频的创建时间、过期时间、可推荐度、作者、关键词、展现数、点击数、抖音点击数、西瓜点击数等数据。离线数据处理部分就是将根据到来的短视频 ID 从多个服务上获得其相关数据,将其写入到存储中,供模型构建时读取。

当前框架的最底层是基于 Flink 流式处理,经过基础架构团队进行了封装,我们只需要实现输入数据流的处理和短视频属性的处理两个部分内容。

在短视频属性处理部分,我们将从不同的属性处理逻辑放到不同的处理类中,这些处理类被称为算子。例如从计数服务中获得点击量等属性,从内容中台获得作者信息等属性,还有根据已获得属性进行后处理的算子。为了加快单个视频的执行速度,采用了 DAG 有向无环图的方式来构建算子之间的依赖关系,并使用线程池来执行任务。将无前置依赖的算子加入线程池中,并增加回调函数。执行结束后,通过 AtomicInteger 更新后置算子的入度,若入度为 0,则将后置算子加入到线程池中执行。

为什么要单独处理?受众不同,VIVO、OPPO、小米这些平台用户不同,为了让用户存留时间更久,模型需要分开训练;推荐的限制条件不同,所以也有不同的数据处理。

其中离线数据的数据源有三种,一种是新产生的短视频,一种是全量回扫的短视频,一种是属性更新需重新计算的短视频。三种数据源对应三个 Kafka Topic,均是由其他部门写入,我们读取数据进行处理。离线数据属性的存储从数据的使用方向又可以被分为候选数据、正排数据、倒排数据。候选数据用于推荐的候选阶段,这个阶段将所有的视频都作为输入,获得一个初步的推荐结果,如 3000 个。正排数据用于推荐的正排阶段,这个阶段在初步的推荐结果的基础上,进行进一步筛选,获得一个相对精确的推荐结果,如 300 个。同样也用于精排阶段,进一步筛选。倒排主要用于推荐某个特定类别的情况,当前没有用到。

latency 降低原因、staytime 提升原因,怎么量化正向显著,量化指标是怎么生成的,

首先,这些指标是线上服务所使用的指标。

latency 降低的原因在于,之前存储是在两个服务上,现在将其存储到了一个服务上,调用次数降低了。

staytime 降低的原因在于,短视频采用了新的数据回扫流,这个回扫流覆盖的视频量更多,优质内容更多,用户观看时间增加。

指标正向显著:通过假设检验计算出 p 值,如果 p 值小于 0.05,那么认为是正向显著。

指标生成有多种,有的是推荐服务中进行打点,如 latency;有的是上游后端业务方中进行打点。

数据流过程中是如何存储属性的

使用一个 Context 类,类内通过 ConcurentHashMap 存储。

HR 面介绍

学习一门技术:技术的官方和非官方文档、Github 中搜索该技术的最佳实践、询问有经验的同学。 例如,训练营的第 8 期的任务是完成一个选课系统,而这个选课系统严格规定使用 go 语言实现。 因此,我去寻找了 go 语言的编程文档、寻找了常见的 go 语言后端使用的框架,即 gin 和 gorm 框架、并找到对应的官方文档。对于建立搭建整个后端的服务,在 github 中寻找了基于 gin 和 gorm 的项目参考。期间发现项目的项目目录结构并非统一,经过询问同学和搜索,确定 go 确实没有专门的统一目录格式。因此参考了多个项目定下来一个比较合理的项目目录结构。之后就是一点点学习如何完成一个基本的后端服务。