| """Table 1 context-window row / Finding 4 — context-window length: mean-pooled layer-9 performance with 15/30/45/60 s of audio.
|
| Uses a 9-layer-truncated WavLM (last_hidden_state == layer-9 output) so 60 s fits an 8 GB GPU, and one
|
| 60 s forward per clip whose prefix means give every shorter cap. Own cache (~35 min extraction on GPU).
|
|
|
| python experiments/exp_window.py
|
| """
|
| import sys
|
| import os
|
| sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), ".."))
|
| import hashlib
|
| import numpy as np
|
| from experiments import common as C
|
| from empathyeval.data.audio import cached_load
|
|
|
| CAPS = [15, 30, 45, 60]
|
| CD = "cache/exp_window"
|
| os.makedirs(CD, exist_ok=True)
|
|
|
|
|
| def cp(w):
|
| return os.path.join(CD, hashlib.md5(w.encode()).hexdigest()[:16] + ".npy")
|
|
|
|
|
| def extract():
|
| import torch
|
| torch.backends.cudnn.deterministic = True
|
| torch.backends.cudnn.benchmark = False
|
| from transformers import AutoFeatureExtractor, WavLMModel
|
| dev = "cuda" if torch.cuda.is_available() else "cpu"
|
| fe = AutoFeatureExtractor.from_pretrained(C.MID)
|
| m = WavLMModel.from_pretrained(C.MID)
|
| m.encoder.layers = m.encoder.layers[:C.LAYER]
|
| m = m.to(dev).eval()
|
| print(f"extracting 60 s layer-9 features on {dev}", flush=True)
|
| wavs = [w for it in C.train_items(2500) for w in (it.good_wav, it.bad_wav)]
|
| wavs += [o.wav for q in C.QS for o in q.options]
|
| for n, w in enumerate(dict.fromkeys(wavs), 1):
|
| if os.path.exists(cp(w)):
|
| continue
|
| y = cached_load(w, C.cfg)[:16000 * CAPS[-1]]
|
| inp = fe(y, sampling_rate=16000, return_tensors="pt").input_values.to(dev)
|
| with torch.no_grad():
|
| h = m(inp).last_hidden_state[0]
|
| np.save(cp(w), np.stack([h[:50 * s].mean(0).cpu().numpy() for s in CAPS]).astype(np.float32))
|
| if n % 500 == 0:
|
| print(f" {n} clips", flush=True)
|
|
|
|
|
| if not os.path.exists(cp(C.train_items(1)[0].good_wav)):
|
| extract()
|
| mem = {}
|
| for i, s in enumerate(CAPS):
|
| def f(w, i=i):
|
| a = mem.get(w)
|
| if a is None:
|
| a = mem[w] = np.load(cp(w))
|
| return a[i]
|
| C.report(f"cap {s:2d}s (mean pooling)", C.answers(f))
|
|
|