[kdd cup tencent] 데이터 이해하기
베이스라인 이해 다음은 데이터다. 1편에서 PCVRHyFormer를 분해했지만, 모델만 안다고 가설이 나오진 않는다. 결국 데이터의 어떤 신호를 우리가 못 살리고 있는가를 봐야 차별화 포인트가 보인다.
1. 들어가며
TAAC 데이터는 demo_1000.parquet (1000행 × 120컬럼)으로 받았다. 풀 데이터는 Academic Track 1M, Industrial Track 2M. demo_1000도 schema는 동일해서 column별 의미를 파악하는 데 충분하다.
목표: 데이터 한 행이 무슨 의미인지, 6개 카테고리가 어떻게 구성되는지, 어떤 fact가 모델 설계의 motivation이 되는지 이해한다.
2. 한 행 = (user, item) 쌍 + 모든 부가정보
한 행에 담긴 것을 6 카테고리로 분류하면:
| 카테고리 | 개수 | 의미 |
| ID & Label | 5 | user_id, item_id, label_type, label_time, timestamp |
| User Int features | 46 | scalar 35 + multi-value list 11 (결혼상태 등) |
| User Dense features | 10 | float array (3 patterns — 아래 §4) |
| Item Int features | 14 | scalar 13 + list 1 |
| Domain Sequence features | 45 | 4 도메인 × 9\~14 칼럼씩 (a=9, b=14, c=12, d=10) |
| 합계 | 120 |
각 행의 의미: "이 user × 이 item 쌍에서 conversion이 일어났는가" 를 예측하기 위한 모든 정보.
3. 시퀀스 — 한 도메인이 여러 칼럼으로 표현되는 이유
Domain a를 예로 보자. 9개 칼럼(domain_a_seq_38 \~ _46)이 있다. 이 9개는 같은 user의 같은 행동 시퀀스를 9가지 속성으로 쪼개서 표현한다.
예시 (한 user의 domain_a, 가장 최근 행동 1개):
| Column | fid | [0]번째 값 | 추정 의미 |
domain_a_seq_38 | 38 | 0 | item id (추정) |
domain_a_seq_39 | 39 | 1772695320 | timestamp (확정) |
domain_a_seq_40 | 40 | 2 | small vocab (action type? category?) |
domain_a_seq_41 | 41 | 6 | small vocab |
domain_a_seq_42 \~ _46 | 42-46 | 840, 1365, 3792, 0, 12 | mid/large vocab (anonymized) |
→ user의 한 행동마다 9개 정보가 함께 기록되고, 이 user는 domain a에서 그런 행동을 682번 했다.
잠깐 — fid가 뭐야?
fid = column 이름의 숫자 suffix (1\~109 범위). 대회 주최자가 feature 의미를 익명화하고 숫자만 부여한 것. 같은 fid가 여러 block에 등장하면 서로 align된다는 의미 (§4.1에서 다룸).
예:
user_int_feats_62와user_dense_feats_62는 같은 fid 62 → 동일 entity의 ID와 weight가 짝.
3.1 익명화의 한계
대회는 의도적으로 모든 feature를 익명화했다. 단 timestamp fid만 schema.json에 명시됐다.
| Domain | timestamp fid |
|---|---|
| a | 39 |
| b | 67 |
| c | 27 |
| d | 26 |
나머지는 추측만 가능. 이게 제약이자 도전 — paper의 도메인 의미를 그대로 가져올 수 없으니, mechanism 설계로 풀어야 한다.
4. User Dense Features — 3가지 패턴
User dense features (10개)은 단순한 float array가 아니다. 동료의 EDA(eda/out/dense_dim_breakdown.json)에 따르면 3가지 패턴으로 나뉜다:
| Pattern | fids | dim | 의미 (anonymized 가설) |
| A. Fixed dense vector (ID 없음, 순수 float) | 61, 87 | 256 / 320 | precomputed user embedding 또는 histogram |
| B. Fixed-K aligned profile (ID + weight, K슬롯) | 89, 90, 91 | 10 each | 10-slot user categorical profile (예: top-10 카테고리) |
| C. Variable-length aligned (ID + weight, K ∈ [0, dim]) | 62-66 | 5, 11, 18, 49, 66 | top-K 카테고리 + affinity score (sparse) |
4.1 Aligned <id, weight> 규약
User int와 User dense가 같은 fid를 공유하면 element-wise 짝이 된다.
예시:
user_int_feats_62 = [1, 2, 3] ← 카테고리 ID 3개 user_dense_feats_62 = [10.5, 20, 15.5] ← 그 카테고리에 대한 통계
→ "user가 카테고리 1을 10.5초 봤고, 카테고리 2를 20초, 카테고리 3을 15.5초 봤다" 같은 의미.
이게 verified shared fids {62, 63, 64, 65, 66, 89, 90, 91} 8개에서 발생. 각 ID에 weight가 짝지어져 있어 gated fusion / attention binding을 시도해볼 만한 자리.
5. 데이터의 핵심 fact 4가지
CLAUDE.md §3 + EDA 결과 종합.
Fact 1 — 12.4% conversion rate (imbalanced)
label_type=1: 876 /label_type=2: 124- → conversion 12.4%. 일반적인 CTR/CVR 예측보단 덜 imbalanced하지만 여전히 한쪽으로 쏠림.
Fact 2 — Sequence 매우 김 (p90 > 1000)
| Domain | p50 | p90 | max | frac_empty |
|---|---|---|---|---|
| a | 577 | 1562 | 1888 | 0.5% |
| b | 405 | 1393 | 1952 | 1.2% |
| c | 322 | 887 | 3894 | 0.2% |
| d | 1035 | 2215 | 3951 | 8.0% ← bimodal |
베이스라인은 64\~128로 truncate → 95%+ 정보 손실. long-seq retrieval (TWIN 등)이 자연스러운 P2 motivation.
Fact 3 — 4 도메인 vocab 거의 disjoint
| Pair | Jaccard |
|---|---|
| a vs c | 0.007 ← 가장 분리 |
| b vs c | 0.010 |
| c vs d | 0.016 |
| b vs d | 0.022 |
| a vs b | 0.079 |
| a vs d | 0.100 ← 가장 가까움 |
→ 4 도메인이 다른 item space. 한 모델로 합쳐 볼 게 아니라 per-domain processing이 자연스러운 설계.
Fact 4 — Target item이 history에 0.4%만 등장 🚨
- target item ∈ user의 어느 도메인 seq: 4/1000 rows (0.4%)
이게 가장 충격적인 fact. 일반적인 추천 task는 user가 본 비슷한 item을 추천하는 거라 collaborative filtering이 잘 통한다. 그런데 TAAC는 target이 user history에 거의 없음 → 새 item을 추천해야 하는 task다.
함의: 추천이라기보다 cold-start 문제에 가깝다. H007 candidate-aware xattn lift가 약했던 이유. user history와 target item을 직접 매칭하는 메커니즘은 한계가 있고, 다른 인덕티브 바이어스가 필요하다 (예: user의 일반적 선호 + item의 일반적 매력도 cross).
6. 데이터 fact → 모델 가설 매핑
데이터 fact를 모델 가설로 연결하면 차별화 포인트가 잡힌다:
| 데이터 fact | 자연스러운 모델 가설 |
| Seq p90 > 1000, 베이스라인 64\~128 truncate | Long-seq retrieval (TWIN, learnable GSU) — H019 첫 성공 신호 |
| 4 도메인 disjoint vocab (Jaccard < 10%) | Per-domain modeling (단순 MoE/PLE 형태는 H012에서 fail, 다른 형태 필요) |
| Target 0.4% in history | candidate-aware cross attn 효과 약함 — 다른 인덕티브 바이어스 필요 |
| Aligned \ | Gated fusion / attention binding — multiply 외 다른 form 시도 (H011 fail의 다음) |
| Conversion 12.4% imbalanced | Focal loss / KLD prior matching (H028, H042) |
| Domain d bimodal (p50 1035, frac_empty 8%) | Activity-conditioned gate (active vs inactive user 분리 처리) |
7. 마무리
데이터 이해 핵심 takeaway 3개:
- 익명화는 제약이자 신호 — feature 의미를 모르니 mechanism으로 풀어야 한다. 추측에 시간 쓰지 말고 fid를 그대로 받아들이고 mechanism을 설계하는 데 집중.
- 시퀀스가 길고 도메인이 disjoint — naive concat은 정보 손실, 도메인별 + 긴 시퀀스 retrieval이 자연스러운 설계 방향.
- Target이 history에 거의 없음 — 추천보단 cold-start에 가깝다. user history-target item 직접 매칭 mechanism 한계 → 다른 형태 필요.
다음 글에선 베이스라인을 직접 학습시켜 첫 점수를 받고, 위 가설들 중 하나를 실험으로 옮긴다.
📄 참고:
- 1편: baseline 이해하기 ↗
- 대회 페이지: algo.qq.com ↗
- 데이터 fact 출처: 동료 EDA(
eda/out/) +data/schema.json실측