회사 상품 추천 모델 만들기 (7) 작은 시너지, 큰 교훈, 과적합 안정화와 회고
단독으로 회귀했던 learning rate 변경이 정규화 강화와 결합되면 시너지를 낸 과정. 학습 곡선의 정점이 epoch 1에서 10으로 이동한 이유, 그리고 7부작 전체에서 여전히 모르는 것 위주의 회고.
회사 상품 추천 모델 만들기 (7) 작은 시너지, 큰 교훈, 과적합 안정화와 회고
앞 편 요약: #6에서 네 가지 실패를 가정 종류별(데이터·피처·구현·수학적)로 분류했습니다. 그 중 learning rate 변경(D_lr)은 단독으로 회귀했고, 정규화 강화(D_reg)는 단독으로 유효했습니다.
이 편의 핵심 트레이드오프는 “하이퍼파라미터를 독립적으로 볼 것인가, 상호작용으로 볼 것인가”였습니다. 결론은 단독 변경의 결과만 보면 결합의 시너지를 놓친다는 것이었습니다. 그리고 이 시너지가 시리즈 마지막 단계의 결과를 만들었습니다.
이 편의 절반은 회고입니다. 알게 된 것보다 여전히 모르는 것에 더 큰 지면을 할애했습니다. 시리즈를 마칠 때 가장 정직한 마무리라고 생각해서입니다.
1. 과적합 진단: CB의 학습 곡선
#4에서 채택한 wb_rs 위에 #6의 실험을 거치며 정착한 베이스를 “CB”(content baseline)로 불렀습니다. 5-seed mean=0.0573±0.0021. 안정적이지만 학습 곡선을 보면 이상한 패턴이 있었습니다.
e1=0.0379 e2=0.0539 e3=0.0569 e4=0.0518 e5=0.0506
e6=0.0574 e7=0.0521 e8=0.0509 e9=0.0491
loss: 3.93 ──────────────────────────────→ 3.14train loss는 매끄럽게 감소하는데, val recall은 epoch 3에서 정점을 찍었다가 진동하면서 하락합니다. e6에서 한 번 더 회복하고 다시 하락. 자료를 찾아보니 전형적인 과적합 + LR 노이즈 패턴이라고 합니다.
2. 두 가지 변경의 단독 효과
이 패턴을 잡기 위해 두 변경을 따로 시도했습니다.
D_lr (learning rate 변경)
학습 후반의 진동을 줄이기 위해 LR(learning rate, 학습률)을 낮추고 cosine annealing(코사인 모양으로 학습률을 천천히 줄이는 스케줄) 스케줄을 도입했습니다.
학습률(learning rate)·epoch·스케줄
#3에서 학습을 “틀린 만큼 한 걸음씩 내려가기”로 설명했습니다. 학습률(learning rate) 은 그 한 걸음의 보폭입니다. 보폭이 너무 크면 골짜기를 건너뛰며 진동하고, 너무 작으면 바닥에 닿기도 전에 시간이 다 갑니다.
epoch(에폭) 는 학습 데이터를 처음부터 끝까지 한 바퀴 도는 것을 말합니다. 10 epoch면 같은 데이터를 열 번 반복해 본다는 뜻이고, 한 epoch는 다시 여러 개의 작은 묶음(step·배치)으로 나뉩니다.
cosine annealing 은 학습이 진행될수록 보폭을 코사인 곡선 모양으로 서서히 줄이는 방법입니다. 처음엔 큰 걸음으로 빠르게 내려오다가 골짜기 근처에선 조심스럽게 줄여 안착시키는 전략입니다. 다만 보폭을 너무 일찍 줄이면 정작 바닥에 닿기 전에 멈춰버리는데, 이 편에서 D_lr이 단독으로 회귀한 게 바로 그 경우였습니다.
| 항목 | CB | D_lr |
|---|---|---|
| learning_rate | 1e-3 | 3e-4 |
| schedule | constant | CosineAnnealingLR(T_max=30) |
| num_epochs | 10 | 30 (cosine을 여유롭게) |
| patience | 3 | 4 |
기대: 후반 진동 감소, 더 안정적인 정점.
결과(3-seed 스크리닝):
| 변형 | mean | best_epoch | 판정 |
|---|---|---|---|
| CB | 0.0594 | 6 | 베이스 |
| D_lr | 0.0543 | 7 | 단독은 회귀 |
회귀였습니다. LR을 낮춰 진동은 줄었지만, 그 LR이 정점에 도달하기에는 부족했다는 추정입니다. cosine annealing이 후반에 LR을 더 낮추면서 모델이 충분히 학습되지 못한 채로 학습이 끝났습니다.
D_reg (regularization 강화)
과적합을 직접 잡기 위해 정규화를 강화했습니다.
| 항목 | CB | D_reg |
|---|---|---|
| dropout | 0.2 | 0.35 |
| weight_decay | 1e-5 | 1e-4 |
정규화: weight decay와 dropout, 그리고 patience
정규화(regularization) 는 모델이 학습 데이터를 통째로 외우는(과적합) 걸 막는 장치들을 통칭하는 말입니다.
weight decay(가중치 감쇠) 는 모델 내부의 숫자(가중치)가 너무 커지지 않도록 매 걸음 살짝 0 쪽으로 잡아당기는 것입니다. 특정 입력 하나에 과하게 민감해지는 걸 눌러 일반화를 돕습니다. 값을 1e-5에서 1e-4로 올렸다는 건 그 잡아당기는 힘을 10배로 키웠다는 뜻입니다.
dropout 은 (#3에서 봤듯) 학습할 때마다 뉴런 일부를 임의로 꺼서, 몇몇 뉴런에만 기대지 못하게 하는 장치입니다. 0.2에서 0.35로 올리면 매번 더 많은 뉴런을 끄는 셈입니다.
patience(인내) 는 early stopping(조기 종료)의 설정값입니다. val 성능이 더 나아지지 않는 epoch가 patience만큼(예: 3번) 연속되면 학습을 멈춥니다. 과적합이 본격화되기 전에 끊어주는 안전장치입니다.
결과:
| 변형 | mean | best_epoch | 판정 |
|---|---|---|---|
| CB | 0.0594 | 6 | 베이스 |
| D_reg | 0.0603 | 3 | 단독 유효 |
유의미한 개선이었습니다. 정점이 epoch 6에서 3으로 빨라졌습니다. 모델이 빨리 좋은 지점에 도달했다가 그 이후는 정규화에 막혀 더 못 올라간 모습이었습니다.
여기서 단독 결과만 보면 결정이 명확해 보입니다. D_reg 채택, D_lr 폐기. 그게 greedy 의사결정입니다.
3. 결합 시너지: D_lrreg
#4에서 배운 것이 있었습니다. 단독 1위가 결합 1위가 아닐 수 있다. 단독으로 회귀했던 D_lr을 D_reg와 결합해 보기로 했습니다. 비용은 한 실험 약 15분(5-seed).
| 변형 | mean | std | best | best_epoch | adj_p (vs CB) |
|---|---|---|---|---|---|
| CB | 0.0573 | 0.0021 | 0.0594 | 6 | (기준) |
| D_reg | 0.0609 | 0.0043 | 0.0648 | 1 | 0.037 ✓ |
| D_lrreg (lr + cosine + reg 결합) | 0.0631 | 0.0064 | 0.0688 | 10 | 0.004 ✓✓ |
결합이 단독보다 좋았습니다. 그리고 정점의 epoch가 1에서 10으로 이동했습니다.
왜 시너지가 났는가 (메커니즘 추정)
곡선을 같이 그려보면 답이 보였습니다.
- CB: 빠르게 정점 도달 후 진동·하락 (LR 큼 + 정규화 약함)
- D_reg 단독: 정규화에 막혀 너무 빨리 정점에 도달, 그 이후 학습 신호 못 받음
- D_lr 단독: LR 낮아 진동은 줄었으나 정점에 도달하기 전에 cosine이 학습을 식힘
- D_lrreg: 정규화가 과적합을 막아주는 동안 cosine schedule이 LR을 천천히 낮추면서 느리지만 꾸준히 정점으로 climb. 정점이 epoch 10으로 이동
직관적으로 말하면, D_reg는 천장을 만들고 D_lr은 그 천장까지 가는 시간을 늘려주는 조합이었던 것 같습니다. 단독으로는 한쪽만 작동해 부족했지만, 결합되면 서로의 약점을 가렸습니다.
정직 한 줄: 위 메커니즘 설명은 추정입니다. 더 깊은 메커니즘(왜 best_epoch가 정확히 10인지, 다른 LR/dropout 조합에서도 같은 패턴이 재현되는지)은 충분히 검증하지 못했습니다. “왜 시너지가 나는지 정확히는 모릅니다.”
4. ensemble 시도와 최종 채택
D_lrreg를 5-seed로 재학습(D_lrreg_keep_5)한 결과를 보존해두고, ensemble을 두 가지 시도했습니다.
| 후보 | recall@20 | vs 단일 best |
|---|---|---|
| 단일 best (seed 44, best_epoch=21) | 0.0725 | ★ |
| 5-seed mean | 0.0657 ± 0.0061 | −0.0068 |
| RRF prediction ensemble | 0.0669 | −0.0056 |
| 임베딩 평균 ensemble | 0.0603 | −0.0122 (#6에서 다룬 rotation invariance 실패) |
ensemble들이 단일 best를 못 이깁니다. 서빙 비용이 5배(5개 모델 유지)인데 결과가 더 나쁘다면 채택할 이유가 없었습니다.
최종 채택: D_lrreg 단일 best (seed 44), recall@20 = 0.0725.
정직한 한 줄
0.0725는 행운의 seed입니다. 같은 코드를 새 seed로 다시 돌리면 0.0657 ± 0.0061 분포 안에서 결과가 나옵니다. 즉 다음 번 학습은 0.06대일 가능성이 큽니다. 실제 기대 성능은 0.0657이라고 보는 게 정확하고, 0.0725는 그 분포에서 가장 위에 있는 점일 뿐입니다.
배포 시점에는 단일 best 모델 가중치를 그대로 쓰지만, 다음 라운드 비교의 기준은 5-seed mean으로 잡아야 한다는 게 결론이었습니다.
5. 전체 궤적
7부작 전체에 걸친 recall@20 궤적을 한 표로 정리하면 이렇습니다.
| 단계 | recall@20 | 비고 |
|---|---|---|
| #1 첫 모델 (깨진 상태) | 0.0048 | 인기도 floor의 30%, 작동 안 함 |
| #3 1차 재설계 (콘텐츠 Two-Tower + logQ) | 0.0534 | 11배 향상, 구조적 결함 해소 |
| #4 wb_rs 추가 (피처 확장) | ~0.0581 | wishs_brands + request_signal |
| #6/#7 D_lrreg 안정화 (5-seed mean) | 0.0657 ± 0.0061 | 학습 동역학 개선, 기대 성능 |
| #7 D_lrreg 단일 best (seed 44) | 0.0725 | 정준 채택, 행운 seed |
| 참고 baseline R* (인기도 floor) | 0.0166 | 4.4배 상회 |
이 표를 보면 각 단계가 다른 종류의 문제를 풀었다는 게 드러납니다.
- #3: 구조 문제 (ID emb, logQ 부재)
- #4: 피처 문제 (어떤 신호를 더 줄 것인가)
- #6/#7: 학습 동역학 문제 (LR, 정규화의 상호작용)
각 단계가 다른 도구를 요구했고, 한 도구로 다른 단계의 문제를 풀려고 했다면 다 실패했을 것 같습니다. 처음에는 “모델만 잘 만들면 된다”는 감각이 있었는데, 실무에서는 문제의 층위가 다 다르고 각 층위가 다른 종류의 작업이라는 걸 알게 됐습니다.
6. 회고: 여전히 모르는 것
이 시리즈를 쓰면서 정리해본 결과, 알게 된 것보다 모르는 것이 훨씬 많았습니다.
모델 본체에 대해 모르는 것
- 0.0725가 한계인가: Two-Tower in-batch sampled softmax 구조의 천장 근처라고 추정하지만, 검증하지 못했다. cross-batch negative sampling(arXiv 2110.15154)으로 negative 다양성을 높이면 더 올릴 수 있을지 모른다.
- 이미지 멀티모달의 효과: 99.97%가 CDN 썸네일이라 CLIP으로 인코딩 가능. GPU만 확보되면 시도할 follow-up. 효과는 미지수.
- 검색의도 attention 결합: #6에서 mean-pool로는 안 됐지만 attention으로 정교하게 결합하면 다를 수 있다.
- EMA per-step 재시도: #6의 decay 0.999 per-step 또는 per-epoch에 맞춰 decay 재조정. 둘 중 어느 쪽이 잘 될지 모른다.
평가·방법론에 대해 모르는 것
- 오프라인 ↔ 온라인 일치 여부: recall@20=0.0725가 실제 비즈니스 지표(CTR, ATC, CVR)로 얼마나 옮겨질지 알 수 없다. 다음 단계의 A/B test가 답할 질문.
- MDE 정밀 산출: #5에서 추정만 했고 정밀한 산출은 안 했다. 실험 설계의 최소 표본 크기를 정하는 데 필요.
- 5-seed가 적절한가: N=10으로 늘리면 변동 추정이 더 정확해질 것이다. 비용 대비 가치는 미지수.
- 다른 retrieval 패러다임과의 정직한 비교: LightFM, ALS, neural CF 등을 같은 평가 셋에서 돌려본 적이 없다. “Two-Tower가 이 도메인에서 더 낫다”는 주장은 사실 강하게 검증된 게 아니다.
도메인·서비스에 대해 모르는 것
- 활성 유저 9천 명의 다양성: 평균적인 활성 유저에게 맞춰진 모델이 신규·저활동 유저에게도 같은 품질을 주는지 모른다.
- 카테고리별 성능 분포: 전체 recall@20만 봤고, 카테고리별 분포(예: 여성복은 잘 되고 아동복은 안 되는지)는 측정 안 했다.
- 추천 결과의 다양성·신선도: recall만 봤고, 추천 리스트의 다양성(같은 브랜드만 반복되지 않는지)이나 신선도(최근 상품이 적절히 나오는지)는 평가 인프라가 없다.
- 유저의 명시적 피드백: “이 추천이 별로다” 같은 피드백을 받아본 적이 없다. 오프라인 지표가 실제 만족도와 일치하는지 모른다.
프로젝트 운영에 대해 모르는 것
- 재학습 주기: 주 1회·월 1회 중 어느 게 적절한지. 데이터 churn 속도와 모델 안정성의 균형을 측정해야 함.
- 모니터링 지표: 운영 중 모델이 깨지는 신호를 무엇으로 잡을 것인지. recall@20 모니터링은 무거우니 가벼운 proxy 지표가 필요.
- 롤백 절차: 새 모델이 더 나빠졌을 때 빠르게 이전 모델로 되돌리는 절차가 정해져 있지 않다.
7. 도구 사용에 대한 솔직한 기록
#1~#6 곳곳에서 의사결정 과정과 코드 검증에 LLM(Claude, ChatGPT 등)을 활용했습니다. 어떤 일에 어떻게 썼는지 정직히 정리합니다.
유용했던 영역:
- 논문 요약과 핵심 수식 검증 (Yi et al. 2019 logQ, Izmailov et al. 2018 SWA 등)
- 대안 패러다임 빠른 비교 (CF/CBF/Two-Tower, 단독 ablation/greedy/전수 탐색)
- 코드 리팩토링, 누수 가드 테스트 작성
- 틀린 가설을 더 빨리 인식하기 (EMA decay 0.999가 per-step용이라는 지적은 LLM이 빨리 잡아줬다)
유용하지 않았던 영역:
- 도메인 특화 결정 (churn 46~74%가 의류 도매에서 무엇을 의미하는지, signal weight 5.0이 적절한지)
- 평가 셋 정의 (GT=all vs strong 같은 의사결정의 무게)
- 실패 가설의 근본 원인 추정 (계절 데이터 반증의 원인을 churn으로 좁히는 것은 도메인 데이터를 직접 봐야 가능)
가장 큰 함정: LLM은 그럴듯한 설명을 항상 만들어 줍니다. “왜 D_lrreg가 시너지를 내는가”에 LLM이 그럴듯한 메커니즘 설명을 줘도, 그 설명이 맞는지는 별개입니다. 위 본문에서 “왜 시너지가 났는가”를 추정으로 적고 “정확히는 모른다”고 단서를 단 이유가 이것입니다.
의사결정과 트레이드오프 판단은 본인의 책임이었고, LLM은 검증·요약·반례 제시의 도구로 썼다는 게 가장 정확한 표현인 것 같습니다.
8. 시리즈 마지막 정리
7부작에 걸쳐 다룬 결정의 큰 줄기입니다.
| # | 핵심 결정 |
|---|---|
| 1 | Two-Tower 패러다임 선택 (CF·CBF 비교 후 도메인 적합성) |
| 2 | 후보풀 1.1M → 142K, 운영 안전 장치 |
| 3 | Item ID 임베딩 제거, 콘텐츠 표현 + logQ |
| 4 | 단독 ablation의 한계, 전수 부분집합 탐색으로 wb_rs |
| 5 | best-of-N + R* baseline + paired permutation + Holm |
| 6 | 4가지 실패의 분류학 (데이터·피처·구현·수학적 가정) |
| 7 | D_lrreg 결합 시너지, 5-seed mean=0.0657 (단일 best 0.0725) |
이 시리즈에서 얻은 결과 수치보다 결정의 흐름과 그 흐름에서 배운 것이 더 가치 있다고 생각합니다. 다음 추천 프로젝트(혹은 다른 ML 프로젝트)에서, 이 시리즈를 다시 펴서 “그때 어떤 도구로 어떤 결정을 했더라”를 빠르게 재구성하는 게 이 글의 진짜 용도입니다.
마치며
실무에서 처음 추천 모델을 만들면 어디서 막히는지를 7부작에 담아봤습니다. 막히는 지점은 모델 그 자체보다 모델 주변에 더 많았습니다. 데이터 파이프라인의 누수, 평가 셋 정의의 모호함, 측정의 불확실성, 가설의 잘못된 종류들. 그 주변을 한 번 돌고 나서야 모델 자체의 튜닝이 의미를 가졌습니다.
이 시리즈가 비슷한 위치에서 시작하는 다른 누군가에게, 그리고 무엇보다도 미래의 저에게 길잡이가 되기를 바랍니다.
이 시리즈의 기획·작성에는 Claude/ChatGPT 등의 LLM 도구를 활용했습니다. 의사결정과 트레이드오프 판단은 본인이 했고, 도구는 글 구조 정리·논문 요약 검증·코드 인용 점검에 사용되었습니다. 7편 회고(§7)에 도구 사용의 솔직한 평가를 적어두었습니다.