Files
icassp2027-experiment/docs/easycom_encoder_only.md
T

144 lines
6.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# EasyCom:先跑 encoder-only A / V / AV 对照
复用已经提取的 Qwen 局部编码器特征,不输入 Thinker hidden states,不重提音频或视频,
不创建软链接。原 B1 的 `audio / visual / av` 分别是 **G+A / G+V / G+A+V**;
这里的新结果命名为 `encoder_audio / encoder_visual / encoder_av`,分别只有 **A / V / AV**。
固定训练 Session **4–12(升序,与原 B1 一致)**,测试 **3/2/1**;4 epochs、无 dev,
评测最后一轮。沿用原来的 5Hz 行索引、十个 horizon、LSTR-MCE 和 AP 协议,不改变标签。
## 1. 确定已经验证过的局部特征目录
在 L20 机器更新本次代码后执行。下面从你之前跑完的 `av_seed0.pth` 读取实际路径,
避免猜错目录或混入 bbox 修正前的旧视觉特征;checkpoint 仅用于找路径,不作为新模型输入。
```bash
cd /data1/yfzx/wangx/Code/icassp2027-experiment
DATA_ROOT=/data1/yfzx/wangx/Datasets/easycom
LOCAL_ROOT=$(python - <<'PY'
from pathlib import Path
import torch
checkpoint = Path("checkpoints/easycom_local_b1_encoded_tf4576/av_seed0.pth")
p = torch.load(checkpoint, map_location="cpu", weights_only=False)
value = p["training_config"]["local_feature_root"]
if not value:
raise ValueError("This checkpoint has no local-feature root")
root = Path(value).expanduser().resolve()
if not root.is_dir():
raise FileNotFoundError(root)
print(root)
PY
) && printf 'LOCAL_ROOT=%s\n' "$LOCAL_ROOT"
```
如果 checkpoint 已移动,修改上述路径;也可以直接将 `LOCAL_ROOT` 设成以前
`easycom_local_b1_encoded_tf4576` 实验实际使用的局部特征目录。
必须包含完整的 `Session_1.pt` 到 `Session_12.pt`,不能用 `local_smoke_encoded`。
下面命令对空变量和缺文件会报错,不会自动重提特征或换成 Thinker 输入。
## 2. 先做 seed 0,三组前台顺序运行
单张空闲 L20 足够先跑这组小 head,无需启动八卡提取或安装新的依赖。
下面先 A、再 AV、最后 V;使用同一批冻结特征,仅改变输入模态。
```bash
(
set -euo pipefail
: "${DATA_ROOT:?Set DATA_ROOT first}"
: "${LOCAL_ROOT:?Set the verified local-feature directory first}"
export CUDA_VISIBLE_DEVICES=0
export OMP_NUM_THREADS=4 MKL_NUM_THREADS=4 OPENBLAS_NUM_THREADS=4
for modality in audio av visual
do
ENCODER_ROOT="${DATA_ROOT}/omni_features/encoder_only_${modality}_1s"
python prepare_encoder_only_features.py \
--dataset easycom \
--data-root "$DATA_ROOT" \
--local-feature-root "$LOCAL_ROOT" \
--modalities "$modality" \
--output-root "$ENCODER_ROOT"
python run_easycom_encoder_only.py \
--data-root "$DATA_ROOT" \
--feature-root "$ENCODER_ROOT" \
--modalities "$modality" \
--seeds 0
done
)
```
两条 Python 命令都支持 `--dry-run`。整理的 dry-run 只验证源文件,不生成训练输入;
训练的 dry-run 则需要已完成的导出目录,只打印训练/评测命令,不启动训练。
整理在 CPU 上完成:读取原生向量+有效性标志,校验全部 12 sessions、时间/索引、
配置一致性和 target 长度,逐文件保存,最后写出 `complete.txt`。
默认 target 是 `$DATA_ROOT/easycom_target_frame`,可用 `--target-root` 覆盖。
不使用 Ego4D manifest。新入口和 `--dataset easycom` 不影响已有 Ego4D 命令。
输出:
- 特征:`omni_features/encoder_only_audio_1s`、`encoder_only_av_1s`、`encoder_only_visual_1s`。
- 模型:`checkpoints/easycom_encoder_only_1s/encoder_<modality>_seed0.pth`。
- 评测:`results/easycom_encoder_only_1s/encoder_<modality>_seed0/metrics.json` 和 `pred/`。
导出目录、checkpoint 或结果目录已存在时**拒绝覆盖**。不要重新跑整个循环来补 seeds;
保留已完成的导出,只运行下面的训练入口。
若某次导出中断、没有完成标记,请使用新的 `--output-root`,不要手动补标记。
训练中断后换新的 `--checkpoint-root` / `--result-root`;不会自动恢复半成品训练。
## 3. 打印结果,随后补 seed 1/2
```bash
python summarize_local_baselines.py \
--root results/easycom_encoder_only_1s \
--dataset easycom \
--protocol causal_valid_only
```
请贴出三行 `encoder_audio_seed0`、`encoder_av_seed0`、`encoder_visual_seed0`。
原来的 81.72257 / 82.02661 / 73.47412 是 **G+A / G+A+V / G+V** 的 0.2s mAP,
不能标为 encoder-only。比较时使用相同 seed 和同一 `causal_valid_only` 协议。
第一轮确认能跑通后,补齐三个种子(不重新导出):
```bash
(
set -euo pipefail
: "${DATA_ROOT:?Set DATA_ROOT first}"
export CUDA_VISIBLE_DEVICES=0
export OMP_NUM_THREADS=4 MKL_NUM_THREADS=4 OPENBLAS_NUM_THREADS=4
for modality in audio av visual
do
python run_easycom_encoder_only.py \
--data-root "$DATA_ROOT" \
--feature-root "${DATA_ROOT}/omni_features/encoder_only_${modality}_1s" \
--modalities "$modality" \
--seeds 1 2
done
)
```
## 实验能回答什么
它测的是“Qwen 编码器近期 readout 本身的预测能力”,不是严格相同容量的 Thinker 消融。
3B 的 A/V 原生各 2048D;带有效性位后单模态 2049D、AV 4098D,
顺序是 `[visual, visual_valid, audio, audio_valid]`。不用 B1 的额外 256D 分支投影;
沿用原 MLP 类,隐藏宽度为输入维度整除 2,因此单模态 1024、AV 2049。
窗口、视觉 crop/视野和 head 参数量与原 Thinker 基线不同,应一起报告。
batch=512、lr=7e-5、weight_decay=5e-5、warmup_epochs=1.6、warmup_factor=0.3、
dropout=0.2、transition_objective=none。目录名 `1s` 不覆盖源文件的窗口配置,
真实窗口保存在导出 `config.encoder_contract.config`;时间含义完全沿用源特征。
本地 CPU 回归包括全部 12 sessions 的三模态导出、精确数值/时间对齐、缺文件和 partial 拒绝、
固定 split 顺序、无 Thinker 依赖,以及三个模态各 4 epochs 的合成数据训练/推理。
真实 EasyCom 精度和 L20 耗时由上述实验验证,不由这些测试推断。
```bash
python -m unittest -q test_easycom_encoder_only test_encoder_only_workflow
```