본문 바로가기
C.W.K.
Stream
Lesson 03 of 07 · published

데이터셋의 크기와 다양성

~18 min · datasets, coverage, sampling

Level 0추측자
0 XP0/55 lessons0/10 achievements
0/150 XP to next level150 XP to go0% complete

크기보다 다양성이 중요하지만, 크기도 충분해야 해

‘사례가 몇 개 필요할까?’는 적절한 질문이 아니야. 이렇게 물어야 해. ‘중요한 동작을 모두 대표하면서 회귀를 감지할 만큼 충분한 표본을 갖췄을까?’

통계적으로 필요한 최소 표본 수

이진 통과·실패 지표에서 95% 신뢰수준으로 통과율의 5%p 변화를 감지하려면 대략 400개 사례가 필요해. 10%p 변화를 감지하려면 약 100개가 필요해. 사례가 20개뿐이면 평균이 10%p 움직여도 실제 회귀와 무작위 잡음을 구분하기 어려워.

다양성을 구성하는 차원

  • 주제 / 분야 — 코딩, 의료, 법률, 가벼운 대화는 모두 서로 다른 방식으로 실패해.
  • 난이도 — 쉬움, 중간, 어려움, 경계 사례를 모두 포함해. 쉬운 사례만 있는 평가 모음은 중요한 회귀를 숨겨.
  • 길이 — 짧은 입력과 긴 입력은 서로 다른 모델 동작을 유발해. 항상 둘 다 포함해.
  • 언어 / 지역 — 적어도 사용자가 가장 많이 쓰는 세 가지 언어를 표본에 넣어.
  • 사용자 의도 — 정보 탐색, 특정 페이지·기능으로 이동, 거래 수행, 폭넓은 탐색처럼 서로 다른 의도를 포함해.
  • 시간 — 여러 날에 걸쳐 표본을 수집해. 월요일에만 모은 표본으로는 주말의 요청을 놓칠 수 있어.
원칙: 10개 차원을 고르게 다루는 100개 사례 데이터셋이 비슷한 사례로만 채운 1,000개 사례 데이터셋보다 더 많은 정보를 줘.

불균형은 결과를 왜곡해

데이터셋의 80%가 ‘쉬운 영어 잡담’이라면 평균 통과율도 여기에 크게 좌우되어 나머지 20%에서 발생한 회귀를 숨겨. 종합 점수와 함께 태그별 통과율도 항상 보고해. 종합 점수는 경영진에게 전체 상황을 보여 주고, 태그별 분석은 개발자가 문제를 찾게 해.

Code

이진 통과율 변화 감지에 필요한 표본 크기·python
from math import ceil

def sample_size_for_difference(p1, p2, alpha=0.05, power=0.8):
    """Approximate two-proportion z-test sample size per group."""
    from statistics import NormalDist
    z_alpha = NormalDist().inv_cdf(1 - alpha / 2)
    z_beta  = NormalDist().inv_cdf(power)
    p_bar = (p1 + p2) / 2
    numerator = (z_alpha * (2 * p_bar * (1 - p_bar)) ** 0.5
                 + z_beta * (p1 * (1 - p1) + p2 * (1 - p2)) ** 0.5) ** 2
    return ceil(numerator / (p1 - p2) ** 2)

print(sample_size_for_difference(0.90, 0.85))  # ~462 — to detect a 5pt drop
print(sample_size_for_difference(0.90, 0.80))  # ~120 — to detect a 10pt drop
종합 점수보다 유용한 태그별 통과율·python
from collections import defaultdict

def pass_rate_by_tag(results):
    by_tag = defaultdict(lambda: [0, 0])  # [passed, total]
    for r in results:
        for tag in r["tags"]:
            by_tag[tag][1] += 1
            if r["score"] >= 1.0:
                by_tag[tag][0] += 1
    return {tag: passed / total for tag, (passed, total) in by_tag.items()}

# Output:
# {"easy": 0.95, "hard": 0.62, "long": 0.71, "polish": 0.40}
# Aggregate said 88%. Polish is on fire.  ← that's the real story

External links

Exercise

제품에 중요한 차원을 나열해. 주제, 길이, 언어, 의도 등을 생각하면 돼. 현재 데이터셋을 이 기준으로 점검하고, 가장 적게 대표된 차원에 이번 주 안으로 사례 10개를 추가해.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.