Code Review Report: Methods–Codebook–Code Alignment Audit

Review Date: 2026-04-12
Scope: 8 core files × 2 design documents
Reviewer: Claude Code (iterative-code-review × 2 agents + manual cross-reference)


Executive Summary

comprehensive_stats_codebook.md(Codebook)와 04_methods.md(Methods)에 기술된 설계 의도 대비 코드 구현을 검토한 결과, CRITICAL 2건, MAJOR 12건, MINOR 10건, NOTE 6건의 이슈를 식별하였다. CRITICAL 이슈는 (1) bias 부호 방향의 시트 간 불일치와 (2) Methods 수식과 코드의 Bland-Altman 부호 반전이다. 에이전트 리뷰에서 추가로 발견된 주요 이슈는 Human LOO baseline의 bias_z_mean 하드코딩, Human .first() vs majority vote 문제, statistics.py의 dead code 위험이다.


Issue Registry

CRITICAL Issues

C-1. Bias 부호 방향이 시트 간 불일치

  • 위치:
    • generate_comprehensive_stats.py:213val_bias = (sub["h_val"] - sub["v_val"]).mean()Human − VLM
    • generate_comprehensive_stats.py:141"bias": hm - vmHuman − VLM
    • generate_comprehensive_stats.py:527,706df_copy["val_bias"] = df_copy["v_val"] - df_copy["h_val"]VLM − Human
  • 설계 문서: Codebook Sheet 9: val_bias: Valence bias (human−VLM) ↔ Sheet 27: dimension: val_bias (코드에서 VLM−Human)
  • 문제: 시트 1/6/8/9의 bias는 Human − VLM (양수 = VLM 과소평정)이지만, 시트 25-26/27-28의 ANOVA bias 변수는 VLM − Human (양수 = VLM 과대평정). 동일 개념이 시트에 따라 반대 부호로 기록됨.
  • 영향: F-test/η² 값 자체는 부호 무관하여 결론에 영향 없으나, emmeans 사후 검정의 estimate 부호가 반전되어 해석 시 혼동 가능. 본문 Table과 교차 참조 시 부호 해석 오류 위험.
  • 권장: 모든 시트에서 bias = Human − VLM (또는 VLM − Human) 한 방향으로 통일. ANOVA 함수(compute_demographic_dimensional_lmm, compute_dimensional_stratified_interaction)에서 df_copy["val_bias"] = df_copy["h_val"] - df_copy["v_val"]로 수정.

C-2. Methods 수식 vs 코드의 Bland-Altman 부호 반전

  • 위치:
    • Methods §3.4.2 (line 156): $d_j = x_j - \bar{y}_j$ (x = VLM, y = Human) → d = VLM − Human
    • statistics.py:124: diffs = values_a - values_b
    • generate_comprehensive_stats.py:96: ba = compute_bland_altman(h, v) → values_a=Human, values_b=VLM → diffs = Human − VLM
    • Codebook Sheet 5/7: ba_bias: Bland-Altman bias (human − VLM 평균 차이)
  • 문제: Methods의 수식은 d = VLM − Human으로 정의하지만, 코드는 Human − VLM으로 계산. Codebook은 코드와 일치하나 Methods와 불일치.
  • 영향: 본문에서 “bias = +0.47” 등으로 보고할 때, Methods의 수식 정의와 실제 부호가 반대. 독자가 수식으로 검증 시 부호가 맞지 않음.
  • 권장: Methods의 정의를 (Human − VLM)로 수정하거나, 코드의 호출 순서를 compute_bland_altman(v, h)로 변경하여 일관성 확보.

MAJOR Issues

M-1. numpy .std() ddof=0 vs pandas .std() ddof=1 혼용

  • 위치:
    • generate_comprehensive_stats.py:102-103: v.std(), h.std() — numpy array → ddof=0 (모집단 SD)
    • generate_comprehensive_stats.py:118-119: h_vals.std(), v_vals.std() — numpy array → ddof=0
    • generate_comprehensive_stats.py:1107-1109: sub["v_val"].std() — pandas Series → ddof=1 (표본 SD)
    • generate_comprehensive_stats.py:165-168: np.std(te)ddof=0
    • generate_comprehensive_stats.py:975,979,1000,1013: np.std(vlm_abs_z) 등 — ddof=0
    • cf. statistics.py:126: np.std(diffs, ddof=1)ddof=1
    • cf. human_ratings.py:92-97: .std(ddof=1)ddof=1
  • 설계 문서: Methods §3.4.2 Bland-Altman: “는 차이값의 표본표준편차(자유도 )”
  • 문제: 동일 스크립트 내에서 numpy(ddof=0)와 pandas(ddof=1) 기본값이 혼재. N=1440에서 차이는 ~0.03%로 미미하나, N=30 수준(thinking sad_correct 등)에서는 ~1.7% 차이.
  • 영향: Sheets 5-8 (vlm_sd, human_sd), 11-12 (thinking SD), 22-23 (abs_z_sd, bias_z_sd)의 SD가 ddof=0으로 산출됨.
  • 권장: 모든 SD 계산에서 ddof=1을 명시. numpy 호출부에 np.std(arr, ddof=1) 추가.

M-2. R 스크립트 실패 시 silent empty return

  • 위치:
    • generate_comprehensive_stats.py:326-328: return [], []
    • generate_comprehensive_stats.py:485-487: return [], []
    • generate_comprehensive_stats.py:643-645: return [], []
    • generate_comprehensive_stats.py:835-837: return [], []
  • 문제: R 스크립트가 실패하면 WARN 메시지만 출력하고 빈 리스트를 반환. 이후 main()에서 if demo_anova_rows: 조건으로 시트 자체를 생략. 사용자는 시트 부재의 원인을 파악하기 어려움.
  • 영향: 재현성 저하. R 환경 문제로 인구통계 분석 전체가 누락되어도 경고만 출력.
  • 권장: 실패 시 Exception을 raise하거나, 최소한 “FAILED” placeholder 시트 생성 + 실패 원인 기록.

M-3. Codebook Sheet 22의 n_bootstrap 컬럼 vs 코드 불일치

  • 위치:
    • Codebook line 326: n_bootstrap: Bootstrap 반복 횟수 (2,000)
    • generate_comprehensive_stats.py:969-982: compute_zscore_analysis()의 summary_rows에 n_bootstrap 필드 없음
  • 문제: Codebook은 Sheet 22에 n_bootstrap 컬럼이 있다고 기술하나, 현재 compute_zscore_analysis() 함수는 bootstrap을 수행하지 않아 해당 컬럼을 생성하지 않음. 현재 consolidate가 사용하는 base 파일은 이전 버전에서 생성된 것.
  • 영향: generate_comprehensive_stats.py를 재실행하면 Sheet 22의 컬럼 구조가 Codebook과 불일치.
  • 권장: (a) compute_zscore_analysis()에 bootstrap 로직 추가하여 Codebook과 일치시키거나, (b) Codebook에서 bootstrap 관련 컬럼 제거.

M-4. 인구통계 결측 시 silent filtering (no row count logging)

  • 위치:
    • generate_comprehensive_stats.py:711: df_copy = df_copy[(df_copy["race"] != "") & (df_copy["gender"] != "")]
    • generate_comprehensive_stats.py:206-208: if not group: continue
  • 문제: 빈 문자열인 race/gender 행을 무조건 제거하나, 제거된 행 수를 기록하지 않음. Sheet 27-28의 N은 결측 행이 제거된 상태이나, 이를 사용자에게 알리지 않음.
  • 영향: 일부 모델의 predictions.jsonl에 race/gender 메타데이터가 누락된 경우, ANOVA의 N이 1,440보다 작아지며 이를 추적 불가.
  • 권장: 결측 행 수를 로깅하고, Sheet 27에 N_dropped 컬럼 추가 또는 별도 메타데이터 기록.

M-5. Per-emotion VA 시트에 ICC(2,1) 잔존

  • 위치:
    • generate_comprehensive_stats.py:125-135: ICC(2,1) 계산 후 icc 컬럼에 저장
    • Codebook Sheet 6 line 107: icc: ICC(2,1) — VLM과 human을 2명의 rater로 취급
    • Methods §3.4.3: “ICC(2,1)은 … 본 연구의 역균형 설계에는 적합하지 않다”
  • 문제: Methods v10.2 개정에서 ICC(2,1)은 부적합하다고 명시적으로 제거되었으나, 코드는 여전히 per-emotion level에서 ICC를 계산하여 Sheets 6/8에 icc 컬럼으로 출력. Codebook도 이를 문서화하고 있음.
  • 영향: Methods와 코드 간 직접적 모순. 리뷰어가 “ICC를 사용하지 않는다고 했는데 시트에 있다”고 지적 가능.
  • 권장: (a) icc 컬럼 제거 또는 (b) Supplementary로 분리하여 명시.

M-6. Human 분류 기준 라벨 혼재 (h_emo vs gt_emotion)

  • 위치:
    • VLM의 경우 generate_comprehensive_stats.py:67: "h_emo": h.emotion_majority (human majority vote = GT label from CSV)
    • Human의 경우 generate_comprehensive_stats.py:1439: "h_emo": human_img["gt"] (image filename-derived GT)
    • generate_comprehensive_stats.py:1440: "v_emo": human_img["emotion"] (human majority vote)
  • 설계 문서: Methods §3.4.5: “Cohen’s κ는 인간 감정 범주 라벨이 수집되지 않은 관계로 ground-truth 자극 라벨을 단일 준거로 사용”
  • 문제: VLM의 κ는 human majority vote(= image GT from CSV emotion column) 대비 VLM 예측으로 계산. Human의 κ는 filename-derived GT 대비 human majority vote로 계산. 정상적으로 작동하지만, VLM의 “h_emo”가 human majority인지 image GT인지 코드만으로는 불명확. CSV의 emotion 컬럼이 GT인지 participant response인지에 따라 의미가 달라짐.
  • 영향: CSV의 emotion = image GT일 경우 (가장 가능성 높음) 문제 없으나, participant의 emotion judgment일 경우 VLM의 κ 기준이 Methods와 달라짐.
  • 권장: 코드에 주석으로 “emotion column = image GT, not participant response” 명시.

M-7. Codebook Sheet 15 행 수 불일치

  • 위치:
    • Codebook line 237: 15_Demo_ANOVA (18 rows) — “R glmer: correct ~ demographic + (1|gt_emotion)
    • 코드 generate_comprehensive_stats.py:276-277: 8 models × 2 demo vars = 16 rows (Human 포함 시 9 × 2 = 18)
  • 문제: Codebook은 18행으로 기술하나, compute_demographic_significance()는 model_dfs에 Human을 포함하여 9 models × 2 demo = 18행이 맞음. 그러나 Human에 대한 glmer 결과는 “Human accuracy vs GT”라는 의미가 모호 — Human의 분류가 demographic에 따라 달라지는지를 검증하는 것은 타당하나, 이것이 VLM 평가와 동일 맥락인지 불명확.
  • 영향: 해석 혼란 가능성.
  • 권장: Human 행의 해석 주석 추가.

M-8. load_predictions()의 이중 JSON 파싱

  • 위치: generate_comprehensive_stats.py:55: [json.loads(l) for l in open(path) if json.loads(l).get("parse_success", True)]
  • 문제: 각 행에 대해 json.loads()를 2번 호출 (필터 조건 + 리스트 생성). 1,440행 × 8 모델 = 11,520번의 불필요한 중복 파싱.
  • 영향: 성능 저하 (체감 가능). 또한, parse_success=False인 행이 있으면 첫 번째 json.loads()에서 파싱 성공하지만 두 번째에서도 다시 파싱하므로 로직은 정확하나 비효율적.
  • 권장: walrus operator 사용: [d for l in open(path) if (d := json.loads(l)).get("parse_success", True)]

M-9. Human LOO baseline의 bias_z_mean이 0.0으로 하드코딩

  • 위치: generate_comprehensive_stats.py:1016-1017,1036-1037: "bias_z_mean": 0.0, "bias_z_sd": 0.0
  • 문제: LOO z-score는 (rating_j - mean_others) / sd_others로 계산. Leave-one-out의 비대칭성(한 명 제거 시 mean과 SD 모두 이동)으로 인해 전체 LOO z의 평균은 정확히 0이 아님. 하드코딩 대신 실제 값을 계산해야 함.
  • 영향: 인간 기저선의 bias 특성이 가려짐. 부호 방향(일관되게 양수 또는 음수인지)에 대한 정보 소실.
  • 권장: "bias_z_mean": float(np.mean(signed_z_values)) 등으로 실제 계산.

M-10. Human 분류에서 .first() vs majority vote 불일치

  • 위치: generate_comprehensive_stats.py:1431-1432: human_img = human_df_full.groupby("image_id").first().reset_index()
  • 문제: 주석에 “all raters agree, so just take first”라고 가정하지만, emotion 컬럼이 image GT 라벨이면 모든 행이 동일하여 문제 없으나, 만약 participant의 emotion judgment라면 .first()는 첫 번째 행의 값만 취하여 majority vote가 아닌 임의의 한 명의 응답을 사용하게 됨.
  • 영향: CSV의 emotion 컬럼이 image GT(가장 가능성 높음)이면 문제 없으나, 코드 주석과 가정이 불명확.
  • 권장: assert (human_df_full.groupby("image_id")["emotion"].nunique() == 1).all() 등으로 가정 검증.

M-11. statistics.py의 compute_krippendorff_alpha()가 dead code

  • 위치:
    • statistics.py:148-183: compute_krippendorff_alpha(level_of_measurement="ordinal")
    • generate_comprehensive_stats.py:1055-1086: krippendorff.alpha(level_of_measurement="interval") 직접 호출
  • 문제: statistics.py에 정의된 함수는 기본값이 "ordinal"이지만, 실제 파이프라인은 이 함수를 사용하지 않고 krippendorff 라이브러리를 직접 "interval"로 호출. 리팩토링 시 statistics.py 함수를 사용하면 ordinal α가 산출되어 결과가 달라짐.
  • 영향: 잠재적 리팩토링 버그. 현재 파이프라인에는 영향 없음.
  • 권장: (a) statistics.py의 기본값을 "interval"로 변경하거나, (b) generate_comprehensive_stats.py에서 statistics.py 함수를 사용하도록 통합.

M-12. 파일 핸들 미해제 (resource leak)

  • 위치:
    • generate_comprehensive_stats.py:55: open(path) without with
    • generate_comprehensive_stats.py:1507: 동일
  • 문제: open(path)with 문 없이 사용됨. CPython의 참조 카운팅 GC에 의해 대부분 해제되지만, 8개 모델 파일 × 2번 로드 = 16개 파일 핸들이 동시에 열릴 수 있음.
  • 권장: with open(path) as f: 패턴 사용.

MINOR Issues

m-1. Thinking metrics의 np.std() ddof=0

  • 위치: generate_comprehensive_stats.py:165-168
  • 문제: M-1의 구체적 사례. np.std(te) 등에서 ddof=0 사용.
  • 영향: N=240일 때 ~0.2% 차이. Sheet 11-12에 영향.

m-2. compute_per_emotion_va()의 per-emotion Bland-Altman 호출 순서

  • 위치: generate_comprehensive_stats.py:136: ba = compute_bland_altman(h_vals, v_vals) → Human − VLM
  • 문제: C-2와 동일한 부호 방향 이슈가 per-emotion 수준에서도 발생.
  • 영향: Sheets 6/8의 ba_bias 부호가 Methods 수식과 반대.

m-3. z-score LOO baseline의 LOO SD threshold

  • 위치: generate_comprehensive_stats.py:915,920: if sd < 0.01: continue / if loo_sd > 0.01:
  • 문제: SD < 0.01인 이미지(인간 평정이 거의 만장일치)를 z-score 분석에서 제외. 이 필터링이 Methods에 문서화되지 않음.
  • 영향: 일부 이미지(특히 happy 등 합의도 높은 정서)가 제외되어 N이 1,440보다 작을 수 있음.
  • 권장: Methods에 “SD < 0.01인 이미지는 z-score 정의가 불안정하여 제외” 명시.

m-4. consolidate_v10_xlsx.py 시트명 변경 미반영

  • 위치:
    • generate_comprehensive_stats.py:1556: 시트명 27_Demo_DimStratified_ANOVA
    • consolidate_v10_xlsx.py:73: strat["27_Demo_DimStratified_ANOVA"]sheets["27_Demo_DimStrat_ANOVA"]
  • 문제: 생성 스크립트와 통합 스크립트에서 시트명이 다름 (DimStratified vs DimStrat). 통합 시 올바르게 매핑되지만, 재생성 후 통합 시 키 불일치로 KeyError 발생 가능.
  • 권장: 시트명을 통일.

m-5. Codebook 자동 생성의 핵심_함수 부정확

  • 위치: consolidate_v10_xlsx.py:264: Sheet 13 핵심_함수 = compute_human_rt() — 이 함수는 존재하지 않음. 실제는 main()에서 직접 rt_by_emotion 딕셔너리 구성.
  • 영향: Codebook의 참조 정보 부정확.

m-6. Codebook 시트 15의 핵심_함수 참조 오류

  • 위치: consolidate_v10_xlsx.py:285: 핵심_함수 = compute_demographic_significance() → r_bridge.fit_glmer()fit_glmer는 존재하지 않음. 실제는 R subprocess를 통한 glmer 호출.
  • 영향: 코드 추적 시 혼란.

m-7. inter_llm_variance.py가 7개 모델만 포함

  • 위치: consolidate_v10_xlsx.py:77-84: Sheets 29-32가 inter_llm_variance.xlsx에서 로드
  • 설계 문서: Methods §3.4.3: “7개 VLM 간 분산” — Gemini-2.5-Flash-NoThink 제외
  • 문제: Sheet 31/32의 wide format이 7개 모델 컬럼만 포함. 8개 VLM 조건 중 NoThink를 제외한 이유가 코드에 문서화되지 않음. (NoThink = 동일 모델의 ablation이므로 inter-model variance 계산에서 제외하는 것은 타당할 수 있음.)
  • 권장: 제외 사유 코드 주석 추가.

m-8. EMOTIONS 라벨 정규화 의존성

  • 위치: generate_comprehensive_stats.py:32: EMOTIONS = ["happy", "sad", "angry", "fear", "disgust", "neutral"]
  • 문제: CLAUDE.md는 “Fea→fearful, Dis→disgusted”로 문서화. classification_report(labels=EMOTIONS)에서 “fearful”/“disgusted”로 예측된 항목은 무시됨. 프롬프트 파싱이 “fear”/“disgust”로 정규화한다면 문제 없으나, 정규화가 누락되면 F1이 silent하게 저하.
  • 영향: 파싱 파이프라인이 정상이면 문제 없으나, 새 모델 추가 시 위험.

m-9. n_sheets 카운트가 부정확

  • 위치: generate_comprehensive_stats.py:1570: n_sheets = 13 + ...
  • 문제: 실제로는 최대 24개 시트를 생성하지만, 카운트 로직이 13 + 조건부 2~3개만 계산. 출력되는 시트 수가 실제와 불일치.
  • 영향: 디버깅 시 혼란.

m-10. 이중 데이터 로드 (predictions)

  • 위치: generate_comprehensive_stats.py:1313 (main loop) + 1507 (z-score용 재로드)
  • 문제: 동일한 predictions.jsonl 파일을 2번 독립적으로 로드. 첫 번째 루프에서 preds를 dict에 저장하면 재로드 불필요.
  • 권장: all_raw_preds[model_name] = preds를 main loop에서 수집.

NOTE (참고 사항)

N-1. z-score 분석 로직의 이중 구현

  • 위치:
    • generate_comprehensive_stats.py:882-1041: compute_zscore_analysis()
    • compute_zscore_per_emotion_bootstrap.py:100+: compute_per_emotion()
  • 문제: 거의 동일한 z-score/LOO 계산 로직이 두 파일에 독립적으로 구현됨. 한쪽 수정 시 다른 쪽과 동기화 필요.
  • 권장: 공유 유틸리티 모듈로 리팩토링.

N-2. Krippendorff α 산출 시 VLM의 결정론적 특성

  • 위치: generate_comprehensive_stats.py:1044-1096: compute_krippendorff_vlm()
  • 문제: α 계산은 평정자 독립성을 가정하나, VLM은 결정론적(temp=0) — 동일 입력에 대해 항상 동일 출력. 이론적으로 α의 해석이 “평정자 교환 가능성”에서 “집단 일치도 유지 여부”로 제한됨.
  • 영향: Methods §3.4.3에서 이미 이 점을 인지하고 Δα의 해석을 “집단 신뢰도 유지/저하”로 제한하고 있어 문제는 아니나, 코드에 주석 없음.

N-3. Confusion matrix의 준거가 h_emo (human majority) vs gt_emotion

  • 위치: generate_comprehensive_stats.py:1340-1346
  • 문제: Confusion matrix의 human_emotion 축은 h_emo (human majority vote)를 사용. 본 데이터에서 h_emo ≈ gt_emotion (CSV의 emotion 컬럼 = image GT)이므로 실질적 차이 없음.
  • 상태: 확인 완료, 이슈 아님.

N-4. Mann-Whitney U 검정의 alternative 미지정

  • 위치: generate_comprehensive_stats.py:193: stats.mannwhitneyu(correct_t, wrong_t)
  • 문제: scipy 기본값은 alternative='two-sided'이며 이는 적절. 단, 방향 가설(thinking 길이가 정답 시 더 긴지)이 있다면 one-sided가 더 적합할 수 있음.
  • 영향: 보수적 검정이므로 결론에 영향 없음.

N-5. Krippendorff pivot_table vs pivot 불일치

  • 위치:
    • generate_comprehensive_stats.py:1059: pivot_table() — 중복 시 mean으로 자동 집계
    • generate_comprehensive_stats.py:1139: pivot() — 중복 시 ValueError raise
  • 문제: 동일 스크립트 내에서 human ratings pivot에 pivot_table (aggfunc=‘mean’)과 pivot (중복 불허)를 혼용. 데이터에 중복이 없으면 동일하지만, 중복 처리 방식이 다름.
  • 영향: 현재 데이터에서 중복이 없으면 문제 없음.

N-6. compute_bland_altman()의 arguments naming 모호성

  • 위치: statistics.py:113-118: values_a, values_b — 어느 것이 reference인지 docstring에서 불명확
  • 문제: Docstring에 “values_a: human mean, values_b: VLM” 예시가 있으나 강제는 아님. 호출부에서 순서를 바꾸면 부호가 반전됨.
  • 권장: 파라미터명을 reference, test 등으로 변경하거나 docstring에 “diffs = a - b” 명시.

Methods ↔ Code Cross-Reference Checklist

Methods 수식/절차코드 위치일치 여부비고
§3.4.1 κ = (p_o − p_e)/(1 − p_e)sklearn.cohen_kappa_score() via generate_comprehensive_stats.py:83sklearn 구현이 정확
§3.4.1 Accuracy = ΣTP_k / Ngenerate_comprehensive_stats.py:82
§3.4.1 Precision_k, Recall_k, F1_ksklearn.classification_report() via :85
§3.4.1 F1_macro = (1/K)ΣF1_ksklearn.f1_score(average="macro") via :84
§3.4.2 Pearson rscipy.stats.pearsonr(h, v) via :93h=Human mean, v=VLM
§3.4.2 Bland-Altman d_j = x_j − ȳ_jstatistics.py:124: diffs = a − b, called as (h, v)⚠️ C-2부호 반전
§3.4.2 Bias = d̄statistics.py:125: mean_diff = mean(diffs)(부호 방향만 반전)
§3.4.2 SD_d, ddof=N−1statistics.py:126: np.std(diffs, ddof=1)
§3.4.2 LoA = d̄ ± 1.96·SD_dstatistics.py:128-131
§3.4.2 LMM: rating ~ rater_type * emotion + (1|image_id)generate_comprehensive_stats.py:1223formula 정확
§3.4.3 α = 1 − D_o/D_ekrippendorff.alpha() via :1062,1085라이브러리 구현
§3.4.3 Δα = α_combined − α_humangenerate_comprehensive_stats.py:1092
§3.4.3 z = (x − M) / SDgenerate_comprehensive_stats.py:955
§3.4.3 W_1SD = proportion(|z| ≤ 1.0)generate_comprehensive_stats.py:976
§3.4.3 LOO z_hj = (x_hj − M^(-h)) / SD^(-h)generate_comprehensive_stats.py:918-921
§3.4.4 glmer: correct ~ race + (1|gt_emotion)generate_comprehensive_stats.py:283
§3.4.4 LR χ² = −2(ℓ_reduced − ℓ_full)generate_comprehensive_stats.py:292-295: R anova(fit_null, fit)
§3.4.4 M_full: bias ~ race × gendergenerate_comprehensive_stats.py:754
§3.4.4 Nested F: M_gen vs M_add (race)generate_comprehensive_stats.py:765
§3.4.4 Nested F: M_race vs M_add (gender)generate_comprehensive_stats.py:766
§3.4.4 Nested F: M_add vs M_full (interaction)generate_comprehensive_stats.py:767
§3.4.4 BH FDR within (model, dimension) familygenerate_comprehensive_stats.py:845-85218 tests/family
§3.4.4 Post-hoc: emmeans Tukey on 6 cells, conditional on q_BH<.05generate_comprehensive_stats.py:860-877
§3.4.4 η² = SS_term / SS_totalgenerate_comprehensive_stats.py:779,790,803Type I SS

Codebook ↔ Code Cross-Reference

SheetCodebook 행 수코드 실제일치비고
1_Model_Summary88 (VLM only) + Human 미포함⚠️Codebook “8 rows”이지만 Human 포함 시 9
2_Classification99 (8 VLM + Human)
3_Per_Emotion_PRF5454 (6 × 9)
4_Confusion_Matrix324324 (36 × 9)
5_Valence_Overall88
6_Valence_Per_Emotion4848 (6 × 8)icc 컬럼 잔존 (M-5)
9_Demographic4545 (5 × 9)
10_Response_Variability48≤48일부 감정 N=0 시 미생성
11_Thinking_Per_Emotion1212 (6 × 2)
14_Human_Reliability1515 (1+6×2+2)
15_Demo_ANOVA1818 (9 × 2)
22_ZScore_Summary1818 (8+1 LOO × 2)⚠️ M-3n_bootstrap 컬럼 불일치
24_Krippendorff_Alpha1818 (1+8 × 2)
27_Demo_DimStrat_ANOVA~288~288 (8×6×2×3)

Summary Statistics

SeverityCountAction Required
CRITICAL2즉시 수정 필요 (부호 일관성)
MAJOR12다음 개정 전 수정 권장
MINOR10코드 품질 개선 시 포함
NOTE6참고용 기록
Total30

Positive Findings

코드의 전반적 품질은 양호하며, 다음 사항이 긍정적으로 평가됨:

  1. 통계 수식의 정확한 구현: Cohen’s κ, F1-macro, Krippendorff α, z-score LOO baseline 등 핵심 지표가 Methods 수식과 정확히 대응
  2. BH FDR 보정의 올바른 적용: (model, dimension) 가족 내 18개 검정 단위로 보정
  3. Nested F-test의 정확한 구현: 4-모형 세트(M_full, M_add, M_race, M_gen)로 3개 nested F-test를 올바르게 수행
  4. Post-hoc 조건부 필터링: race:gender 교호작용이 유의한 경우에만 사후 검정 보고
  5. Human LOO baseline: z-score 해석을 위한 인간 기저선이 올바르게 구현
  6. Codebook 자동 생성: 시트 메타데이터의 자동 문서화
  7. HumanRatingStore의 ddof=1: 인간 평정 집계에서 표본 SD가 올바르게 사용