Download code/scripts/artifact_metrics.py from maxpicy/mamba-cot-tts: direct link, hf CLI and curl.
- Browser
- Download file 3.95 kB
-
https://huggingface.co/maxpicy/mamba-cot-tts/resolve/main/code/scripts/artifact_metrics.py
- Command line
-
hf download hf://maxpicy/mamba-cot-tts/code/scripts/artifact_metrics.py
-
curl -L -o artifact_metrics.py https://huggingface.co/maxpicy/mamba-cot-tts/resolve/main/code/scripts/artifact_metrics.py
3.95 kB
| # artifact_metrics.py: Completion and prefix WER (truncation kept apart from articulation). | |
| from __future__ import annotations | |
| import sys | |
| from pathlib import Path | |
| import numpy as np | |
| REPO = Path(__file__).resolve().parent.parent | |
| sys.path.insert(0, str(REPO)) | |
| sys.path.insert(0, str(REPO / "scripts")) | |
| def _ops(ref, hyp): | |
| n, m = len(ref), len(hyp) | |
| if n == 0: | |
| return ["I"] * m | |
| if m == 0: | |
| return ["D"] * n | |
| dp = np.zeros((n + 1, m + 1), dtype=np.int32) | |
| op = np.zeros((n + 1, m + 1), dtype=np.int8) | |
| dp[:, 0] = np.arange(n + 1) | |
| dp[0, :] = np.arange(m + 1) | |
| op[:, 0] = 2 | |
| op[0, :] = 3 | |
| op[0, 0] = 0 | |
| for i in range(1, n + 1): | |
| for j in range(1, m + 1): | |
| if ref[i - 1] == hyp[j - 1]: | |
| dp[i, j], op[i, j] = dp[i - 1, j - 1], 0 | |
| else: | |
| c = (dp[i - 1, j - 1] + 1, dp[i - 1, j] + 1, dp[i, j - 1] + 1) | |
| best = min(c) | |
| dp[i, j] = best | |
| op[i, j] = 1 if best == c[0] else 2 if best == c[1] else 3 | |
| out, i, j = [], n, m | |
| while i > 0 or j > 0: | |
| o = op[i, j] | |
| if o == 0: | |
| out.append("="); i -= 1; j -= 1 | |
| elif o == 1: | |
| out.append("S"); i -= 1; j -= 1 | |
| elif o == 2: | |
| out.append("D"); i -= 1 | |
| else: | |
| out.append("I"); j -= 1 | |
| return out[::-1] | |
| def truncation_metrics(reference: str, hypothesis: str) -> dict: | |
| from eval.intelligibility import _normalize, word_error_rate | |
| ref, hyp = _normalize(reference), _normalize(hypothesis) | |
| n = len(ref) | |
| if n == 0: | |
| return {"completion": float("nan"), "prefix_wer": float("nan"), | |
| "trailing_del": 0, "wer": float("nan")} | |
| ops = _ops(ref, hyp) | |
| trailing = 0 | |
| for o in reversed(ops): | |
| if o == "D": | |
| trailing += 1 | |
| elif o == "I": | |
| continue | |
| else: | |
| break | |
| covered = max(0, n - trailing) | |
| prefix_ref = " ".join(ref[:covered]) | |
| pw = (word_error_rate(prefix_ref, " ".join(hyp))["wer"] if covered | |
| else float("nan")) | |
| return {"completion": covered / n, "prefix_wer": pw, | |
| "trailing_del": trailing, | |
| "wer": word_error_rate(" ".join(ref), " ".join(hyp))["wer"]} | |
| def autotune_metrics(wav, sr, flat_cents=5.0, jump_cents=50.0) -> dict: | |
| from score_naturalness_panel import f0_track | |
| f0, _fs = f0_track(wav, sr) | |
| f0 = np.asarray(f0, dtype=float) | |
| v = f0[np.isfinite(f0) & (f0 > 0)] | |
| if v.size < 8: | |
| return {"flat_f0": float("nan"), "jump_f0": float("nan"), | |
| "stair": float("nan")} | |
| cents = 1200.0 * np.log2(v / v[0]) | |
| d = np.abs(np.diff(cents)) | |
| if d.size == 0: | |
| return {"flat_f0": float("nan"), "jump_f0": float("nan"), | |
| "stair": float("nan")} | |
| flat = float((d < flat_cents).mean() * 100.0) | |
| jump = float((d > jump_cents).mean() * 100.0) | |
| return {"flat_f0": flat, "jump_f0": jump, "stair": flat + jump} | |
| def prosody_metrics(wav, sr) -> dict: | |
| from score_naturalness_panel import f0_track | |
| f0, _fs = f0_track(wav, sr) | |
| f0 = np.asarray(f0, dtype=float) | |
| ok = np.isfinite(f0) & (f0 > 0) | |
| v = f0[ok] | |
| if v.size < 8: | |
| return {"f0_sd_st": float("nan"), "f0_rng_st": float("nan"), | |
| "voiced_pct": float("nan")} | |
| med = float(np.median(v)) | |
| st = 12.0 * np.log2(v / med) | |
| return {"f0_sd_st": float(np.std(st)), | |
| "f0_rng_st": float(np.percentile(st, 95) - np.percentile(st, 5)), | |
| "voiced_pct": float(ok.mean() * 100.0)} | |
| if __name__ == "__main__": | |
| full = "good morning i hope you slept well and feel rested today" | |
| print("exact ", truncation_metrics(full, full)) | |
| print("truncated ", truncation_metrics(full, "good morning")) | |
| print("garbled ", truncation_metrics(full, "good morning i hope you slipped " | |
| "wall and fill rusted today")) | |