Meta 这个“预测观众反应”的模型,厉害在哪?
你刷到一个视频,3 秒内会发生什么?
- 直接划走
- 继续看
- 看完还想评论/转发
- 甚至有点“上头”
Meta 这类研究在做的事,就是把这些“人类反应”变成可学习的信号,然后让模型在你发视频之前就给个分:这条大概率能留人,还是会被秒划。
这事听着玄,其实落地路径很朴素:
用视频编码模型把内容变成向量 → 用真实数据(完播、停留、点赞)当标签 → 训练一个回归/分类头 → 得到“吸引力分数”。
下面我按“你真要做一个能用的系统”的角度讲,尽量不绕。
你要预测的“反应”,到底选哪个?
别一上来就喊“兴奋度”。兴奋这词太虚,数据也很难干净。
更实用的做法:选你平台上拿得到、且能代表“值得看”的指标。
常见选择(从容易到难):
- 3 秒留存率:能不能扛过开头
- 完播率:能不能让人看完
- 平均观看时长:更细一点的“黏住能力”
- 互动率:点赞/评论/转发
- 负反馈率:不感兴趣、拉黑、举报(这个非常值钱)
建议你直接用一个综合分,省得模型学偏:
AttractScore = 0.5 * 完播率
+ 0.3 * 标准化观看时长
+ 0.2 * 互动率
- 0.4 * 负反馈率
系数怎么定?别纠结,先拍一个“差不多”的版本跑起来,后面用线上 A/B 再调。
数据怎么来:别做“完美数据梦”😅
你需要两样东西:
- 视频本体:文件或可下载链接
- 观众反应标签:你要预测的那个指标
数据来源建议
- 你自己的账号历史视频 + 对应的后台数据(最香)
- 公共数据集(只适合练手,不太贴合你的内容分布)
样本量要多少?
真相:越多越好。
但如果你只是想做个可用 MVP:
- 500 条:能看到一点趋势
- 2,000 条:开始像样
- 10,000 条:才有“稳定感”
内容跨度越大(搞笑、美食、剧情、带货混一起),需要的数据就越多。
模型结构怎么搭:别自己从零训视频大模型
你要的是“预测反应”,不是“发明视频基础模型”。
最稳的套路:
- 用开源预训练视频模型抽特征(冻结)
- 上面接一个很小的预测头(MLP/线性层)
- 训练这个小头,输出你的 AttractScore
你可以用哪些视频编码器
- VideoMAE:很常用,特征质量不错
- TimeSformer:经典 Transformer 视频模型
- CLIP 系列(图像帧 + 文本):你有标题/文案时很划算
你会发现一个现实:
只用画面有时候不够,配上 标题、字幕、封面,分数会明显更准。
可执行的训练流程(按你能照着做的版本来)
1)切片:别把整条视频喂进去
大部分“秒划/留存”都发生在开头。
建议你对每条视频抽几段:
- 0–3 秒(开头生死线)
- 3–8 秒(节奏是否跟上)
- 随机 1 段(防止模型只学开头套路)
2)抽帧:别抽太密
一个实用配置:
- 采样 8–16 帧
- 帧率 1–2 fps
- 分辨率 224 或 256
3)训练:回归比分类更爽
你要的是一个连续分数,回归更贴合。
- Loss:MSE / Huber
- 指标:Spearman(看排序能力)比 MAE 更有意义
4)输出:给运营看的不是 loss,是排序
你最终要的结果是:
同一个选题的 A/B/C 三个版本,模型能告诉你哪个更容易留人。
所以评估方式建议用:
- Top-K 命中率:你挑分数最高的 10 条,线上是不是更好
- 排名相关系数:Spearman / Kendall
代码骨架(PyTorch 思路版)
下面是“特征抽取 + 小头训练”的骨架,帮助你把工程跑起来。
说明:不同编码器的输入格式差异很大,这里写的是结构,别照抄参数就硬跑。
import torch
import torch.nn as nn
class AttractHead(nn.Module):
def __init__(self, in_dim=768):
super().__init__()
self.mlp = nn.Sequential(
nn.Linear(in_dim, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, 1)
)
def forward(self, x):
# x: [B, in_dim]
return self.mlp(x).squeeze(-1)
# 伪代码:video_encoder 输出一个向量
# video_encoder 冻结,只训练 head
for p in video_encoder.parameters():
p.requires_grad = False
head = AttractHead(in_dim=768).cuda()
opt = torch.optim.AdamW(head.parameters(), lr=3e-4)
loss_fn = nn.HuberLoss(delta=1.0)
for batch in loader:
frames, y = batch # frames: [B, T, C, H, W]
frames = frames.cuda()
y = y.cuda().float()
with torch.no_grad():
feat = video_encoder(frames) # [B, 768]
pred = head(feat)
loss = loss_fn(pred, y)
opt.zero_grad()
loss.backward()
opt.step()
上线时也简单:
- 你剪辑完导出 3 个版本
- 系统自动抽帧打分
- 分数最低的直接回炉重剪,省得发出去被“秒划”
这能让你少走很多冤枉路。
让分数更准的 5 个小技巧
1)把“封面/首帧”单独建一个分支
很多平台的点击来自封面。
做法:
- 封面走图像编码器(比如 CLIP image encoder)
- 视频内容走视频编码器
- 两个特征拼起来再预测
2)加上文本:标题、字幕、口播转写
人不是只看画面,大家也看字。
做法:
- ASR 转写(Whisper 之类)
- 文本编码器(BERT/Chinese-RoBERTa/CLIP text)
3)同题材分桶训练
美食和剧情的“好看”完全不是一个东西。
做法:
- 先用简单规则或标签把内容分桶
- 每个桶一个 head,或者一个模型加上“题材 embedding”
4)别只学“高互动”,要把负反馈压住
很多低质猎奇内容互动很高。
你如果不加负反馈项,模型可能会给“标题党/擦边”更高分。
5)做“版本对比”训练,效果会更像人
比起预测绝对分数,训练模型学“哪个更好”更符合真实决策。
做法:
- 同选题 A/B 两条,标签用线上真实胜负
- 用 pairwise ranking loss(比如 hinge loss)
避坑清单(踩一个你就想骂人)🧨
- 数据泄漏:把“发布时间、账号粉丝量、投流金额”喂给模型,它会学会“谁更有钱谁更爆”,你还以为模型懂内容
- 标签不稳:刚发 30 分钟的数据拿来当真,波动大到离谱。给数据一个冷却期,比如 24–72 小时
- 只看均值不看分布:一条视频可能“爱的人很爱,恨的人很恨”。建议同时预测负反馈
- 训练集全是你的老风格:你换赛道模型直接瞎。换风格要补数据
- 把分数当圣旨:模型是筛选器,不是导演。分数是参考,最终还得看内容逻辑
你可以怎么用它:一个很实在的工作流
给你一个剪辑团队能执行的流程:
- 同一条素材,剪 3 个开头(0–5 秒节奏不同)
- 跑“吸引力评分器”
- 分数最低的版本直接删掉
- 分数最高的版本再做人工检查:信息是否清晰、有无误导、是否踩平台规则
- 发出去后看真实数据,把结果回流到训练集
你会明显感觉到:
- 低级失误少了(开头无聊、信息太慢)
- 每天少浪费几小时在“发了才知道”
一句话回答原问题:爆款能提前算出来吗?
能算“更像爆款的概率”,算不出“保证爆款”。
爆不爆还受很多非内容因素影响:发布时间、推荐池、竞争视频、热点、评论区发酵。
模型真正值钱的点是:
在你发布前,把明显留不住人的版本筛掉,让你更少做无用功。
如果你愿意,我也可以按你的内容类型(剧情号/带货/知识科普/游戏/美食)给你一套更贴的标签设计和特征方案,把“评分器”变成你账号的私有外挂。