motionx-ski-artifacts / code /eval_mimetics_qwen.py
fira-aslan's picture
Upload folder using huggingface_hub
723126c verified
Raw History Blame Contribute Delete
3.94 kB
import json
import os
import time
from pathlib import Path
import pandas as pd
import torch
from peft import PeftModel
from transformers import AutoModelForImageTextToText, AutoProcessor
from video_inputs import build_video_item, prepare
SKI_ROOT = Path("/home/s56fasla/EXPERIMENTS_AND_EVALUATIONS/Testset_AR_EPFL/SKI-Models")
CSV = SKI_ROOT / "Mimetics_release_v1" / "mimetics_v1.0.csv"
CLASSES_TXT = SKI_ROOT / "mimetics_ski_zs_55_5_ckpt_raw_classes.txt"
VIDEO_DIR = SKI_ROOT / "mimetics_videos"
RUNS = Path("/home/s56fasla/MOTIONX/runs")
BASE_MODEL = os.environ.get("BASE_MODEL", "Qwen/Qwen3-VL-8B-Instruct")
RUN_PREFIX = os.environ.get("RUN_PREFIX", "skivlm_Qwen3-VL-8B")
TAG = os.environ.get("TAG", "q3")
ARM = os.environ.get("ARM", "ski")
LIMIT = int(os.environ.get("LIMIT", 0))
OUT = Path("/home/s56fasla/MOTIONX/evals")
VIDEO_FPS = 4.0
MAX_FRAMES = 32
MAX_PIXELS = 200704
MAX_NEW_TOKENS = 16
OUT.mkdir(parents=True, exist_ok=True)
device = "cuda"
classes = [c.strip() for c in open(CLASSES_TXT) if c.strip()]
menu = "\n".join(f"- {c}" for c in classes)
PROMPT = ("The person in this video is performing one of the following actions.\n"
f"{menu}\n\nAnswer with exactly one action name from the list, nothing else.")
run_dir = None if ARM == "base" else RUNS / f"{RUN_PREFIX}_{ARM}"
processor = AutoProcessor.from_pretrained(run_dir / "processor" if run_dir else BASE_MODEL)
model = AutoModelForImageTextToText.from_pretrained(
BASE_MODEL, dtype=torch.bfloat16, device_map={"": 0})
if len(processor.tokenizer) != model.get_input_embeddings().weight.shape[0]:
model.resize_token_embeddings(len(processor.tokenizer))
if run_dir:
model = PeftModel.from_pretrained(model, run_dir / "lora")
model.eval()
df = pd.read_csv(CSV)
df["file_name"] = df.apply(
lambda r: f"{r['youtube_id']}_{int(r['time_start']):06d}_{int(r['time_end']):06d}.mp4", axis=1)
vindex = {p.name: p for p in VIDEO_DIR.rglob("*.mp4")}
df = df[df["file_name"].isin(vindex) & df["label"].isin(classes)].reset_index(drop=True)
if LIMIT:
df = df.iloc[:LIMIT]
print("arm", ARM, "| classes", len(classes), "| clips", len(df),
"| chance %.3f" % (1.0 / len(classes)), flush=True)
lower = {c.lower(): c for c in classes}
rows = []
t0 = time.time()
for k, r in df.iterrows():
messages = [{"role": "user", "content": [
build_video_item(vindex[r["file_name"]], VIDEO_FPS, MAX_FRAMES, MAX_PIXELS),
{"type": "text", "text": PROMPT}]}]
try:
text = processor.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
videos, vkw = prepare(messages, vindex[r["file_name"]])
enc = processor(text=[text], videos=videos, return_tensors="pt", **vkw).to(device)
with torch.no_grad():
out = model.generate(**enc, max_new_tokens=MAX_NEW_TOKENS, do_sample=False)
gen = processor.tokenizer.decode(
out[0][enc["input_ids"].shape[1]:], skip_special_tokens=True).strip()
except Exception as e:
print("[skip]", r["file_name"], type(e).__name__, flush=True)
continue
g = gen.lower().strip().strip(".").strip()
pred = lower.get(g)
if pred is None:
hits = [c for c in classes if c.lower() in g]
pred = max(hits, key=len) if hits else None
rows.append({"file_name": r["file_name"], "label": r["label"], "raw": gen,
"pred": pred, "correct": int(pred == r["label"])})
if k % 25 == 0:
el = time.time() - t0
print(f"{k}/{len(df)} {el:.0f}s eta {el/max(1,k)*(len(df)-k)/60:.0f}min", flush=True)
pd.DataFrame(rows).to_csv(OUT / f"mimetics_{TAG}_{ARM}.csv", index=False)
out = pd.DataFrame(rows)
out.to_csv(OUT / f"mimetics_{TAG}_{ARM}.csv", index=False)
n = len(out)
acc = out["correct"].mean() if n else 0.0
unparsed = int(out["pred"].isna().sum()) if n else 0
print(f"ARM={ARM} n={n} top1={acc:.4f} chance={1.0/len(classes):.4f} unparsed={unparsed}", flush=True)