Download code/speaker_v5/common.py from laion/tyger-speaker-predictor: direct link, hf CLI and curl.
- Browser
- Download file 6.34 kB
-
https://huggingface.co/laion/tyger-speaker-predictor/resolve/main/code/speaker_v5/common.py
- Command line
-
hf download hf://laion/tyger-speaker-predictor/code/speaker_v5/common.py
-
curl -L -o common.py https://huggingface.co/laion/tyger-speaker-predictor/resolve/main/code/speaker_v5/common.py
6.34 kB
| import html,json,os,shutil,time | |
| from pathlib import Path | |
| from speaker_v4.common import OLD,atomic,digest | |
| ROOT=Path(__file__).resolve().parent | |
| WORK=Path.home()/'.cache/robo-v5' | |
| SEEDS=(2021,2022,2023) | |
| CONTEXTS=(4,25,38) | |
| ARMS={'utterance':(0.,None),'stable20':(.2,None),'hard':(0.,'hard'), | |
| 'stable20_hard':(.2,'hard'),'stable20_random':(.2,'random')} | |
| def guard(cache=None): | |
| if (ROOT/'STOP').exists():raise RuntimeError('V5 STOP requested; retained epoch checkpoints are resumable') | |
| WORK.mkdir(parents=True,exist_ok=True) | |
| if shutil.disk_usage(WORK).free<3*1024**3:raise RuntimeError('Persistent work volume below 3-GiB reserve') | |
| if cache is not None and shutil.disk_usage(cache).free<8*1024**3:raise RuntimeError('Temporary feature volume below 8-GiB reserve') | |
| def update(**fields): | |
| path=ROOT/'progress.json';state=json.loads(path.read_text()) if path.exists() else {'started':time.time()} | |
| state.update(fields,updated=time.time());atomic(path,state) | |
| WORK.mkdir(parents=True,exist_ok=True) | |
| with (WORK/'events.jsonl').open('a') as out:out.write(json.dumps({'time':time.time(),**fields})+'\n') | |
| def report(results=None): | |
| if results is not None:atomic(WORK/'results.json',results) | |
| else:results=json.loads((WORK/'results.json').read_text()) if (WORK/'results.json').exists() else {} | |
| table=[] | |
| for key,group in results.get('aggregates',{}).items(): | |
| def value(split,metric,scale=1): | |
| v=group.get(split,{}).get(metric) | |
| return 'Pending' if v is None else f"{v['mean']*scale:.3f} ± {v['std_across_seeds']*scale:.3f}" | |
| table.append('<tr>'+''.join('<td>'+html.escape(str(v))+'</td>' for v in [key,group['seeds'], | |
| value('validation','macro_speaker_accuracy',100),value('test','macro_speaker_accuracy',100), | |
| value('test','eer',100),value('test','source_utterance_teacher_cosine'),value('test','positive_cosine'), | |
| value('test','impostor_cosine'),group.get('student_gpu_batch1_ms','Pending')])+'</tr>') | |
| status=json.loads((ROOT/'progress.json').read_text()) if (ROOT/'progress.json').exists() else {} | |
| body='''<!doctype html><html lang="en"><meta charset="utf-8"><meta name="viewport" content="width=device-width"><title>Speaker context optimization: 320 ms, 2 s, 3 s</title> | |
| <style>body{font:16px/1.6 system-ui;max-width:1200px;margin:35px auto;padding:20px;background:#faf8f3;color:#403a30}td,th{padding:9px;border-bottom:1px solid #ccc;text-align:left}.scroll{overflow:auto}pre{white-space:pre-wrap;font-size:12px}</style> | |
| <a href="/speaker-training/">Training overview</a> · <a href="/speaker-training/320ms-study/">320-ms layer/hard-negative study</a> | |
| <h1>Context-specific speaker prediction</h1><p id="phase">'''+html.escape(status.get('phase','Queued'))+'''</p> | |
| <p>Dedicated training at 320 ms, 2000 ms and 3040 ms (4, 25, 38 frames). A nominal three-second window rounds up to 3.04 s on the native 80-ms grid. Each prediction still identifies the current/newest 320-ms speaker, NOT the majority speaker over the longer context. Every hidden state already sees causal history from the same original eight-second encoder input; these are not cold-start audio-duration limits.</p> | |
| <p>Matched 480/10/10 synthetic speaker split, 96,000 training and 10,000 validation/test windows each, three paired seeds per condition. Warm start is the same frozen V3 Query-GRU, not a different per-context winner. Compare utterance-only targets, 20% stable training-centroid loss, hard cross-emotion/near-speaker pairs, stable+hard, and a compute-matched stable+random-pairs control. No layer mixing is added here, isolating duration and training recipe. The preceding lower-layer study is retained separately.</p> | |
| <p>Each checkpoint is selected on its own context's validation objective: macro accuracy − 0.5 EER + 0.1 source-utterance cosine. All configurations and context winners are frozen before new test evaluation. These ten synthetic test identities were benchmarked previously; this is a repeated benchmark, not a new independent human population. Genuine and impostor cosine are both reported. No microphone recordings or enrolled-user embeddings are used.</p> | |
| <h2>Summary</h2><p>Mean ± SD across seeds, not a confidence interval across people. Pending test cells are not results. Latency is student-only batch 1, excluding Nemotron.</p><div class="scroll"><table><tr><th>Context / recipe</th><th>Seeds</th><th>Val accuracy %</th><th>Test accuracy %</th><th>Test EER %</th><th>Utterance cosine</th><th>Enrollment cosine</th><th>Impostor cosine</th><th>GPU ms</th></tr>'''+''.join(table)+'''</table></div> | |
| <h2>Findings</h2>'''+''.join('<p>'+html.escape(v)+'</p>' for v in results.get('conclusions',[]))+''' | |
| <h2>Speaker changes and storage</h2><p>Accuracy is also separated by time since the current source utterance began (<320 ms, 320–640 ms, 640–1000 ms, ≥1 s). These are onset/re-entry slices, not proof of clean single-speaker intervals or a measured gate-response delay. Silence and ambiguous overlap retain their own activity labels, without speaker-regression targets. Paired identity bootstrap comparisons average seeds before resampling identities.</p> | |
| <p>The existing 25-frame cache is reused read-only. Only the missing 13 older L15 frames and energy are cached for the exact same windows, in bounded temporary RAM (~1.55 GB). The suffix must match original 25-frame features at cosine ≥0.995. Source audio is replayed from pinned public clips, not downloaded again. The worker waits for the earlier study to release GPU 0; live TTS on GPU 1 is untouched. Models/results persist on disk; the regenerable RAM cache can be lost on reboot. No automatic live identity-filter promotion.</p> | |
| <h2>Live progress</h2><pre id="progress">'''+html.escape(json.dumps(status,indent=2))+'''</pre><h2>Protocol and complete results</h2><pre>'''+html.escape(json.dumps(results,indent=2,allow_nan=False))+'''</pre> | |
| <script>async function poll(){try{let s=await fetch('/api/speaker-v5',{cache:'no-store'}).then(r=>r.json());document.getElementById('phase').textContent=s.phase;document.getElementById('progress').textContent=JSON.stringify(s,null,2)}catch{}}setInterval(poll,15000)</script></html>''' | |
| WORK.mkdir(parents=True,exist_ok=True);p=WORK/'report.tmp.html';p.write_text(body);p.replace(WORK/'report.html') | |