Skip to content

MoriochoRadio/multimodal-bias-vqa

Repository files navigation

Multimodal AI Bias Challenge — Vision-Language QA with Uncertainty Calibration

멀티모달 AI Bias 챌린지 — 불확실성 보정 기반 이미지·텍스트 질의응답

Predict the correct answer for image + context + question + 3 options, while knowing when there is not enough information to answer — measured by Balanced Accuracy over ambiguous and disambiguated questions.

이미지 + 상황 + 질문 + 선택지 3개에서 정답을 고르되, 근거가 부족하면 "모름"을 선택해야 하는 과제. 모호(ambiguous) 문항과 명확(disambiguated) 문항의 Balanced Accuracy로 평가.

Stack: Python · Qwen2.5-VL (3B / 7B, 4-bit) · Hugging Face Transformers · PyTorch · Kaggle GPU Result: Public Balanced Accuracy 0.883 (rank ~103) on the first complete submission · fully offline, open-weights only (no external API)

🌐 English · 한국어


🇬🇧 English

Problem

A multimodal variant of BBQ (Bias Benchmark for QA). Each sample provides an image, a context, a question, and exactly three options — one of which always means "unknown" / "cannot be determined." The model must output the answer index (0/1/2).

  • Ambiguous questions: the context gives no real evidence → the correct answer is the unknown option.
  • Disambiguated questions: the context names the responsible person → pick that person.
  • The metric is Balanced Accuracy = (accuracy on ambiguous + accuracy on disambiguated) / 2. A model that always guesses a person collapses on ambiguous items; one that always answers "unknown" collapses on disambiguated items. Calibrating "is there enough evidence?" is therefore half the score.

Constraints (competition rules)

  • ❌ No external inference APIs (OpenAI/Gemini/HF Inference, etc.). ✅ Open-source weights loaded locally only.
  • Only models with weights released before 2026-05-31.
  • The final answer must be LLM-generated text (no pure rule/majority mapping).
  • Inference must be reproducible offline within a reference env (RTX A6000 48GB), ~0.5s/sample target.
  • No data leakage: training/validation data must not be derived from the test set.

Approach

  1. Built a labeled validation set from scratch. The competition ships only one training example, so I constructed a 600-sample balanced dev set (300 ambiguous / 300 disambiguated) from the public BBQ dataset (text proxy) — used to measure Balanced Accuracy locally without spending the 5/day DACON submission budget. (No test data used → leakage-free.)
  2. Iterative prompt engineering, one change at a time, each evaluated on the dev set (10 experiments logged in EXPERIMENTS.md).
  3. Final model: Qwen2.5-VL-7B-Instruct (4-bit) + balanced chain-of-thought prompt. A faster 3B config is kept as a fallback.

Key findings

  • Chain-of-Thought is the single biggest lever. Asking the model to reason before answering cut overconfidence on ambiguous items from 0.47 → 0.09, lifting Balanced Accuracy from 0.71 → 0.87+.
  • Model size × prompt strongly interact. The same prompt flips results across model sizes:
    • 3B follows instructions weakly → "disambiguation-reinforcing" prompts make it over-pick people. Best with a cautious CoT (dev 0.848).
    • 7B follows instructions well → a balanced CoT ("if evidence is stated, treat it as fact and name the person; otherwise answer unknown") fixes both sides (dev 0.923).

Results (local dev, BBQ text proxy)

Step Change Ambiguous Disambiguated Balanced Kept
baseline 3B, plain prompt (v0) 0.527 0.897 0.712 base
exp3 3B + CoT (v4) 0.935 0.806 0.870
exp7 3B + cautious CoT (full) 0.863 0.833 0.848 ★ fallback
exp9 7B + balanced CoT (v6) 0.946 0.926 0.936
exp10 7B + balanced CoT (full) 0.913 0.933 0.923 ★★ best
exp11 7B, max_new_tokens 200→96 0.913 0.930 0.922 ★ (2× faster, same acc)

Leaderboard

  • First complete submission (3B cautious-CoT): Public Balanced Accuracy 0.883, rank ~103.
  • Validation insight: dev (0.848) < public (0.883) → the text-only dev set is a trustworthy, slightly conservative proxy for the real multimodal test, so dev improvements can be trusted for fast iteration.

Engineering challenges (the interesting part)

Running an 8,500-sample VLM inference on a free Kaggle T4 initially took ~18s/sample (≈40h) — impossible within Kaggle's 12h limit. Root-causing this was the bulk of the work:

  1. device_map="auto" silently offloaded part of the 7B model to CPU, causing a PCIe round-trip on every generated token. → Forced device_map={"":0} (whole model on one GPU).
  2. The T4 bf16 trap: torch.cuda.is_bf16_supported() returns True on a T4 (Turing, sm_75), but bf16 is only emulated there → slow. The auto-fallback never triggered. → Detect by compute capability < 8.0 (or "T4" in the name) and force fp16.
  3. Added batched generation, checkpoint/resume (safe across 12h session caps & disconnects), and unbuffered streaming logs for live progress.

Result: 18s → 3.4s/sample, the full 8,500-sample run finishes in ~8h within one Kaggle commit.

Reproducibility

pip install -r requirements.txt
# 1) build the dev set from public BBQ (one-time)
python build_dev.py
# 2) measure Balanced Accuracy locally on the dev set
python eval_dev.py --config best_config.json --batch 4
# 3) generate the test submission (8,500 rows)
python infer.py --config best_config.json --data_dir ./open --out submission.csv --batch 4 --resume

For a free GPU, run on Kaggle — see README_kaggle.md (single-cell kaggle_run.py, "Save & Run All (Commit)" headless mode).

Repo structure

bias_pipeline.py     # model load (device/dtype fixes), prompts v0–v7, batched generate
infer.py             # full-test inference: checkpoint/resume, streaming progress
eval_dev.py          # Balanced Accuracy on the local dev set
build_dev.py         # build the 600-sample dev set from public BBQ
configs/             # versioned prompt + hyperparameter configs
best_config.json     # current best (7B + balanced CoT, 96 tokens)
dev/dev.csv          # 600-sample balanced validation set (from public BBQ)
EXPERIMENTS.md       # full experiment log (every change, every score)
kaggle_run.py        # single-cell Kaggle runner (Commit mode)
README_kaggle.md     # Kaggle setup & run guide

What I learned

Building your own measurement (a leakage-free dev set) is what makes iteration possible; prompt strategy interacts with model scale; and on real hardware, systems debugging (dtype, device placement, batching, checkpointing) matters as much as modeling.

Acknowledgements

BBQ: A Hand-Built Bias Benchmark for QA (CC-BY-4.0) · Qwen2.5-VL · DACON / Sungkyunkwan University.


🇰🇷 한국어

문제

BBQ(Bias Benchmark for QA)의 멀티모달 버전. 각 샘플은 이미지 + 상황(context) + 질문 + 선택지 3개로 구성되고, 선택지 중 하나는 항상 "모름/판단 불가" 계열이다. 정답 인덱스(0/1/2)를 예측한다.

  • 모호(ambiguous): 맥락에 근거 없음 → 정답은 모름 옵션.
  • 명확(disambiguated): 맥락에 근거 있음 → 해당 인물.
  • 지표는 Balanced Accuracy = (모호 정확도 + 명확 정확도) / 2. 사람만 찍으면 모호에서, 모름만 찍으면 명확에서 무너진다. "근거가 충분한가?"의 보정이 점수의 절반.

제약 (대회 규칙)

  • ❌ 외부 추론 API 금지(OpenAI/Gemini/HF 등). ✅ 오픈소스 가중치를 로컬에 직접 로드만 허용.
  • 2026-05-31 이전 공개 가중치만 사용.
  • 최종 답은 LLM이 생성한 텍스트여야 함(룰/다수결 매핑 불가).
  • 오프라인 재현 가능해야 함(기준 환경 RTX A6000 48GB, 샘플당 ~0.5초 권장).
  • Data Leakage 금지: 학습/검증 데이터를 test에서 파생 금지.

접근

  1. 라벨 검증셋을 직접 구축. 학습 예시가 1개뿐이라, 공개 BBQ 데이터균형 dev셋 600개(모호/명확 300/300)(텍스트 프록시)를 만들어 DACON 제출(하루 5회)을 쓰지 않고도 로컬에서 Balanced Accuracy를 측정. (test 미사용 → leakage 없음.)
  2. 한 번에 하나씩 프롬프트 개선, 매번 dev로 측정(실험 10회, EXPERIMENTS.md).
  3. 최종 모델: Qwen2.5-VL-7B-Instruct(4bit) + 균형 CoT 프롬프트. 빠른 3B 설정은 폴백으로 보존.

핵심 발견

  • CoT(추론 먼저)가 최대 레버. 답하기 전에 추론시키자 모호 문항의 과확신이 0.47 → 0.09로 급감, Balanced Accuracy가 0.71 → 0.87+로 상승.
  • 모델 크기 × 프롬프트가 강하게 상호작용. 같은 프롬프트도 모델 크기에 따라 결과가 뒤집힘:
    • 3B는 지시추종이 약해, "명확성 보강" 프롬프트를 주면 사람을 과하게 찍음 → 신중 CoT가 최적(dev 0.848).
    • 7B는 지시추종이 좋아, 균형 CoT("근거 명시되면 사실로 인물 선택, 없으면 모름")가 양쪽 다 잡음(dev 0.923).

결과 (로컬 dev, BBQ 텍스트 프록시)

단계 변경 모호 명확 Balanced 채택
baseline 3B, 기본 프롬프트(v0) 0.527 0.897 0.712 base
exp3 3B + CoT(v4) 0.935 0.806 0.870
exp7 3B + 신중 CoT(full) 0.863 0.833 0.848 ★ 폴백
exp9 7B + 균형 CoT(v6) 0.946 0.926 0.936
exp10 7B + 균형 CoT(full) 0.913 0.933 0.923 ★★ best
exp11 7B, max_new_tokens 200→96 0.913 0.930 0.922 ★ (2배 빠름, 정확도 동일)

리더보드

  • 첫 완전 제출(3B 신중 CoT): Public Balanced Accuracy 0.883, 약 103등.
  • 검증 인사이트: dev(0.848) < public(0.883) → 텍스트 dev셋이 실제 멀티모달 시험을 약간 보수적으로 잡는, 믿을 만한 프록시임을 확인 → dev 개선을 신뢰하고 빠르게 반복 가능.

엔지니어링 디버깅 (가장 값진 부분)

무료 Kaggle T4에서 8,500개 VLM 추론이 처음엔 샘플당 18초(약 40시간) — Kaggle 12시간 제한 내 불가능. 원인 규명이 작업의 핵심이었다:

  1. device_map="auto"가 7B 일부를 CPU로 오프로드 → 매 토큰 PCIe 왕복으로 치명적 저하. → device_map={"":0}(단일 GPU 통째 적재)로 해결.
  2. T4 bf16 함정: torch.cuda.is_bf16_supported()T4(Turing, sm_75)에서 True를 반환하지만 bf16은 에뮬레이션이라 느림. 자동 폴백이 안 걸림. → compute capability < 8.0(또는 이름에 "T4")이면 fp16 강제.
  3. 배치 추론, 체크포인트/resume(12시간 세션·연결끊김 대비), 실시간 스트리밍 로그 추가.

결과: 18초 → 3.4초/샘플, 8,500개 전체가 한 커밋(~8시간)에 완주.

재현 방법

pip install -r requirements.txt
# 1) 공개 BBQ로 dev셋 구축 (최초 1회)
python build_dev.py
# 2) 로컬 dev셋에서 Balanced Accuracy 측정
python eval_dev.py --config best_config.json --batch 4
# 3) test 제출파일 생성 (8,500행)
python infer.py --config best_config.json --data_dir ./open --out submission.csv --batch 4 --resume

무료 GPU는 Kaggle 권장 — README_kaggle.md 참고(단일 셀 kaggle_run.py, "Save & Run All (Commit)" 백그라운드 모드).

레포 구조

bias_pipeline.py     # 모델 로드(디바이스/dtype 수정), 프롬프트 v0–v7, 배치 생성
infer.py             # 전체 추론: 체크포인트/resume, 진행률 스트리밍
eval_dev.py          # 로컬 dev셋 Balanced Accuracy 측정
build_dev.py         # 공개 BBQ로 600개 dev셋 구축
configs/             # 프롬프트·하이퍼파라미터 버전별 설정
best_config.json     # 현재 best (7B + 균형 CoT, 96토큰)
dev/dev.csv          # 600개 균형 검증셋 (공개 BBQ 기반)
EXPERIMENTS.md       # 전체 실험 로그 (모든 변경·점수)
kaggle_run.py        # Kaggle 단일 셀 실행기 (Commit 모드)
README_kaggle.md     # Kaggle 셋업·실행 가이드

배운 점

라벨 없는 문제에서 "측정 도구(leakage 없는 dev셋)"를 직접 만드는 것이 반복 개선을 가능케 한다. 프롬프트 전략은 모델 규모와 상호작용하며, 실제 하드웨어에서는 시스템 디버깅(dtype·디바이스 배치·배칭·체크포인트)이 모델링만큼 중요하다.

출처

BBQ: A Hand-Built Bias Benchmark for QA (CC-BY-4.0) · Qwen2.5-VL · DACON / 성균관대학교.


This project was developed for the 2026 SKKU Multimodal AI Bias Challenge (DACON). Competition test data is not redistributed here; see DACON for data access. 본 프로젝트는 2026 성균관대 멀티모달 AI Bias 챌린지(DACON)를 위해 개발되었습니다. 대회 평가 데이터는 재배포하지 않으며, 데이터는 DACON에서 받으세요.

About

Multimodal BBQ (bias) visual question answering: pick the right answer from image + context + question + 3 options, and answer "unknown" when evidence is insufficient. Offline, open-weights Qwen2.5-VL (4-bit) + balanced chain-of-thought. Public Balanced Accuracy 0.883.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages