# Ambivalence / Hesitancy Recognition in Video ### ABAW 2026 ยท 3rd A/H Challenge ยท BAH dataset [![arXiv](https://img.shields.io/badge/arXiv-2607.11120-b31b1b.svg)](https://arxiv.org/abs/2607.11120) [![Python 3.10](https://img.shields.io/badge/python-3.10-blue.svg)](https://www.python.org/downloads/release/python-3100/) [![PyTorch](https://img.shields.io/badge/PyTorch-EE4C2C.svg?logo=pytorch&logoColor=white)](https://pytorch.org/) *Given a short interview video, decide: does this person show ambivalence or hesitancy?* *Six models, one honest ensemble, one command.* **[๐Ÿ“„ Paper](https://arxiv.org/abs/2607.11120)** ยท **[โšก Quick start](#quick-start)** ยท **[๐Ÿ“Š Results](#results)** ยท **[๐Ÿ“ File map](#file-map)**
--- ## Overview

AMF architecture: three affect-specialised branches (text, visual, audio) feed a reliability-gated fusion module, combined with five other members into an AP-weighted ensemble at a fixed threshold.

Text, video, and audio inputs become affect-specialised features. AMF gates weak channels and predicts A/H. Six members are combined by AP-weighted averaging at a fixed threshold of 0.5. Features that hurt the model (gaze/brow dynamics, prosody, cue supervision) are excluded.

**Public test: 0.731 macro-F1**. --- ## Quick start ```bash # 1. environment conda create -n bah python=3.10 -y && conda activate bah pip install -r requirements.txt # + ffmpeg on PATH, 1 GPU # 2. put the BAH data next to this folder (see "Data layout" below) # 3. everything: features โ†’ training โ†’ ensemble โ†’ report โ†’ submission bash run_all.sh ``` That is the whole pipeline. Seed 42, no hand-tuning, no hidden steps. Resume anywhere: `bash run_all.sh --step 8`. --- ## How it works ``` โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” transcript โ”€โ”€โ–บ โ”‚ text model โ”‚โ”€โ”€โ” โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ face frames โ”€โ–บ โ”‚ video model โ”‚โ”€โ”€โ”ค โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ AP-weighted fixed waveform โ”€โ”€โ”€โ”€โ–บ โ”‚ audio model โ”‚โ”€โ”€โ”ผโ”€โ”€โ–บ average of 6 โ”€โ”€โ–บ threshold โ”€โ”€โ–บ A/H? โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ probabilities 0.5 all three โ”€โ”€โ”€โ–บ โ”‚ fusion ร—2 โ”‚โ”€โ”€โ”ค โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ affect feats โ–บ โ”‚ AMF (ours) โ”‚โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ ``` - **Text** RoBERTa fine-tuned on GoEmotions ยท **Video** VideoMAE on cropped faces ยท **Audio** HuBERT ยท **Fusion** orthogonal + gated-attention variants - **AMF** โ€” our member: FER-ViT face statistics + emotion-wav2vec2 audio + **11 readable hesitation markers** (hedges, filled pauses, "but", repeated words, sentiment flips). A learned gate turns weak channels down. - **ASR-erased time** โ€” a signal we introduce: speech recognisers delete fillers and hesitation pauses from the transcript, but the chunk timestamps keep the time those events took. 16 features built from these gaps form the strongest, most independent non-verbal channel we measured (see the paper). - **The key decision is calibration, not architecture.** Tuning ensemble weights and threshold on the 124-video validation split overfits: it scores 0.741 on validation but only **0.690** on test. Weighting members by AP and fixing the threshold at 0.5 gives **0.731** โ€” that one change is worth more than any model change we tried. ## Results | Setup | Macro-F1 | AP | |---|:---:|:---:| | Ensemble, public test (models trained on train split) | **0.731** | 0.875 | | Ensemble, internal 113-video holdout (all-data models) | 0.814 | 0.907 | Verified end-to-end: a from-scratch rerun of `run_all.sh` reproduces the ensemble to ยฑ0.0001 F1 (individual members may drift ~a point across GPUs/sessions; the near-uniform AP weighting absorbs it). Full ablations (conflict-operator study, per-stream probe, calibration study, what-didn't-help) are in the [paper](https://arxiv.org/abs/2607.11120). --- ## Data layout BAH is EULA-protected โ€” request it from the organisers, then place it **next to** this folder: ``` / โ”œโ”€โ”€ code/ โ† this folder (any name works) โ”‚ โ””โ”€โ”€ run_all.sh, *.py, models/ โ””โ”€โ”€ data/ โ”œโ”€โ”€ Videos//Visite_1/*.mp4 โ”œโ”€โ”€ cropped-aligned-faces/Videos//Visite_1/