Pooling 方法说明

解释 pooling_vs_mos_en.html 里每个 temporal pooling rule 是什么,以及这次 DSIS pilot 用的参数是怎么来的。 代码来源:规则在 VQA2-gmad-pooling/gmad/temporal_pooling_snapshot.py(与 VQA2/temporal_pooling.py 相同的快照), 调用参数在 gmad/run_selection.py 的 predict(),实际运行配置记录在 results/gmad_all_shots_480p720p1080p_skip_negative_no_offset_time_converted/config.json。 文献出处与原始参数见 VQA2/temporal_pooling_rules.md。

1. 所有规则共用的输入

因为视频只有 4.5 s,而很多文献参数是为 8–10 s 片段甚至几分钟的 streaming session 设计的,几个规则在这种时长下会退化成 mean。 这就是结果页里 “mean = last_frames_mean = cumulative_quality” 和 “median = kth_percentile” 的原因,下面逐条说明。

2. 一览表

最后一列是结果页的主指标(各 scene SRCC 按 n − 3 加权在 Fisher z 空间平均),按它排序。只有 7 位被试、84 条视频,差距大多在噪声范围内,仅供参照。

规则一句话本次参数来源加权 SRCC
increasing_weights三个 chunk 权重 1 : 2 : 3(越后越重)n_segments = 3Duanmu 20180.622
exp_weighted_minkowski指数近因权重 + Minkowskip = 2, τ = 480 帧 (4 s)Rimac-Drlje 20090.613
decreasing_weights三个 chunk 权重 3 : 2 : 1(越前越重)n_segments = 3Duanmu 20180.585
minkowski(mean qp)1/pp = 2Rimac-Drlje 20090.569
hysteresis记忆(过去最差)+ 当前(未来窗口偏向最差)τ = 2 s (240 帧), α = 0.8Seshadrinathan & Bovik 20110.568
worst_window滑动平均的最小值N = 480 帧 (4 s)Rimac-Drlje 20090.566
mean = last_frames_mean = cumulative_quality算术平均—多篇0.564
vqpooling_temporal2-means 分高低两组,好帧组降权无可调参数Park 20130.555
combined_jod(参照)CVVDP 对整段视频自己的打分CVVDP 默认Mantiuk 20240.529
median = kth_percentile中位数k = 50Eswara 2020 / Rimac-Drlje 20090.511
percentile最差 5% 帧的平均p = 5%(约 27 帧)Park 2013; Bampis 20170.429
early_dominance只看第 1 个 chunkn_segments = 3Duanmu 20180.411
late_dominance只看第 3 个 chunkn_segments = 3Duanmu 20180.399

3. 时间权重对比

纯加权平均类规则可以画成“每一时刻占多少权重”。横轴是 4.5 s 视频,竖线是 chunk 边界。 exp_weighted_minkowski 的三段权重约为 0.22 / 0.32 / 0.46,和 increasing_weights 的 0.17 / 0.33 / 0.50 很接近——这两个规则在结果页排前两名,说明的是同一件事:后面的 chunk 权重大一些更贴近 MOS。

纵轴是相对每帧权重(mean 每帧 = 1)。exp_weighted_minkowski 画的是 p 次方之前的权重 exp((t − T)/τ),已归一化。

4. 参数大白话

每个参数其实都在回答一个问题:“观众更记得哪些帧?”是差的帧、好的帧、最后几秒,还是某一段。下面用一个玩具例子说明: 一条视频三段,质量分别是 10, 10, 2(JOD,越高越好),普通平均 = 7.33。

Minkowski 的 p:数值大的帧和数值小的帧谁说了算

先把每个分数取 p 次方,平均以后再开 p 次方根。p 次方会把差距放大或缩小,所以 p 决定了往哪一边偏:

p10, 10, 2 的结果大白话
→ −∞2只看最差的那一帧
−14.29明显被差帧拉低(调和平均)
0.56.65稍微偏向差帧
17.33就是普通平均
2(本次)8.25稍微偏向好帧
49.04差帧几乎不算了
→ +∞10只看最好的那一帧

p 越大 = 分数越高的帧越占主导。论文里输入是失真(越高越差),所以“p 大”等于“盯着最差的帧”,表达的是“一次卡顿/模糊就毁掉印象”。 我们的输入是 JOD(越高越好),方向反过来了:p = 2 其实是在原谅差帧。想表达“人记仇”,在 JOD 上要用 p < 1。 不过我们的 JOD 大多集中在 7–10,差距不大,所以 p = 2 和平均几乎一样。

exp_weighted_minkowski 的 τ:观众的“记忆有多长”

每帧的权重是 exp((t − T)/τ):最后一帧权重 1,往前每过 τ 帧权重变成原来的 37%。

  • τ 很小(比如 1 s = 120 帧):前面的几乎全忘了,第一帧权重只有最后一帧的 1%,基本只看最后一段。
  • τ 很大:所有帧差不多一样重,退回普通平均(或普通 Minkowski)。
  • 本次 τ = 4 s:视频只有 4.5 s,第一帧权重是最后一帧的 1/3,三段大约 22% / 32% / 46%,即“最后一段稍微更重要”。

p 在这个规则里的含义和上面一样。

last_frames_mean 的 F:“只看最后几秒”的那个几秒

F 越小,越只看结尾(近因效应越强);F ≥ 视频长度就是普通平均。论文说的是“最后 5 s 决定印象”,但我们的视频总共才 4.5 s,所以“最后 5 s”就是整条视频。 如果想在这里测近因效应,F 应该取 1 个 chunk(180 帧),这就等于 late_dominance。

worst_window 的 N:多长的“最差片段”才算数

在视频里找连续 N 帧平均最差的一段,用它代表整条视频。

  • N = 1:最差的单独一帧,一闪而过的瑕疵也会被抓住,最严格。
  • N 越大:短暂的差帧被周围的好帧冲淡,越宽容;N = 视频长度就是平均。
  • 本次 N = 4 s:占了视频的 89%,只是在“去掉开头半秒”和“去掉结尾半秒”之间选差的那个,所以和平均很接近。如果 N = 1 个 chunk,它就成了“最差那个 chunk 的平均”。

percentile 的 p%:只看最差的百分之多少

把帧从差到好排好,只取最差的 p% 求平均。p 越小越苛刻:p = 5% 只看最差的 27 帧(约 0.23 s);p = 100% 就是平均。 它表达的是“观众记住的是最难看的那一下”。在我们的数据里排名靠后,说明观众并不是只记最差的那 0.2 秒。

kth_percentile 的 k:排在第 k% 位置的那一帧

和上面类似,但不是求平均,而是直接取一个位置的值。k 小 = 看差帧,k = 50 = 中位数,k 大 = 看好帧。本次 k = 50,所以就是中位数。

hysteresis 的 τ 和 α:“记仇多久”和“多记仇”

每一时刻的感受 = α × 当前看到的 + (1 − α) × 过去 τ 秒里最差的那一刻。

  • τ(记仇多久):一次质量下降在记忆里留多久。τ 大,掉一次质量会影响后面很长一段时间;τ 小,很快就“原谅”了。本次 2 s,大约一个多 chunk。
  • α(多看眼前,还是多记过去):α = 1 完全不记仇,只看当前;α 越小,过去最差的那一刻越拖累现在。本次 α = 0.8,即 80% 看眼前,20% 记着刚才最差的。
  • 另外“当前”那一项本身也偏向差帧:它看接下来 τ 秒的帧,最差的那几帧权重最大。所以这个规则整体是“对下降敏感、恢复慢”。

vqpooling 的 w:自动决定好帧算多少

没有要手动设的参数。它把帧分成“差的一组”和“好的一组”,差组永远全算,好组乘一个权重 w = (1 − 差组均值/好组均值)²:

  • 两组差不多(比如 9.5 和 10):w ≈ 0,好组几乎不算,结果 ≈ 差组均值。意思是:差别不明显时,取偏差的那一边作为保守估计。
  • 两组差很多(比如 2 和 10):w = 0.64,好组也算进来,结果更接近平均。

因为看的是“比值”,如果给所有分数加上同一个常数,结果会变,所以所有规则必须用同一个输入(本次没有加偏移)。

early / late / increasing / decreasing 的权重:三个 chunk 各占几成

就是给三个 chunk 分配“话语权”:

  • early_dominance [1, 0, 0]:只看第一印象。
  • late_dominance [0, 0, 1]:只看最后印象。
  • increasing_weights [1, 2, 3]:17% / 33% / 50%,越后越重。
  • decreasing_weights [3, 2, 1]:50% / 33% / 17%,越前越重。

例子 10, 10, 2:early = 10,late = 2,increasing = 5.67,decreasing = 8.67。同样三段,只因为差的在最后,increasing 就比 decreasing 低 3 分。

cumulative_quality 的四个权重:最后、平均、最差、最好各占几成

0.28 × 最后一段 + 0.426 × 整体平均 + 0.28 × 最差一段 + 0.014 × 最好一段。大白话:平均印象占四成多,结尾和最差的时刻各占约三成,最好的时刻几乎不算 (人对好的记不住、对坏的和结尾记得住)。但这里的“一段”是 50–60 s,我们的视频只有 4.5 s,四项都是整体平均,所以就是平均。

5. 逐条说明

记号:q[t] 是第 t 帧的 JOD,t = 1…T(T ≈ 540)。

combined_jod 参照,不是 pooling rule

CVVDP 对整段 4.5 s 视频直接给出的 JOD。CVVDP 内部的时间池化是在失真响应上做 L2(βt = 2),然后再映射到 JOD; 而其它规则都是先把每帧转成 JOD 再池化。所以它和 minkowski、mean 很像但不完全相同。用来回答“直接用 CVVDP 行不行”。

mean = last_frames_mean = cumulative_quality

Q = (1/T) Σ q[t]

基线。多篇文献(Duanmu 2018、Bampis 2017、Seshadrinathan & Bovik 2011)发现 mean 很难被稳定超越。无参数。

last_frames_mean 退化为 mean

Q = (1/F) Σ_{t = T−F+1 … T} q[t] (只看最后 F 帧,近因效应)
F = 600 帧
论文(Rimac-Drlje 2009)扫了 F ∈ {50…300} 帧,在 25 fps 下 F = 125 帧(5 s)最好,结论是“最后 3–7 s 主导判断”。换算到 120 Hz:125 × 4.8 = 600 帧。
600 帧 > 视频总长 540 帧,所以“最后 5 s”就是整条视频,结果和 mean 完全一样。要让它有意义得改用更短的窗口(例如最后一个 chunk = late_dominance)。

cumulative_quality (CQM) 退化为 mean

CQM = 0.280·WQ_last(50 s) + 0.426·WQ_avg(60 s) + 0.280·WQ_min(50 s) + 0.014·WQ_max(50 s)

Tran et al. 2021,为几分钟的 streaming session 设计:在 1 s 片段上滑动长度 K 的窗口,组合“最后一个窗口”(近因)、“所有窗口平均”、“最差窗口”(peak-end)和“最好窗口”。 权重和窗口长度是论文在 36 段 6 分钟序列上拟合的值,原样使用。

50 / 60 s 窗口远长于 4.5 s,每个窗口都覆盖整条视频,四项都等于整体平均,权重和为 1,所以 CQM = mean。 另外原实现按 1 s 切片时最后半秒会被当成一整段(偏差最大 0.39 JOD),run_selection.py 直接用按帧时长加权的 mean 代替来避免这个偏差。

median = kth_percentile

Q = q 的中位数

对少数异常帧更稳健。Eswara 2020 用它来汇总连续 QoE 预测。无参数。

kth_percentile 退化为 median

Q = q 分布的第 k 百分位
k = 50
函数默认值。Rimac-Drlje 2009 扫过 k ∈ {10…97},最优 k 取决于指标方向:质量类分数 SSIM 为 60、PSNR 为 10;失真类分数取高 k。
k = 50 就是中位数,所以与 median 完全相同。如果想测试“偏向最差”的版本,应该用较小的 k(例如 10),这次 pilot 没有做。

percentile

Q = 最低 p% 帧的平均
p = 5%
Bampis 2017 和 Park 2013(剩余帧权重 r = 0 时)都用 5%;Moorthy & Bovik 2010 用 6%。540 × 5% → 27 帧 ≈ 0.23 s。

只看最差的一小段,代表“worst-case / peak impairment”。在我们的数据里它几乎只反映最差那个 chunk 里最差的那几帧,排名靠后。

minkowski

Q = ( (1/T) Σ q[t]^p )^(1/p)
p = 2
函数默认值。Rimac-Drlje 2009 扫了 p = 1…12,最佳值随指标不同(SSIM 3、MSE 2、VQM 10、PSNR 12)。
论文里 p > 1 是作用在失真分数上,用来放大最差帧。我们的输入是质量分数(越高越好),p = 2 反而略微偏向好帧;要强调差帧需要 p < 1。 实际上 p = 2 与 mean 的 Spearman 相关为 0.997,几乎就是 mean。

exp_weighted_minkowski

Q = ( Σ w[t]·q[t]^p / Σ w[t] )^(1/p), w[t] = exp((t − T)/τ)

在 Minkowski 上加指数近因权重:越靠后的帧权重越大。

p = 2
函数默认(与 minkowski 一致;p 的方向问题同上)。
τ = 480 帧
默认 τ = 100 帧(论文中 SSIM / MSE 的最佳值),在 25 fps 下是 4 s,换算到 120 Hz:100 × 4.8 = 480 帧。 这样第一帧的权重是最后一帧的 exp(−539/480) ≈ 0.33。
normalize = True
论文公式用 1/T 归一化,会让结果随 τ 变小;实现改为除以权重和,使输出保持在 JOD 尺度上。

worst_window

Q = min_i (1/N) Σ_{j=0…N−1} q[i + j] (最差的连续 N 帧的平均)
N = 480 帧
默认 N = 100 帧(Rimac-Drlje 扫过 1…160 帧),25 fps 下 4 s,换算为 480 帧。
4 s 窗口占了 4.5 s 视频的 89%,只有约 60 个可选位置,差别只在“去掉开头 0.5 s 还是结尾 0.5 s”,所以结果非常接近 mean。

hysteresis

memory x(t) = min q[t−n … t−1] (过去 τ 秒的最差值;x(1) = q[1]) current y(t) = Σ v_k·w_k (v = q[t … t+n] 升序排列,w = 半高斯,最差的权重最大) g(t) = α·y(t) + (1 − α)·x(t) Q = mean_t g(t)

来自连续打分实验:人对质量下降反应快、恢复慢。“记忆”项让一次下降的影响延续 τ 秒。

τ = 2 s
论文推荐值(τ 在 1–3 s 内结果稳定)。τ 以秒定义,直接用 fps = 120,所以 n = 240 帧,不需要另外换算。
α = 0.8
论文推荐值(α > 0.5 时结果稳定)。
高斯 σ
(2K − 1)/12,K 为窗口中的帧数,按论文定义。

实现说明:论文 eq.(7) 印成 x(t) = min[x(t)],字面上是常数;按文字描述取过去 τ 秒 q 的最小值。高斯权重归一化为和 = 1。

vqpooling_temporal

1. 用 1-D k-means (k = 2) 把帧分成低组 G_L、高组 G_H,均值 M_L、M_H 2. w = (1 − M_L / M_H)² 3. Q = (Σ_{G_L} q + w·Σ_{G_H} q) / (|G_L| + w·|G_H|)

Park et al. 2013 的时间部分。质量均匀时 M_L ≈ M_H,w ≈ 0,结果≈低组均值;高低差距越大,好帧的权重越大(回到更接近平均)。 没有可调参数(k = 2 是方法本身的定义)。论文中大部分提升来自空间部分,对逐帧向量不适用,这里只用了时间部分。

依赖 M_L / M_H 的比值,所以对输入整体平移敏感。这是为什么所有规则共用同一个(这次为 0 的)偏移。

early_dominance / late_dominance / increasing_weights / decreasing_weights

把视频等分成 n 段,Q = Σ w_i · mean(第 i 段) / Σ w_i
n_segments = 3
Duanmu 2018 原文是两个 4 s 片段,权重分别为 [1,0]、[0,1]、[1/3,2/3]、[2/3,1/3]。我们推广到 3 段,正好对应实验的三个 chunk:
  • early_dominance:[1, 0, 0],只看 chunk 1(首因效应)
  • late_dominance:[0, 0, 1],只看 chunk 3(近因效应)
  • increasing_weights:[1, 2, 3] / 6,越后越重
  • decreasing_weights:[3, 2, 1] / 6,越前越重

“只看一个 chunk”的两条都排最后,说明三个 chunk 都会影响判断;“加权但都保留”的两条都比 mean 好,其中偏后的更好。 注意:去掉负分帧的视频(538/539 帧)等分时边界会偏一两帧,影响可忽略。

6. 怎么调参数(大白话)

上面用的都是文献默认值。gmad/tune_pooling_makeway.py 试了另一种做法:用我们自己的 MOS 把参数调一遍,看能不能变好。 结果在 tuning_makeway/(grid.csv、best_params.csv、test_results.csv)。

第 1 步:分“练习题”和“考试题”

拿 makeway 这一个 scene(19 条视频,pilot 里最多的一个)当练习题,只在它上面调参数。 其余 7 个 scene 的 65 条视频当考试题,调参时完全不看。

为什么不在全部 84 条上调?那等于自己出题自己考:总能找到一组参数在这批视频上分数很高,但换一批视频就不灵了(过拟合)。 分开以后,“考试分数”才说明参数是真的好,还是只是碰巧适合 makeway。

第 2 步:把每个候选值都试一遍(网格搜索)

每个规则准备一张候选值表,逐个代入,算出 19 条 makeway 视频的预测分数,再看预测的排名和 MOS 的排名有多一致(SRCC)。SRCC 最高的那组就是“调好的参数”。 如果两组 SRCC 一样,比 PLCC(线性相关);还一样,就选离默认值最近的那个,免得没有理由地乱改。

规则试了哪些值默认
minkowskip ∈ {−8, −4, −2, −1, −0.5, 0.5, 1, 2, 4, 8}p = 2
exp_weighted_minkowskip ∈ {−4, −2, −1, 1, 2, 4} × τ ∈ {30, 60, 120, 240, 480, 960, 1920} 帧(0.25–16 s),共 42 组p = 2, τ = 480
percentilep ∈ {1, 2, 5, 10, 20, 30, 40, 50, 75, 100}%5%
kth_percentilek ∈ {1, 5, 10, 20, …, 90}50
last_frames_meanF ∈ {30, 60, 90, 120, 180, …, 540} 帧(0.25–4.5 s)600
worst_windowN ∈ {1, 12, 30, 60, 90, 120, 180, 240, 360, 480, 540} 帧480
hysteresisτ ∈ {0.05, 0.1, 0.25, 0.5, 1, 2} s × α ∈ {0, 0.2, …, 1},共 36 组τ = 2, α = 0.8
四个分段规则n_segments ∈ {2, 3, 4, 5, 6, 9}3

候选值的范围特意比默认值宽很多,两个方向都包括(例如 Minkowski 的 p 有正有负,就是为了检查“偏向差帧”和“偏向好帧”哪个更好)。 mean、median、vqpooling_temporal 没有参数可调;cumulative_quality 在 4.5 s 上就是 mean,没有放进来。 同样的流程对 CVVDP 逐帧 JOD、逐帧 VMAF、逐帧 PSNR-Y 各做一遍。

参数对比:默认 vs 调好的

规则参数默认CVVDPVMAFPSNR-Y
minkowskip2282
exp_weighted_minkowskip2442
τ(帧)480192019201920
percentilep(%)5100100100
kth_percentilek50906060
last_frames_meanF(帧)600600600600
worst_windowN(帧)4801809030
hysteresisτ(s)20.120.25
α0.8000.6
early_dominancen_segments3222
late_dominancen_segments3235
increasing_weightsn_segments3242
decreasing_weightsn_segments3222

第 3 步:拿去考试,和默认值比

把调好的参数和默认参数都用在 65 条考试视频上,各算一个 SRCC,差值就是“调参带来的提升”。

第 4 步:提升是真的还是运气(bootstrap)

65 条视频不多,换一批视频提升可能就没了。做法是:从 65 条里有放回地随机抽 65 条,重新算一次“调参后 − 默认”的 SRCC 差,这样重复 2000 次, 取中间 95% 作为区间。区间整体在 0 以上 = 提升比较可信;区间跨过 0 = 说不准,可能只是运气。

结果(CVVDP 逐帧 JOD)

规则默认 → 调好的练习 SRCC考试 SRCC提升 95% 区间
exp_weighted_minkowskip 2→4, τ 480→19200.608 → 0.6590.477 → 0.509[−0.02, +0.08]
minkowskip 2 → 2(没变)0.6530.506—
hysteresisτ 2→0.1 s, α 0.8→00.586 → 0.6390.486 → 0.497[−0.06, +0.08]
percentilep 5% → 100%0.523 → 0.6390.393 → 0.493[−0.02, +0.24]
kth_percentilek 50 → 900.444 → 0.6220.396 → 0.485[−0.04, +0.24]
increasing_weights3 段 → 2 段0.600 → 0.6080.479 → 0.487[−0.01, +0.04]
decreasing_weights3 段 → 2 段0.608 → 0.6230.503 → 0.487[−0.06, +0.02]
early_dominance3 段 → 2 段0.420 → 0.5510.313 → 0.413[+0.02, +0.18]
late_dominance3 段 → 2 段0.496 → 0.5800.413 → 0.437[−0.01, +0.07]
worst_windowN 480 → 1800.603 → 0.6700.486 → 0.409[−0.16, +0.00]
last_frames_mean600 → 600(没变)0.6390.493—
mean(对照)—0.6390.493—

考试 SRCC 是 65 条视频放在一起算的。这里的数字和结果页不能直接比:考试题里没有 makeway,逐帧输入是 cvvdp_combined_version_a/frames 里的完整 540 帧(这 84 条 pilot 视频都没有负分帧,所以去不去掉负分帧都一样)。

怎么读这个结果

  • 练习分涨得多,考试分涨得少,甚至变差。这是过拟合的典型样子。最明显的是 worst_window:在 makeway 上从 0.60 涨到 0.67,到别的 scene 反而从 0.49 掉到 0.41。
  • 几乎所有区间都跨过 0。11 个规则里只有 early_dominance 的提升是可信的,而那只是因为默认的“只看第 1 个 chunk”太极端,改成 2 段后变成“只看前 2.25 s”,离 mean 更近了。
  • 调参后大多“往 mean 靠”。percentile p = 100% 就是 mean;k = 90 只是取一个偏好帧的值;τ = 1920 帧(16 s)让权重几乎一样平;hysteresis 的 τ = 0.1 s 几乎没有记忆。 可以理解为:在 makeway 上,数据并不支持“观众盯着最差的帧”或“强近因效应”,越像平均越好。
  • Minkowski 的曲线很平。在 makeway 上 p 从 −8 到 8,SRCC 只在 0.57–0.65 之间变化,p = 1(平均)是 0.639,p = 2 是 0.653,这点差别在 19 条视频上就是噪声。偏向差帧的 p < 0 反而稍差。
  • 曲线忽高忽低就是噪声。例如 kth_percentile:k = 5 是 0.61,k = 10 掉到 0.51,k = 30 又到 0.59。一个真实的效应不会这样跳,19 条视频太少了。
  • VMAF 和 PSNR-Y 的结论一样:percentile 也被调到 p = 100%(= mean);PSNR-Y 的 percentile 提升可信([+0.06, +0.50]),原因同样是默认的 5% 太苛刻,并不是找到了更好的规则。
一句话:到目前为止,调参的主要作用是把那些“不像平均”的规则拉回到平均附近,没有哪个规则的调参版本稳定地超过 mean。 这只是 1 个 scene 调参、7 位被试的 pilot 结论。更稳妥的做法是 leave-one-scene-out(轮流留一个 scene 做考试,其余用来调参),并等正式实验数据。

7. 参数选择的总结与局限