尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

文生视频评测指标全解:画质、文本对齐、时序与运动

文生视频评测指标全解:画质、文本对齐、时序与运动 做文生视频这行绕不开一个特别拧巴的问题模型跑完一轮训练改了时序注意力、换了一批数据、调了 CFG 权重怎么看这一版到底比上一版强靠肉眼看几个 demo 是最不靠谱的路子因为人眼对动起来的画面宽容度极高只要主体没崩、颜色不糊十几帧循环播放你根本看不出慢速漂移。这时候就得靠文本生成视频相关指标来兜底。我把这两年整理和实际用过的指标体系做一次彻底梳理。内容覆盖画质、文本对齐、时序一致性、运动质量四大类会给到具体的计算逻辑、能直接跑的代码骨架、参数选择的经验值以及在多组实验中反复踩过的坑。适合正在训 T2V 模型的算法同学、需要给模型做上线前评估的工程同学以及想搞明白VBench 分数高是不是真的代表好用的产品同学。不管你是刚接手评测脚本还是已经写过一版想找问题这篇应该都能对上号。1. 文本生成视频的指标为什么要分层看1.1 三个层级画质、文本对齐、时序先说清楚一件事图像生成时代留下来的那套指标搬到视频上会立刻失效一半。原因是视频多了一个时间轴而这个轴上会出现图像里根本不存在的问题——闪烁、形变、主体漂移、运动幅度趋近于零。我把指标体系拆成三层来看。底层是画质与保真关心单帧像不像真实图像代表指标是 FID、FVD、LPIPS、PSNR、SSIM还有近两年常用的 MUSIQ、Aesthetic Predictor 这类无参考质量评估模型。中层是文本对齐关心画面是否真的表达了 prompt代表指标是 CLIP Score、ViCLIP、以及用多模态大模型做的 VQA 式打分。顶层是时序与运动关心帧与帧之间是否连贯、运动是否合理代表指标是光流一致性、动态度、运动平滑度、主体一致性。这三层不是并列关系是有依赖的。底层崩了中层的 CLIP Score 反而可能虚高因为 CLIP 对模糊图像不敏感顶层崩了底层的 FID 也可能看不出来因为 FID 是逐帧统计的帧序完全打乱它也不变。我见过不止一次团队拿着一个 FVD 很漂亮的模型去做人工评测结果用户反馈像幻灯片——这就是只看单层指标的代价。记住一个判断如果一个指标在你打乱帧顺序后几乎不变那它对时序质量就是零信息量。FID、PSNR、SSIM、CLIP Score 逐帧版全部属于这一类。1.2 为什么单一指标一定会骗你做过一段时间评测就会有个体感指标之间经常打架。动态度高的模型主体一致性往往掉时序平滑度高的模型动作经常软绵绵没有力度CLIP Score 高的模型画面容易变成 prompt 里每个名词的静态拼贴。这不是指标设计得不好而是它们各自在优化不同的目标。有个很典型的场景一个模型的 prompt 是一只金毛在草地上奔跑A 模型生成的是金毛几乎不动但毛发光影极佳B 模型生成的是金毛四肢飞快摆动但偶尔多出一条腿。A 的 FVD 和无参考画质分更高B 的动态度和文本对齐更高。你说哪个好没有统一答案取决于你的应用场景是短视频素材还是真实感渲染。所以实操中的正确做法不是找最优指标而是搭一个指标面板每个维度选一到两个代表然后看整体的雷达图形状。后面第 5 节我会给出具体的组合方式。这里先把每一层的细节讲透。2. 画质类指标从 FID 到 FVD 的取舍2.1 FID 的推导与它在视频上的失效点FID 的全称是 Fréchet Inception Distance逻辑是把真实样本和生成样本分别过一遍 Inception-V3在 ImageNet 上预训练取池化层特征各自拟合成一个多元高斯分布然后算两个高斯分布之间的 Fréchet 距离import numpy as np from scipy.linalg import sqrtm def frechet_distance(mu1, sigma1, mu2, sigma2, eps1e-6): FID / FVD 共用的 Fréchet 距离计算 diff mu1 - mu2 # 用 Cholesky 分解求 sqrt(sigma1 sigma2)比直接开方数值更稳 covmean, _ sqrtm(sigma1 sigma2, dispFalse) if np.iscomplexobj(covmean): covmean covmean.real return float(diff.dot(diff) np.trace(sigma1) np.trace(sigma2) - 2 * np.trace(covmean))公式展开就是||μ1 - μ2||² Tr(Σ1 Σ2 - 2(Σ1Σ2)^0.5)。看起来挺数学但理解上可以这么类比均值差衡量生成分布整体偏了多少协方差项衡量生成分布的多样性和覆盖能力。只优化均值项模型会退化成生成同一张平均脸。FID 用在视频上主要有三个失效点。第一Inception 是图像分类网络对运动信息完全无感哪怕是纯静态帧拼成的视频也能拿到好分数。第二它需要足够多的样本才能把协方差估计准一般认为至少 10000 张图像视频上通常采样 2048 个 clip 就已经很吃力了样本量不够时 FID 波动能到正负 10 个点。第三Inception 的特征空间和人类审美之间有偏移一个 FID 优化到极致的模型画质反而可能显得油。2.2 FVD 的正确打开方式FVD 把 Inception 换成了 I3D这是一个在 Kinetics 上预训练的视频动作识别网络输入是固定长度的视频片段。它的计算流程和 FID 完全一致只是特征提取器变了。看起来只是换了个 backbone实际影响非常大。我实测下来最容易出问题的是三个参数采样帧数、输入分辨率、特征提取器权重。常见的 I3D 权重有 Kinetics-400 和 Kinetics-600 两版两者算出来的 FVD 数值差异可以达到 30% 以上。所以你在论文里看到 FVD120和别人报的 FVD450很可能根本不是一回事。采样帧数上早期工作普遍用 16 帧因为 I3D 的原生输入就是 16 帧。但 16 帧对于一个 5 秒、24fps 的视频来说只覆盖了 13%像慢速镜头推进这类运动根本体现不出来。现在比较认可的做法是用 128 帧、分多个 16 帧 clip 提取特征再聚合代价是显存和时间成倍上涨。视频预处理规范上我的经验是参数项常见做法我的建议采样帧数16 帧至少 64 帧按 16 帧切 clip 聚合空间分辨率短边 224统一 resize 到 256 短边再中心裁 224裁剪方式随机裁中心裁避免不同 batch 引入随机性样本量512 个 clip2048 个 clip 起步特征类型最后一层池化用 pre-logits 特征维度更丰富一个特别隐蔽的坑如果你的评测数据是同一个 prompt 生成的多个视频那么这些视频之间高度相关。把相关的样本当独立样本喂给 FVD协方差矩阵会被低估FVD 会异常偏低。处理办法是按 prompt 分组每个 prompt 只留一条最长或最典型的样本。2.3 逐帧 PSNR / SSIM / LPIPS 的定位这三个指标在有参考的评测里才有意义比如做视频超分、视频修复、或者做 latent 空间重建质量评估。文生视频里是没有参考视频的所以一般情况下 PSNR 和 SSIM 用不上。不过有两个例外场景值得提。一是你训了一个从文本生成首帧、再用插帧模型补帧的 pipeline这时你要评估插帧模块的质量就可以用 PSNR 和 SSIM 去对比真实中间帧。二是做 latent consistency 检查把视频编码到 latent 再解码回来看重建误差这时候 LPIPS 比 PSNR 更接近人眼感受因为 PSNR 对亮度偏移极其敏感但对结构失真迟钝。LPIPS 的实现细节里有个常被忽略的点它的 AlexNet 权重是 ImageNet 上训的对纹理细节敏感对颜色偏移不敏感。所以如果你在做色彩相关的消融实验LPIPS 反应会慢半拍。实践中我一般把 PSNR、SSIM、LPIPS 三个一起报让人自己看取舍。3. 文本对齐类指标CLIP Score 与它的进阶版本3.1 CLIP Score 的池化策略与缩放系数CLIP Score 大概是文生视频里被用得最多、也被误用最多的指标。基本形式很简单把视频的每一帧和 prompt 分别编码计算余弦相似度import torch import torch.nn.functional as F import clip device cuda model, preprocess clip.load(ViT-B/32, devicedevice) def clip_score(frames, prompt, scale2.5): frames: List[PIL.Image]prompt: str image_input torch.stack([preprocess(f) for f in frames]).to(device) text_input clip.tokenize([prompt], truncateTrue).to(device) with torch.no_grad(): image_features model.encode_image(image_input) text_features model.encode_text(text_input) image_features F.normalize(image_features, dim-1) text_features F.normalize(text_features, dim-1) # 逐帧算余弦相似度再对整个视频求平均 sim (image_features text_features.T).squeeze(-1) return (scale * sim.mean()).item()这里有几个容易出偏差的地方。缩放系数原始论文里乘了 2.5 是为了让数值范围更接近人类打分习惯但很多开源实现直接不乘导致你看到 0.12 和 0.30 两个数不知道该信谁。报数时一定要写清楚是否乘了系数。池化策略平均池化最简单但会稀释掉少数关键帧的对齐最大池化能捕捉最对齐的那一帧但对噪声敏感我比较推荐前 30% 帧取平均因为大部分文生视频模型的开头帧质量最好尾部容易崩。还有一点CLIP 的文本编码器最大长度是 77 个 token长 prompt 会被静默截断。如果你的 prompt 平均长度超过 60 个 tokenCLIP Score 就已经在测一个不完整的句子了。3.2 视频原生 CLIP 与多模态大模型打分CLIP 是图像-文本对齐模型逐帧平均的做法本质上把它当成了帧级打分器完全丢掉了时间信息。为了补这个短板出现了几个视频原生的对齐方案。一类是视频 CLIP比如 ViCLIP、InternVideo 系列它们是在视频-文本对上训练的直接吃一段视频出特征天然包含时序。这类模型在评估动作类 prompt时优势明显比如一个人从沙发上站起来这种逐帧 CLIP 根本分不出站起来和坐下。另一类是用多模态大模型做 VQA 式打分。做法是把视频按网格抽帧拼成一张图配上问题模板比如这个视频中是否出现了[主体]、视频中的动作是[动作]吗直接让模型回答是或否然后统计正确率。VBench 里的多个维度就是这么做的——主体一致性、多物体、人类动作、空间关系、场景等维度背后是若干 VQA 问题。这套方法的好处是可解释能定位到具体哪个元素没对齐。缺点是依赖大模型本身的能力而且推理成本高。我的经验是VQA 式打分适合做诊断不适合做大规模排序。做模型选型时用它跑一个 200 条的样本集就够了全量评测还是得靠轻量指标。3.3 人工评估MOS 与 Elo 的实操设计任何自动指标都必须有人工评估做锚定否则你不知道 0.02 的 CLIP 提升对应多少人眼能察觉的改善。MOS平均意见分的设计有几个关键点。量表维度要拆开问别让人只打一个总分至少拆成文本相关性画面质量运动自然度三项每项 1-5 分。要给锚点样本先展示几个大家都认可的参考视频作为 5 分和 2 分的基准。要设置陷阱题把同一个视频重复插入两次看评分者的一致性如果两次差超过 1.5 分这个评分者的数据要打折。Elo 更适合做模型间的两两对比。每次随机抽出两个模型对同一 prompt 的输出让评分者选更好的那个或者差不多然后按标准的 Elo 更新公式算分。它比 MOS 的优势是避免绝对分数的漂移不同批次、不同时间的评测结果可以直接放在一起比。代价是需要的人次多一些一般要收集到每个模型对上至少 200 次比较才能稳定。实操上我建议内部迭代用 Elo对外发布用 MOS。Elo 迭代快、不用反复校准标准MOS 更容易被外部理解也更适合写进技术报告。4. 时序与运动指标最容易造假的区域4.1 光流一致性Flow Warping Error这是我最看重的一类指标因为它真的能抓住帧间不连贯。核心思路很直接用光流模型估计第 t 帧到第 t1 帧的运动场然后用这个运动场把第 t 帧 warp 过去看和真实的第 t1 帧差多少。差得越小说明运动越符合光流估计的假设帧间越连贯。import numpy as np import torch from torchvision.models.optical_flow import raft_large, Raft_Large_Weights weights Raft_Large_Weights.DEFAULT flow_model raft_large(weightsweights, progressFalse).cuda().eval() def flow_warping_error(frames): frames: List[np.ndarray]HWC uint8。返回平均 warp 误差越小越好 errors [] for i in range(len(frames) - 1): f1 torch.from_numpy(frames[i]).permute(2, 0, 1)[None].float().cuda() f2 torch.from_numpy(frames[i 1]).permute(2, 0, 1)[None].float().cuda() with torch.no_grad(): flows flow_model(f1, f2) flow flows[-1] # 取最终迭代的光流 warped warp_with_flow(f1, flow) err (warped - f2).abs().mean().item() errors.append(err) return float(np.mean(errors))光流模型的选择很关键。Farneback 这类传统方法速度极快但精度差尤其在大位移场景下会完全失效RAFT 和它的变体精度高得多但显存占用大一段 49 帧的 512 分辨率视频在单卡上跑要几百毫秒。折中方案是用 RAFT 的小模型或者把视频降到 256 分辨率再算光流误差会放大但在做模型间对比时排序基本一致。有个细节要注意warp 误差对遮挡区域天然偏高因为被遮挡的像素在下一帧根本不存在光流也无能为力。所以更好的做法是同时估计一个遮挡掩码只在非遮挡区域统计误差或者直接用现成的 flow warping error 实现。4.2 动态度与运动平滑度动态度衡量视频里到底有没有发生运动。VBench 里的 Dynamic Degree 是用 RAFT 算相邻帧光流幅度统计幅度超过某个阈值的像素比例。阈值一般取 0.5 到 2 像素之间具体要看分辨率。这个指标看起来简单但非常有用。我踩过好几次坑一个模型在 FVD 和 CLIP Score 上全面领先结果一算动态度只有对手的三分之一看视频才发现画面几乎静止只是光影在缓慢变化。这类高质量静态图在自动指标里几乎无敌只有动态度能戳破。运动平滑度的思路是反过来——用插帧模型在相邻两帧中间生成一个中间帧然后比较这个中间帧和真实情况下的对应帧。如果视频本身运动平滑插帧模型生成的中间帧应该和真实中间帧很接近。VBench 里用的是 AMT 或 FILM 做插帧。这个指标对快速运动比较敏感对慢速平移不敏感。动态度和运动平滑度是一对需要同时看的指标。只看动态度模型会倾向于生成剧烈抖动只看平滑度模型会退化成慢动作。理想状态是动态度高、平滑度也高实践中往往要牺牲一点。4.3 主体一致性与闪烁检测主体一致性测的是同一个物体在整段视频里是否保持外观稳定。VBench 的做法是用目标检测或分割模型把主体抠出来然后逐帧提取特征通常用 DINO 或 CLIP计算帧间特征相似度。相似度高说明主体没变形、没换衣服、没变颜色。这里有个实操经验检测框的抖动会污染特征相似度。如果检测框在帧间来回跳即使主体本身完全一致抠出来的特征也会有差异。解决方法是加时序平滑或者直接用分割掩码而不是检测框。另外如果视频里有两个同类物体比如两只猫跟踪算法可能在中途交换 ID导致相似度突然暴跌这时候保守做法是只看主体区域的整体特征不做实例级跟踪。闪烁检测主要针对亮度突变。做法是计算相邻帧在亮度通道上的均值差统计超过阈值的帧对比例。短视频平台上那种忽明忽暗的观感基本就是这个问题。还有一个不太被提及但很影响观感的指标背景一致性。做法和主体一致性类似只是针对背景区域。很多模型能做到主体稳定但背景每帧都在换看久了非常出戏。5. 搭一条可复现的评测流水线5.1 数据与预处理规范评测结果不可复现八成是预处理环节出了问题。我总结了一套固定流程写进配置文件每次评测严格照做。Prompt 集合要固定并版本化。不要每次评测临时从训练集里抽那样前后结果无法比较。建议准备三个集合一个 200 条的快速集用于日常迭代一个 1000 条的标准集用于版本对比一个 2000 条的完整集用于对外发布。每个集合的 prompt 要做长度分布统计确保平均长度和长度方差在合理范围内。随机种子要锁死。包括采样时的 seed、视频生成时的 seed、特征提取时的数据加载顺序。我见过因为 DataLoader 的 shuffle 没关同一份数据跑两次 FVD 差 8 个点的案例。分辨率与帧率统一。把所有模型输出的视频统一到同一分辨率和帧率再喂给指标模型。如果模型 A 出 512x5128fps模型 B 出 720x128024fps直接对比是没有意义的。统一采样到 16fps、短边 256 是个比较通用的选择。样本量要满足统计要求。FVD 这类基于分布距离的指标对样本量敏感2048 个 clip 是比较稳妥的量。如果预算有限至少 512 个并且在报告里标注置信区间。5.2 代码骨架与并行策略整套流水线可以拆成四步生成结果落盘、特征批量提取、指标计算、结果汇总。特征提取是最耗时的一步必须做成可缓存。我的做法是给每个视频算一个内容哈希把特征存成.npz文件路径按模型名/prompt_id/视频哈希.npz组织。重跑指标时先检查缓存命中就跳过。这样调参阶段反复算 FVD 时实际只花几秒。import hashlib import os import numpy as np def video_cache_key(video_path): h hashlib.md5() with open(video_path, rb) as f: for chunk in iter(lambda: f.read(1 20), b): h.update(chunk) return h.hexdigest() def get_feature(video_path, extractor, cache_root./cache): key video_cache_key(video_path) cache_path os.path.join(cache_root, key .npz) if os.path.exists(cache_path): return np.load(cache_path)[feat] feat extractor(video_path) os.makedirs(cache_root, exist_okTrue) np.savez_compressed(cache_path, featfeat) return feat并行上特征提取按 GPU 数量切分数据分片每个进程独立跑指标计算因为涉及协方差矩阵这类全局运算要等所有特征提取完再单进程做。中间用文件系统做同步不要试图在一个进程里同时管 GPU 和全局统计很容易出内存问题。5.3 结果汇总置信区间与显著性只报一个均值是远远不够的。我一般用 bootstrap 重采样来估计每个指标的置信区间从样本里可重复地抽 N 次每次算一遍指标取 2.5% 和 97.5% 分位数作为 95% 置信区间。有了置信区间两个模型的对比就有依据了。如果 A 的 FVD 是 320±15B 是 335±18区间大幅重叠这个差异基本可以认为不显著。反过来如果区间完全不重叠才可以下显著更好的结论。做模型选型时我通常要求至少在三个维度上显著优于基线才认为这一版值得推。结果汇总建议做成一张大表行是模型列是各维度指标每格写均值加减标准差。再加一张雷达图看整体形状。表格里一定要标注每个指标的具体配置版本包括特征提取器、采样帧数、样本量不然三个月后自己都看不懂。6. 踩坑实录与速查表6.1 指标打架时的优先级判断这是我被问得最多的问题两个模型A 的动态度和文本对齐高B 的 FVD 和画质分高选哪个我的判断顺序是这样的。先看应用场景。如果下游是短视频素材动态度和文本对齐优先用户最在意有没有动起来、像不像 prompt 说的如果下游是虚拟场景渲染画质和时序一致优先用户对糊和抖最敏感。再看指标本身的可信度。FVD 这类分布距离指标在小样本下噪声大如果两个模型的 FVD 差异在置信区间内就不要拿它当决策依据。最后看人工评估。自动指标只能过滤掉明显差的版本真正的分水岭还得靠人工两两对比。还有一条经验如果两个模型在自动指标上互有胜负那它们大概率是同一水平这种时候选工程成本低的那个——推理快、显存小、依赖少。6.2 采样参数导致的偏差清单我把容易造成偏差的参数整理成一张表每次评测前对照检查一遍环节易偏差参数后果应对视频生成随机种子同 prompt 结果差异大固定 seed 或每个 prompt 生成多条取均值视频生成CFG 权重影响文本对齐与画质平衡全模型统一且记录取值帧采样采样帧数FVD 差异可达 30%全实验统一报告里写清帧采样采样位置首尾帧比例影响 CLIP Score固定为均匀采样或前 30% 平均特征提取I3D 权重版本数值不可跨版本比较锁死版本写进报告特征提取输入分辨率影响特征分布统一 resize 与裁切策略统计计算样本量小样本下方差大至少 512 clip报告置信区间统计计算数据顺序理论上不影响实现上会有关闭 shuffle固定加载顺序6.3 常见问题速查表下面这些是我在群里、邮件里被问过最多的具体问题直接给结论。QFVD 一直居高不下但肉眼看视频挺好的怎么办先检查 I3D 权重版本是否和参考值一致再检查采样帧数。如果这两项都没问题大概率是评测集和 I3D 预训练数据的域差异太大比如你测的是动画风格I3D 是在真实视频上训的。这种情况 FVD 的绝对值参考价值有限只能用来做相对比较。QCLIP Score 提升很小是模型没改进吗CLIP Score 的噪声本身就比较大同一模型跑两次差 0.005 是正常的。如果提升在 0.01 以上才有讨论价值而且要看是哪个 prompt 子集贡献的提升。建议按 prompt 类别拆开看动作类和场景类的表现经常完全不同。Q动态度算出来很高但视频看着很糊检查是不是运动模糊被算成了动态。光流幅度大不等于运动合理可能是画面剧烈抖动。这种情况结合运动平滑度一起看如果平滑度很低说明是抖动不是运动。Q主体一致性分数高但人眼觉得脸在变把特征提取器换成更细粒度的模型。CLIP 的特征对局部变化不敏感人脸变了但整体配色和构图没变时CLIP 相似度依然很高。人脸场景建议用专门的人脸特征提取器或者直接上 VQA 式打分。Q多个模型的自动指标雷达图几乎一样怎么区分说明你的评测集区分度不够。换更有挑战性的 prompt特别是包含多物体、复杂动作、空间关系的。另外检查评测集里是不是有大量简单场景这类 prompt 所有模型都能过拉不开差距。Q评测跑一遍太慢怎么提速三个方向。一是特征缓存前面讲过的哈希缓存能省掉 80% 的重复计算。二是降低分辨率光流和 CLIP 在 256 短边下和 512 短边的排序结果通常一致。三是分层评测日常迭代只跑 200 条快速集发版前才跑全量。Q开源的评测工具能直接用吗可以但要理解它内部用的模型版本和参数。比如 VBench 内部调用了十几个预训练模型其中任何一个版本变化都会影响结果。建议把关键版本写进你的实验记录最好把权重文件也归档一份。我在实际做评测这件事上体会最深的一点是指标的作用不是给模型打分而是帮你定位问题出在哪一层。FVD 崩了但 CLIP Score 正常问题大概率在画质动态度正常但主体一致性崩了问题在时序建模所有指标都正常但人工评测说不行那说明你的评测集没覆盖住真实场景。把指标当成诊断工具而不是排行榜整个评测流程的价值会完全不一样。最后分享一个习惯每次跑完评测我会挑五条指标最好和五条指标最差的样本亲自看一遍。十次里有七八次能从这十条里看出下一步该改什么。这件事花不了二十分钟但比盯着表格里的数字琢磨一下午有用得多。
返回列表