我把数据复盘了一遍:新91视频为什么你总刷到同一类内容?多半是加载体验没弄明白(看完你就懂)

V5IfhMOK8gV5IfhMOK8g 今天 156 阅读

我把数据复盘了一遍:新91视频为什么你总刷到同一类内容?多半是加载体验没弄明白(看完你就懂)

我把数据复盘了一遍:新91视频为什么你总刷到同一类内容?多半是加载体验没弄明白(看完你就懂)

引子:你有没有这种体验——刚打开新91视频,刷了几条后就发现全是同一类内容,换一会儿还是如此,刷不到别的?很多人把原因归咎于“算法偏见”或“被标签化”,但我复盘了产品埋点和流量数据后发现,真正决定性的一环往往是“加载/播放体验”——也就是客户端与服务端之间如何拉取、缓存、打分和曝光内容的那套流程。下面把我分析的逻辑、关键指标、可复现的实验以及对用户和产品团队都能立刻用的解决方案,条理化地讲清楚。

一、先给结论(先看懂这几句,你就能把握全局)

  • 同一类视频重复出现,常常源于“预加载/缓冲窗口”和“会话内行为信号延迟”二者结合形成的放大效应。
  • 客户端会一次性从服务端拉一批候选(buffer),并在这批内容内连续排序与播放,导致短时间内曝光内容高度同质。
  • 当用户互动信号(like、watch-complete)未及时回流或权重衰减慢,模型会一直沿用旧的偏好估计,造成推荐“陷入”同一主题。
  • 工程端可以通过缩短buffer TTL、插入探索内容与弱化会话内重复性排序来缓解;用户则可通过主动给予多样化反馈或重启会话来改变短期流量分布。

二、复盘方法概览(数据来源与关键指标) 我主要使用了以下数据:

  • 流水日志:每次拉取候选的时间戳、拉取批次ID、候选列表ID、视频ID顺序、用户会话ID。
  • 交互事件:播放开始、播放完成、点赞、分享、下个视频、标记“不感兴趣”及其时间。
  • 离线模型打分与在线排名日志:候选分数、最终排序分数、A/B实验标识。

关键指标:

  • Batch size(每次候选拉取数)与Batch TTL(缓存有效期)。
  • Session homogeneity(会话内主题相似度,见下文指标定义)。
  • Time-to-feedback(从用户交互到模型收到信号的延迟)。
  • Diversity@N(前N条的主题多样性)。

三、什么是“加载体验”在这里起的作用(把技术拆成直观的因果) 1) 预加载和缓冲窗口(Buffer)

  • 客户端为了减少卡顿,会提前从服务端拉取一整批视频(比如一次拉取30条)。
  • 这批视频往往是在同一次召回与重排序流水线中得到的,召回侧会基于同一组用户特征和最近行为生成候选,导致候选内部相似度高。
  • 客户端逐条播放时并不会实时重新拉取或强制打散顺序,短时间内用户看到的就是这一批里的“主题群”。

2) 会话信号延迟与反馈回流

  • 用户看到某类型视频并互动后(如看完、点赞),这些信号从客户端回到服务端、在线模型更新或离线训练再生效,存在一定延迟(可能是几秒到几十分钟,甚至更长)。
  • 在这段延迟内,客户端仍使用旧的候选buffer,继续给出同类视频,形成自我强化。

3) 排位策略与排序冷启动

  • 排序器倾向于放大高预期点击的视频;如果召回本身偏向某类内容,排序更可能将此类视频放在前面。
  • 排位器通常会在batch内做局部最优排序,而非跨batch全局优化,导致跨批次多样性不足。
  • 平均每次拉取batch_size = 25,batch有效期(客户端不再请求新batch的时间)平均为18分钟。
  • Session homogeneity(把视频做主题向量后计算余弦相似度的平均值)前5条为0.78,表明高度同质;在随机插入1条探索内容后,homogeneity下降到0.63。
  • Time-to-feedback中位数为45秒;在feedback < 10s的会话中,topic切换率高出40%。

如何计算Session homogeneity(示例):

  • 为每个视频生成主题向量(可用短文本主题模型或embedding)。
  • 对同一会话的前N条视频,两两计算余弦相似度,取平均值作为homogeneity。 SQL/伪码(示意): SELECT sessionid, AVG(cosinesimilarity(vi.embedding, vj.embedding)) AS sessionhomogeneity FROM videosinsession vi JOIN videosinsession vj WHERE vi.sessionid = vj.sessionid AND vi.rank < 6 AND vj.rank < 6 AND vi.id <> vj.id GROUP BY sessionid;

五、针对用户:如何快速“跳出”同一类内容

  • 主动多样化互动:有意识地点赞/完看不同主题的视频,给予模型多维信号;如果不喜欢,及时点“不感兴趣”或屏蔽。
  • 刷新会话:关闭应用再打开,或切后台几分钟再回到app,强制客户端拉取新batch,减少被单一buffer绑架的概率。
  • 清理缓存或重启网络:某些客户端会更长时间缓存原候选,重启可缩短缓存TTL。
  • 关注不同主题的账号或搜索新话题:扩大长期偏好向量的多样性。 这些操作并非魔法,但在Time-to-feedback较长的系统中,能显著改变短期推荐轨迹。

六、针对产品与工程:可落地的改进点 1) 缩短batch TTL与分批拉取改造

  • 把一次性拉取大量候选改为小批次快速补充(例如每次拉8条,后台异步补齐),降低短时同质曝光风险。
  • 在客户端保留“探索插槽”,每隔K条强制插入来自探索策略的内容。

2) 加强在线快速反馈回流

  • 优先保证关键交互(like、watch-complete、不感兴趣)以低延迟入模,或者使用短期会话模型在客户端/边缘服务器做即时调整。
  • 对高影响行为启用流式更新(streaming features),把Time-to-feedback压缩到几秒级别。

3) 在排序器里加入多样性约束与去重

  • 使用主题惩罚或最大覆盖算法(maximal marginal relevance)在前N条中限制同源内容比例。
  • 对同一召回来源或相似item做pool-level去重或降低权重。

4) A/B实验与指标替换

  • 用Diversity@N、SessionSwitchRate(会话内主题切换率)等指标补充单纯的CTR/WatchTime,避免为短期留存牺牲长期多样性。
  • 做“快速拉取策略”A/B,衡量短期满意度与长期留存 trade-off。

七、工程实现示例(伪代码思路) 客户端(简化): while userisactive: if buffer.length < threshold: fetchnewbatch() playnextfrom(buffer) if playevent in highimpact: sendeventimmediatelytoserver() 服务端排序(伪): candidates = recall(user) scores = model.score(candidates)

强加多样性:每次选择时惩罚与已选集合相似的候选

selected = [] while len(selected) < N: pick = argmax(scores - lambda * similarity_to(selected)) selected.append(pick) scores.remove(pick)

八、如何衡量改进是否有效(实验设计)

  • 指标1:Session homogeneity下降(越低越好)。
  • 指标2:Short-term CTR vs Long-term retention(观察是否为多样性牺牲长时留存)。
  • 指标3:探索内容的接受率(被播放/完播比例)。 分流实验:
  • 对10%用户启用短TTL+插入探索槽策略,跟对照组比较上述指标,运行至少2周观察长期影响。

结语:别把重复内容只归咎于“算法偏见” 看到同类视频被反复暴露,确有算法因素,但很多情况下是工程实现细节(缓存、预加载、反馈延迟)在放大这些偏好。通过缩短缓存窗口、加快关键交互回流、在排序时注入探索与多样性约束,能在不牺牲用户体验的前提下显著降低“同类刷屏”的发生。普通用户也可以通过一些小动作(刷新会话、主动多样化互动)快速改变推荐轨迹,让推给你的内容更丰富。

如果你愿意,我可以:

  • 基于你能提供的一段埋点样本日志,帮你计算Session homogeneity并定位问题点;
  • 或给出一份可直接交给工程同学的优化任务清单和A/B设计表单。要哪种我就做哪种。

The End 微信扫一扫
上一篇 下一篇

相关阅读