통계 및 수학¶
면접에서 자주 나오는 통계/수학 질문들
질문 목록¶
선형대수¶
- [ ] 고유값(eigen value)와 고유벡터(eigen vector)에 대해 설명해주세요. 그리고 왜 중요할까요?
확률/통계¶
- [ ] 샘플링(Sampling)과 리샘플링(Resampling)에 대해 설명해주세요
- [ ] 확률 모형과 확률 변수는 무엇일까요?
- [ ] 누적 분포 함수와 확률 밀도 함수는 무엇일까요?
- [ ] 베르누이 분포 / 이항 분포 / 카테고리 분포 / 다항 분포 등에 대해 설명해주세요
- [ ] 조건부 확률은 무엇일까요?
- [ ] 공분산과 상관계수는 무엇일까요?
- [ ] 신뢰 구간의 정의는 무엇인가요?
- [ ] p-value를 고객에게는 뭐라고 설명하는게 이해하기 편할까요?
- [ ] 중심극한정리는 왜 유용한걸까요?
- [ ] 엔트로피(entropy)에 대해 설명해주세요
- [ ] "likelihood"와 "probability"의 차이는 무엇일까요?
- [ ] 베이지안과 프리퀀티스트간의 입장차이를 설명해주실 수 있나요?
- [ ] 검정력(statistical power)은 무엇일까요?
가설검정¶
- [ ] A/B Test 관련 통계적 유의미함 판단 방법은?
- [ ] 정규성 테스트가 빅데이터 시대에 의미 있을까요?
- [ ] 모수적 방법론과 비모수적 방법론을 어떨 때 쓸 수 있나요?
- [ ] 통계에서 사용되는 bootstrap의 의미는 무엇인가요?
- [ ] 필요한 표본의 크기를 어떻게 계산합니까?
- [ ] Bias를 통제하는 방법은 무엇입니까?
회귀분석¶
- [ ] R square의 의미는 무엇인가요?
- [ ] 로그 함수는 어떤 경우 유용합니까?
기술통계¶
- [ ] 평균(mean)과 중앙값(median)중에 어떤 케이스에서 뭐를 써야할까요?
- [ ] 아웃라이어의 판단하는 기준은 무엇인가요?
- [ ] missing value가 있을 경우 채워야 할까요?
응용¶
- [ ] 모수가 매우 적은 케이스의 예측 모델 수립 방법은?
- [ ] 콜센터 통화 지속 시간에 대한 분석 계획을 세워주세요
답변¶
고유값(eigen value)와 고유벡터(eigen vector)에 대해 설명해주세요. 그리고 왜 중요할까요?¶
한 줄 정의¶
행렬 A를 곱해도 방향이 변하지 않고 크기만 λ배 변하는 벡터가 고유벡터, 그 크기 변화량이 고유값
수학적 정의¶
-A: n×n 정방행렬
- v: 고유벡터 (영벡터가 아닌 벡터)
- λ: 고유값 (스칼라)
직관적 이해¶
행렬은 "선형 변환"이다. 대부분의 벡터는 행렬을 곱하면 방향과 크기가 모두 변한다. 하지만 특별한 방향의 벡터는 방향은 유지되고 크기만 늘어나거나 줄어든다. - 이 특별한 방향 = 고유벡터 - 크기가 늘어나는 비율 = 고유값
왜 중요한가?¶
- PCA (주성분 분석)
- 공분산 행렬의 고유벡터 = 데이터 분산이 가장 큰 방향
-
고유값이 큰 순서대로 주성분을 선택 → 차원 축소
-
행렬 분해 (SVD, Spectral Decomposition)
A = VΛV⁻¹형태로 분해 가능-
복잡한 행렬 연산을 단순화
-
딥러닝에서 안정성 분석
- Hessian 행렬의 고유값 → loss surface의 곡률
-
고유값이 모두 양수 → local minimum
-
추천 시스템 (Matrix Factorization)
- User-Item 행렬을 저차원으로 분해
계산 방법¶
import numpy as np
A = np.array([[4, 2], [1, 3]])
eigenvalues, eigenvectors = np.linalg.eig(A)
print(f"고유값: {eigenvalues}") # [5. 2.]
print(f"고유벡터:\n{eigenvectors}") # 각 열이 고유벡터
면접 포인트¶
- "방향 불변, 크기만 변화"라는 핵심 개념
- PCA와의 연결 (가장 자주 물어봄)
- 고유값이 큰 고유벡터 = 데이터의 주요 방향
샘플링(Sampling)과 리샘플링(Resampling)에 대해 설명해주세요¶
한 줄 정의¶
샘플링: 모집단에서 표본 추출 | 리샘플링: 이미 뽑은 표본에서 다시 추출
샘플링 (Sampling)¶
정의: 전체 모집단(population)에서 일부 표본(sample)을 추출하는 것
종류:
| 방법 | 설명 | 예시 |
|------|------|------|
| 단순 무작위 | 모든 개체가 동일한 확률로 선택 | random.sample() |
| 층화 샘플링 | 그룹별로 비율 맞춰 추출 | 남:여 = 6:4 비율 유지 |
| 군집 샘플링 | 그룹 단위로 선택 후 전수조사 | 특정 학교 전체 조사 |
| 체계적 샘플링 | k번째마다 추출 | 매 10번째 고객 |
ML에서 활용: - Train/Test split - Class imbalance 해결 (Oversampling, Undersampling)
리샘플링 (Resampling)¶
정의: 이미 수집된 표본에서 반복적으로 부분집합을 추출하는 것
종류:
- Bootstrap
- 복원 추출로 원본과 같은 크기의 표본 생성
-
신뢰구간 추정, 분산 추정에 활용
-
Cross-Validation
- 데이터를 k개로 나눠 학습/검증 반복
-
모델 성능의 일반화 능력 평가
-
Jackknife
- 한 번에 하나씩 제외하고 통계량 계산
- Leave-One-Out의 원조
차이점 정리¶
| 구분 | 샘플링 | 리샘플링 |
|---|---|---|
| 대상 | 모집단 → 표본 | 표본 → 표본 |
| 목적 | 데이터 수집 | 통계량 추정, 모델 평가 |
| 예시 | 설문조사 대상 선정 | Bootstrap, CV |
면접 포인트¶
- Bootstrap의 "복원 추출" 개념
- Cross-Validation이 왜 필요한지 (과적합 방지, 일반화 성능 평가)
확률 모형과 확률 변수는 무엇일까요?¶
한 줄 정의¶
확률 변수: 결과를 숫자로 매핑하는 함수 | 확률 모형: 확률 변수의 분포를 수학적으로 표현한 것
확률 변수 (Random Variable)¶
정의: 표본 공간의 각 결과를 실수에 대응시키는 함수
예시: 동전 2번 던지기 - 표본 공간: {HH, HT, TH, TT} - 확률 변수 X = "앞면 개수" - X(HH)=2, X(HT)=1, X(TH)=1, X(TT)=0
종류: | 종류 | 정의 | 예시 | |------|------|------| | 이산 확률 변수 | 셀 수 있는 값 | 주사위 눈, 클릭 수 | | 연속 확률 변수 | 연속적인 값 | 키, 온도, 시간 |
확률 모형 (Probability Model)¶
정의: 확률 변수가 어떤 값을 가질 확률을 수학적으로 기술한 것
구성 요소: 1. 표본 공간 (Sample Space): 가능한 모든 결과 2. 사건 (Event): 표본 공간의 부분집합 3. 확률 함수: 각 사건에 확률 할당
예시:
# 정규분포 확률 모형
# X ~ N(μ=0, σ²=1)
import scipy.stats as stats
model = stats.norm(loc=0, scale=1) # 확률 모형 정의
prob = model.pdf(0) # x=0에서 확률밀도
sample = model.rvs(size=100) # 표본 생성
ML에서의 활용¶
| 개념 | ML 적용 |
|---|---|
| 확률 변수 | 모델 출력 (예측값), 손실 |
| 확률 모형 | 가우시안 나이브베이즈, GMM, VAE의 잠재변수 |
관계¶
면접 포인트¶
- 확률 변수는 함수다 (결과 → 숫자)
- 확률 모형은 분포를 수학적으로 표현한 것
- ML 모델도 일종의 확률 모형 (입력 → 출력 확률분포)
누적 분포 함수와 확률 밀도 함수는 무엇일까요?¶
한 줄 정의¶
PDF: 특정 값에서의 상대적 확률 밀도 | CDF: 특정 값 이하일 확률의 누적
확률 밀도 함수 (PDF: Probability Density Function)¶
정의: 연속 확률 변수가 특정 값 근처에 있을 상대적 가능성
수식:
특징: - f(x) ≥ 0 (항상 양수) - 전체 면적 = 1: ∫[-∞,∞] f(x)dx = 1 - 주의: f(x) 자체는 확률이 아님! 면적이 확률
예시 (정규분포):
import numpy as np
import scipy.stats as stats
x = np.linspace(-3, 3, 100)
pdf = stats.norm.pdf(x, loc=0, scale=1) # 표준정규분포 PDF
누적 분포 함수 (CDF: Cumulative Distribution Function)¶
정의: X가 특정 값 x 이하일 확률
수식:
특징: - 0 ≤ F(x) ≤ 1 - 단조 증가 함수 - F(-∞) = 0, F(∞) = 1
예시:
관계¶
| 함수 | 의미 | 값 범위 | 질문 유형 |
|---|---|---|---|
| 특정 점의 밀도 | [0, ∞) | "x=1.5 근처일 가능성?" | |
| CDF | 누적 확률 | [0, 1] | "x ≤ 1.5일 확률?" |
이산 확률 변수의 경우¶
| 연속 | 이산 |
|---|---|
| PMF (Probability Mass Function) | |
| 적분 | 합 |
| P(X=x) = 0 | P(X=x) > 0 가능 |
면접 포인트¶
- PDF 값 자체는 확률이 아니다 (면적이 확률)
- CDF는 항상 0→1로 증가
- 연속분포에서 P(X=정확히 x) = 0
베르누이 분포 / 이항 분포 / 카테고리 분포 / 다항 분포 등에 대해 설명해주세요¶
한 줄 정의¶
베르누이 ↔ 이항 = 2가지 결과의 1회 vs n회 카테고리 ↔ 다항 = k가지 결과의 1회 vs n회
관계도¶
1회 시행 n회 시행
┌──────────┐ ┌──────────┐
2가지 결과 │ 베르누이 │ ──→ │ 이항 │
(성공/실패) └──────────┘ └──────────┘
k가지 결과 ┌──────────┐ ┌──────────┐
(1,2,...k) │ 카테고리 │ ──→ │ 다항 │
└──────────┘ └──────────┘
1. 베르누이 분포 (Bernoulli)¶
정의: 성공(1) 또는 실패(0), 단 1회 시행
예시: 동전 1번 던지기, 광고 클릭 여부
2. 이항 분포 (Binomial)¶
정의: n번의 독립적인 베르누이 시행에서 성공 횟수
예시: 동전 10번 던져서 앞면 나오는 횟수
3. 카테고리 분포 (Categorical)¶
정의: k개의 결과 중 하나, 단 1회 시행 (= 일반화된 베르누이)
예시: 주사위 1번 던지기, 분류 모델의 softmax 출력
4. 다항 분포 (Multinomial)¶
정의: n번의 독립적인 카테고리 시행에서 각 결과의 횟수 (= 일반화된 이항)
예시: 주사위 60번 던져서 각 눈이 나온 횟수
from scipy.stats import multinomial
# 주사위 60번: 각 눈이 10번씩 나올 확률
multinomial.pmf([10,10,10,10,10,10], n=60, p=[1/6]*6)
ML에서의 활용¶
| 분포 | ML 적용 |
|---|---|
| 베르누이 | Binary classification의 출력 |
| 이항 | 여러 독립 예측의 성공 횟수 |
| 카테고리 | Multi-class classification (softmax) |
| 다항 | Bag-of-Words, Topic modeling |
면접 포인트¶
- "시행 횟수"와 "결과 개수"로 구분
- 카테고리 = softmax 출력의 확률 분포
- 다항 분포의 각 원소의 합 = n
조건부 확률은 무엇일까요?¶
한 줄 정의¶
어떤 사건 B가 일어났다는 조건 하에 사건 A가 일어날 확률
수식¶
- P(A|B): B가 주어졌을 때 A의 확률
- P(A ∩ B): A와 B가 동시에 일어날 확률
- P(B): B가 일어날 확률 (P(B) > 0)
직관적 이해¶
예시: 주사위를 던졌더니 짝수가 나왔다. 이 중 6일 확률은?
- 전체 표본공간: {1, 2, 3, 4, 5, 6}
- B(짝수): {2, 4, 6} → P(B) = 3/6
- A(6): {6} → P(A ∩ B) = 1/6
- P(A|B) = (1/6) / (3/6) = 1/3
베이즈 정리와의 관계¶
| 용어 | 의미 |
|---|---|
| P(A) | 사전 확률 (Prior) |
| P(A|B) | 사후 확률 (Posterior) |
| P(B|A) | 우도 (Likelihood) |
| P(B) | 정규화 상수 (Evidence) |
ML에서의 활용¶
-
나이브 베이즈 분류기
-
조건부 확률 모델
- Language Model: P(다음 단어 | 이전 단어들)
-
분류: P(레이블 | 입력)
-
체인 룰 (Chain Rule)
→ GPT의 자기회귀 생성 원리
흔한 실수¶
| 혼동 | 실제 의미 |
|---|---|
| P(A|B) = P(B|A)? | ❌ 완전히 다름! |
| P(암|양성) vs P(양성|암) | 전자가 환자 관점에서 중요 |
면접 포인트¶
- 조건이 주어지면 표본공간 축소
- P(A|B) ≠ P(B|A) 강조
- 베이즈 정리로 사후확률 계산
공분산과 상관계수는 무엇일까요?¶
한 줄 정의¶
공분산: 두 변수가 함께 변하는 정도 | 상관계수: 공분산을 -1~1로 정규화한 것
공분산 (Covariance)¶
수식:
해석: - Cov > 0: X 증가 → Y도 증가 경향 (양의 관계) - Cov < 0: X 증가 → Y는 감소 경향 (음의 관계) - Cov = 0: 선형 관계 없음
문제점: 단위에 의존 → 값의 크기로 관계 강도 판단 불가
상관계수 (Correlation Coefficient)¶
피어슨 상관계수:
특징: - 범위: -1 ≤ ρ ≤ 1 - |ρ| = 1: 완벽한 선형 관계 - ρ = 0: 선형 관계 없음 (비선형 관계 가능!) - 단위 무관 (정규화됨)
해석 기준: | 범위 | 관계 강도 | |------|----------| | 0.0 ~ 0.3 | 약함 | | 0.3 ~ 0.7 | 보통 | | 0.7 ~ 1.0 | 강함 |
비교¶
| 특성 | 공분산 | 상관계수 |
|---|---|---|
| 범위 | (-∞, ∞) | [-1, 1] |
| 단위 | 영향 받음 | 무차원 |
| 해석 | 방향만 | 방향 + 강도 |
주의사항¶
- 상관 ≠ 인과
- 아이스크림 판매량 ↔ 익사 사고 (상관 있음)
-
실제 원인: 기온 (교란 변수)
-
선형 관계만 측정
-
이상치에 민감
- 하나의 극단값이 상관계수를 크게 바꿀 수 있음
ML에서의 활용¶
- Feature 선택: 타겟과 상관 높은 변수 선택
- 다중공선성 탐지: 독립변수 간 높은 상관 → VIF 확인
- EDA: 상관 행렬 히트맵
면접 포인트¶
- 공분산의 단위 의존성 문제
- 상관계수는 선형 관계만 측정
- "상관관계 ≠ 인과관계" 반드시 언급
신뢰 구간의 정의는 무엇인가요?¶
한 줄 정의¶
동일한 방법으로 표본을 반복 추출할 때, 95%의 구간이 모수를 포함하는 범위
수식 (95% 신뢰구간, 정규분포 가정)¶
- X̄: 표본 평균
- z: 신뢰수준에 해당하는 z-값 (95% → 1.96)
- σ: 표준편차
- n: 표본 크기
올바른 해석 vs 잘못된 해석¶
| ❌ 잘못된 해석 | ✅ 올바른 해석 |
|---|---|
| "모수가 이 구간에 있을 확률이 95%" | "이 방법으로 100번 구간을 만들면 95번은 모수 포함" |
| 모수는 확률변수가 아님! | 구간이 확률적, 모수는 고정값 |
직관적 이해¶
신뢰수준별 z-값¶
| 신뢰수준 | z-값 |
|---|---|
| 90% | 1.645 |
| 95% | 1.96 |
| 99% | 2.576 |
구간 폭에 영향을 주는 요소¶
| 요소 | 구간 폭 | 이유 |
|---|---|---|
| 신뢰수준 ↑ | 넓어짐 | 더 확실하려면 넓은 그물 |
| 표본 크기 ↑ | 좁아짐 | 정보가 많으면 정밀해짐 |
| 분산 ↑ | 넓어짐 | 데이터가 흩어지면 불확실 |
import scipy.stats as stats
import numpy as np
data = np.random.normal(100, 15, 50) # μ=100, σ=15, n=50
mean = np.mean(data)
se = stats.sem(data) # 표준오차
ci = stats.t.interval(0.95, len(data)-1, loc=mean, scale=se)
print(f"95% CI: {ci}")
ML에서의 활용¶
- 모델 성능 추정: "정확도 = 0.85 (95% CI: 0.82-0.88)"
- A/B 테스트: 두 그룹 차이의 신뢰구간
- 앙상블 모델: 예측 불확실성 정량화
면접 포인트¶
- 모수는 고정값, 구간이 확률적
- "95%의 구간이 모수를 포함" 정확히 표현
- 표본 크기 커지면 구간 좁아짐
p-value를 고객에게는 뭐라고 설명하는게 이해하기 편할까요?¶
한 줄 정의¶
"차이가 없다고 가정했을 때, 이런 결과가 우연히 나올 확률"
고객 친화적 설명¶
비유: 동전 던지기
동전이 공정하다고 가정 (귀무가설)
10번 던져서 10번 다 앞면이 나옴
"공정한 동전이라면 이런 일이 일어날 확률은?" → p-value
p = 0.001 (0.1%)
이렇게 낮으면 "이 동전은 공정하지 않다"고 판단
A/B 테스트 맥락:
정확한 정의 (기술적)¶
- 귀무가설(H₀)이 참일 때, 관측된 결과보다 더 극단적인 결과가 나올 확률
해석 기준¶
| p-value | 해석 | 표기 |
|---|---|---|
| p < 0.01 | 매우 유의 | ** |
| p < 0.05 | 유의 | * |
| p ≥ 0.05 | 유의하지 않음 | ns |
흔한 오해¶
| ❌ 잘못된 해석 | ✅ 올바른 해석 |
|---|---|
| "귀무가설이 참일 확률" | "귀무가설이 참이라면 이런 결과가 나올 확률" |
| "효과 크기를 의미" | 효과 크기와 무관, n이 크면 작은 차이도 유의 |
| "p<0.05면 중요한 발견" | 통계적 유의성 ≠ 실용적 중요성 |
예시 코드¶
from scipy import stats
# A/B 테스트: 전환율 비교
group_a = [1, 0, 1, 1, 0, 1, 0, 0, 1, 1] # 기존
group_b = [1, 1, 1, 1, 0, 1, 1, 0, 1, 1] # 신규
t_stat, p_value = stats.ttest_ind(group_a, group_b)
print(f"p-value: {p_value:.4f}")
if p_value < 0.05:
print("통계적으로 유의한 차이 있음")
else:
print("통계적으로 유의한 차이 없음")
주의사항 (면접에서 언급하면 좋음)¶
- p-hacking 경고: 데이터 보면서 가설을 바꾸면 안 됨
- 다중 검정 문제: 여러 테스트하면 보정 필요 (Bonferroni)
- 표본 크기 영향: n이 크면 작은 차이도 유의해짐
면접 포인트¶
- "우연히 이런 결과가 나올 확률"로 쉽게 설명
- p-value는 효과 크기가 아니라 신뢰도
- "유의하다" ≠ "중요하다"
중심극한정리는 왜 유용한걸까요?¶
한 줄 정의¶
원래 분포가 무엇이든, 표본 평균의 분포는 정규분포에 근사한다 (n이 충분히 클 때)
수학적 표현¶
X₁, X₂, ..., Xₙ이 평균 μ, 분산 σ² 인 모집단에서 추출된 표본이면,
n이 충분히 클 때:
X̄ ~ N(μ, σ²/n)
또는 표준화하면:
Z = (X̄ - μ) / (σ/√n) ~ N(0, 1)
왜 유용한가?¶
-
모집단 분포 몰라도 됨
-
신뢰구간, 가설검정의 기반
- z-test, t-test 모두 CLT 기반
-
"평균이 정규분포를 따른다" 가정 가능
-
표본 크기만 충분하면 OK
- 일반적으로 n ≥ 30이면 충분
- 원본이 극단적으로 비대칭이면 더 필요
시각적 이해¶
import numpy as np
import matplotlib.pyplot as plt
# 지수분포에서 표본 추출 → 평균의 분포
original = []
sample_means = []
for _ in range(10000):
sample = np.random.exponential(scale=1, size=30)
sample_means.append(np.mean(sample))
# sample_means는 정규분포에 근사!
plt.hist(sample_means, bins=50, density=True)
plt.title("표본 평균의 분포 (CLT)")
ML에서의 활용¶
| 상황 | CLT 활용 |
|---|---|
| 배치 평균 | 미니배치 gradient 평균 → 안정적 |
| 앙상블 | 여러 모델 예측 평균 → 분산 감소 |
| 부트스트랩 | 표본 평균의 분포 추정 |
| A/B 테스트 | 전환율 차이의 신뢰구간 |
주의사항¶
- 표본 평균의 분포가 정규화, 원본 아님!
- 이상치 많으면 더 큰 n 필요
- 독립성 가정 필요
면접 포인트¶
- "어떤 분포에서 뽑아도 평균은 정규분포"
- 이것 덕분에 z-test, t-test 사용 가능
- n ≥ 30 언급
엔트로피(entropy)에 대해 설명해주세요¶
한 줄 정의¶
확률 분포의 불확실성(무질서도)을 수치화한 것. 높을수록 예측하기 어려움
수식¶
- p(x): 사건 x가 일어날 확률
- log₂: 보통 log base 2 사용 (단위: bit)
직관적 이해¶
동전 던지기 예시:
| 확률 분포 | 엔트로피 | 불확실성 |
|---|---|---|
| p(앞)=0.5, p(뒤)=0.5 | 1 bit | 최대 (예측 불가) |
| p(앞)=0.9, p(뒤)=0.1 | 0.47 bit | 낮음 (대충 앞면) |
| p(앞)=1.0, p(뒤)=0.0 | 0 bit | 없음 (확실) |
import numpy as np
def entropy(probs):
probs = np.array(probs)
probs = probs[probs > 0] # log(0) 방지
return -np.sum(probs * np.log2(probs))
print(entropy([0.5, 0.5])) # 1.0 (최대 불확실)
print(entropy([0.9, 0.1])) # 0.47
print(entropy([1.0, 0.0])) # 0.0 (확실)
ML에서의 활용¶
- Cross-Entropy Loss (분류)
- p: 실제 분포 (one-hot)
- q: 예측 분포 (softmax 출력)
-
분류 문제의 표준 손실 함수
-
Decision Tree 분할 기준
- Information Gain = 부모 엔트로피 - 자식 엔트로피 가중평균
-
엔트로피 감소가 큰 feature로 분할
-
KL Divergence
- 두 분포의 차이 측정
- VAE의 손실 함수에 사용
엔트로피 vs Cross-Entropy vs KL Divergence¶
| 개념 | 의미 | 수식 |
|---|---|---|
| 엔트로피 H(p) | p의 불확실성 | -Σp log p |
| Cross-Entropy H(p,q) | p 대신 q로 인코딩할 때 비트 수 | -Σp log q |
| KL Divergence | p를 q로 근사할 때 정보 손실 | H(p,q) - H(p) |
시각적 이해¶
면접 포인트¶
- "불확실성의 정량화"
- 균등할수록 엔트로피 높음
- Cross-Entropy Loss와의 연결 (분류에서 왜 쓰는지)
"likelihood"와 "probability"의 차이는 무엇일까요?¶
한 줄 정의¶
Probability: 파라미터 고정, 데이터가 나올 확률 Likelihood: 데이터 고정, 파라미터가 그럴듯한 정도
수식으로 비교¶
같은 함수 f(x|θ)를 다르게 해석:
P(x|θ): θ가 주어졌을 때, x가 나올 확률 (Probability)
L(θ|x): x가 주어졌을 때, θ가 그럴듯한 정도 (Likelihood)
직관적 이해¶
동전 던지기 예시:
관측: 10번 던져서 7번 앞면
[Probability 관점]
"동전이 공정하다면 (θ=0.5), 7번 앞면 나올 확률은?"
→ P(X=7 | θ=0.5) = 0.117
[Likelihood 관점]
"7번 앞면이 나왔는데, θ=0.7일 가능성은?"
→ L(θ=0.7 | X=7) = 0.267 ← 더 그럴듯함!
핵심 차이점¶
| 구분 | Probability | Likelihood |
|---|---|---|
| 고정된 것 | 파라미터 θ | 데이터 x |
| 변하는 것 | 데이터 x | 파라미터 θ |
| 합/적분 | = 1 (확률이므로) | ≠ 1 (확률 아님) |
| 질문 | "이 모델에서 이 데이터?" | "이 데이터에 어떤 모델?" |
ML에서의 활용¶
- Maximum Likelihood Estimation (MLE)
- 관측 데이터를 가장 잘 설명하는 파라미터 찾기
-
대부분의 ML 학습이 MLE 기반
-
Log-Likelihood
- 곱셈 → 덧셈으로 변환 (수치적 안정성)
-
Negative Log-Likelihood = Cross-Entropy Loss
-
베이즈 정리에서
코드 예시¶
from scipy.stats import binom
# 10번 중 7번 앞면 관측
n, k = 10, 7
# Probability: θ=0.5일 때 k=7 나올 확률
prob = binom.pmf(k, n, p=0.5) # 0.117
# Likelihood: 여러 θ에 대해 계산
import numpy as np
thetas = np.linspace(0, 1, 100)
likelihoods = [binom.pmf(k, n, p=theta) for theta in thetas]
# MLE: likelihood 최대화하는 θ
mle_theta = thetas[np.argmax(likelihoods)] # ≈ 0.7
면접 포인트¶
- "무엇을 고정하느냐"가 핵심
- Likelihood는 확률이 아님 (합이 1이 아님)
- MLE = "데이터를 가장 잘 설명하는 파라미터"
베이지안과 프리퀀티스트간의 입장차이를 설명해주실 수 있나요?¶
한 줄 정의¶
Frequentist: 확률 = 무한 반복 시 빈도 | Bayesian: 확률 = 믿음의 정도 (사전지식 반영)
핵심 차이점¶
| 관점 | Frequentist | Bayesian |
|---|---|---|
| 확률의 정의 | 장기적 빈도 (객관적) | 믿음의 정도 (주관적) |
| 파라미터 θ | 고정된 미지의 값 | 확률분포를 가진 변수 |
| 데이터 | 확률 변수 | 고정된 관측값 |
| 사전 정보 | 사용 안 함 | Prior로 반영 |
| 결과 | 점 추정 + 신뢰구간 | 사후분포 (분포 전체) |
예시: "동전의 앞면 확률은?"¶
Frequentist 접근:
Bayesian 접근:
사전믿음: θ ~ Beta(1, 1) # 균등분포 (모름)
데이터: 1000번 중 700번 앞면
사후분포: θ|data ~ Beta(701, 301)
"θ 자체가 분포를 가지며, 데이터로 믿음을 업데이트"
베이즈 정리¶
| 요소 | 의미 |
|---|---|
| P(θ) | Prior: 사전 믿음 |
| P(Data|θ) | Likelihood: 데이터 우도 |
| P(θ|Data) | Posterior: 사후 믿음 |
장단점 비교¶
| 측면 | Frequentist | Bayesian |
|---|---|---|
| 장점 | 객관적, 계산 간단 | 사전지식 활용, 불확실성 표현 |
| 단점 | 사전정보 무시 | Prior 선택이 주관적, 계산 비쌈 |
| 데이터 적을 때 | 불안정 | Prior로 보완 가능 |
| 해석 | 복잡 (신뢰구간 해석) | 직관적 ("θ가 0.7일 확률 95%") |
ML에서의 적용¶
| 접근 | ML 적용 |
|---|---|
| Frequentist | MLE, 일반 딥러닝, 정규화(L2 = 가우시안 prior의 MAP) |
| Bayesian | Bayesian Neural Network, Gaussian Process, Thompson Sampling |
# Frequentist: 점 추정
from scipy.stats import binom
mle = 700 / 1000 # 0.7
# Bayesian: 사후분포
from scipy.stats import beta
prior = beta(1, 1) # 균등 prior
posterior = beta(1 + 700, 1 + 300) # 사후분포
credible_interval = posterior.interval(0.95) # (0.67, 0.73)
면접 포인트¶
- 파라미터를 고정값 vs 확률변수로 보는지
- Bayesian은 Prior 사용 (장점이자 단점)
- "신뢰구간" vs "신용구간(Credible Interval)" 차이
검정력(statistical power)은 무엇일까요?¶
한 줄 정의¶
실제로 효과가 있을 때, 그것을 올바르게 탐지할 확률 (= 1 - β)
가설 검정의 4가지 결과¶
| H₀ 참 (효과 없음) | H₀ 거짓 (효과 있음) | |
|---|---|---|
| H₀ 기각 | Type I Error (α) | ✅ 올바른 결정 (Power) |
| H₀ 채택 | ✅ 올바른 결정 | Type II Error (β) |
직관적 이해¶
새 약이 실제로 효과가 있다고 가정
검정력 = 0.8 → 100번 실험 중 80번은 "효과 있다"고 탐지
검정력 = 0.5 → 100번 실험 중 50번만 탐지 (동전 던지기 수준!)
검정력에 영향을 주는 요소¶
| 요소 | 검정력 영향 | 이유 |
|---|---|---|
| 표본 크기 ↑ | ↑ 증가 | 더 정밀한 추정 |
| 효과 크기 ↑ | ↑ 증가 | 차이가 크면 탐지 쉬움 |
| 유의수준 α ↑ | ↑ 증가 | 기준 완화 (but Type I Error 증가) |
| 분산 ↓ | ↑ 증가 | 노이즈가 적으면 신호 탐지 쉬움 |
권장 검정력¶
- 0.8 (80%): 일반적인 기준
- 0.9 이상: 중요한 의사결정 시
A/B 테스트에서의 활용¶
from statsmodels.stats.power import TTestIndPower
analysis = TTestIndPower()
# 필요 표본 크기 계산
n = analysis.solve_power(
effect_size=0.2, # Cohen's d (작은 효과)
alpha=0.05, # 유의수준
power=0.8, # 목표 검정력
ratio=1.0 # 두 그룹 비율
)
print(f"각 그룹당 필요 표본: {n:.0f}") # 약 393명
왜 중요한가?¶
- 실험 설계: 필요한 표본 크기 결정
- 비용 효율: 너무 적으면 효과 못 찾고, 너무 많으면 낭비
- 결과 해석: "유의하지 않음" = "효과 없음"이 아닐 수 있음
면접 포인트¶
- "진짜 효과를 찾아낼 확률"
- 0.8 (80%) 기준
- 표본 크기와의 관계 (크면 검정력 상승)
A/B Test 관련 통계적 유의미함 판단 방법은?¶
한 줄 정의¶
p-value < α (보통 0.05)이면 통계적으로 유의미한 차이가 있다고 판단
A/B 테스트 기본 구조¶
판단 방법¶
1. p-value 기반 (Frequentist)
from scipy import stats
# 전환율 예시
conversions_a = [1, 0, 1, 0, 1, 1, 0, ...] # n=1000
conversions_b = [1, 1, 1, 0, 1, 1, 1, ...] # n=1000
# t-test
t_stat, p_value = stats.ttest_ind(conversions_a, conversions_b)
if p_value < 0.05:
print("통계적으로 유의미한 차이!")
2. 신뢰구간 기반
import numpy as np
# 전환율 차이의 신뢰구간
rate_a = np.mean(conversions_a)
rate_b = np.mean(conversions_b)
diff = rate_b - rate_a
# 95% 신뢰구간이 0을 포함하지 않으면 유의
se = np.sqrt(rate_a*(1-rate_a)/len(conversions_a) +
rate_b*(1-rate_b)/len(conversions_b))
ci = (diff - 1.96*se, diff + 1.96*se)
if ci[0] > 0 or ci[1] < 0: # 0을 포함하지 않음
print("통계적으로 유의미!")
3. 베이지안 방법
from scipy.stats import beta
# 사후분포 계산
posterior_a = beta(1 + sum(conversions_a), 1 + len(conversions_a) - sum(conversions_a))
posterior_b = beta(1 + sum(conversions_b), 1 + len(conversions_b) - sum(conversions_b))
# B가 A보다 나을 확률
samples_a = posterior_a.rvs(10000)
samples_b = posterior_b.rvs(10000)
prob_b_better = np.mean(samples_b > samples_a)
print(f"B가 더 좋을 확률: {prob_b_better:.1%}")
체크리스트¶
| 단계 | 확인 사항 |
|---|---|
| 실험 전 | 필요 표본 크기, 검정력 계산 |
| 실험 중 | 무작위 배정, 동시 진행 |
| 실험 후 | p-value, 효과 크기, 신뢰구간 모두 확인 |
주의사항¶
- Peeking Problem: 중간에 여러 번 확인하면 위양성 증가
-
해결: Sequential Testing, Bayesian 방법
-
Multiple Testing: 여러 지표 테스트 시 보정 필요
-
실용적 유의성 ≠ 통계적 유의성
- 전환율 0.01% 상승이 유의해도 의미 없을 수 있음
- MDE (Minimum Detectable Effect) 사전 정의 필요
면접 포인트¶
- p-value < 0.05 기준
- 신뢰구간이 0을 포함하는지 확인
- "통계적 유의" ≠ "실용적 의미" 구분
정규성 테스트가 빅데이터 시대에 의미 있을까요?¶
한 줄 정의¶
빅데이터에서 정규성 테스트는 거의 항상 기각되므로, 실용적 의미가 제한적
왜 의미가 제한적인가?¶
1. n이 크면 작은 편차도 유의해짐
from scipy import stats
import numpy as np
# 거의 정규분포인 데이터
np.random.seed(42)
data = np.random.normal(0, 1, 100000) # 10만개
data = data + 0.001 * data**2 # 아주 미세한 비정규성
# Shapiro-Wilk (5000개까지만)
stat, p = stats.shapiro(data[:5000])
print(f"p-value: {p}") # 거의 0에 가까움 → 기각!
# 눈으로 보면 완전 정규분포처럼 보임
2. 중심극한정리의 힘
정규성 테스트 종류¶
| 방법 | 특징 | Python |
|---|---|---|
| Shapiro-Wilk | 가장 강력, n<5000 | stats.shapiro() |
| Kolmogorov-Smirnov | 표본 크기 무관 | stats.kstest() |
| Anderson-Darling | 꼬리 부분에 민감 | stats.anderson() |
| D'Agostino-Pearson | 왜도+첨도 기반 | stats.normaltest() |
실용적 대안¶
1. 시각적 확인
import matplotlib.pyplot as plt
from scipy import stats
# Q-Q plot
stats.probplot(data, dist="norm", plot=plt)
plt.title("Q-Q Plot")
2. 왜도/첨도 확인
skewness = stats.skew(data) # 0에 가까우면 대칭
kurtosis = stats.kurtosis(data) # 0에 가까우면 정규
# 경험적 기준: |skewness| < 2, |kurtosis| < 7
3. 로버스트 방법 사용 - 비모수적 방법 (Mann-Whitney, Kruskal-Wallis) - 부트스트랩
결론¶
| 상황 | 권장 |
|---|---|
| 소규모 (n < 30) | 정규성 테스트 의미 있음 |
| 중규모 (30 < n < 5000) | 테스트 + 시각적 확인 |
| 대규모 (n > 5000) | 시각적 확인만, CLT 의존 |
면접 포인트¶
- 빅데이터에서 정규성 테스트는 항상 기각됨
- CLT 덕분에 큰 표본에서는 정규성 덜 중요
- 시각적 확인 (Q-Q plot)이 더 실용적
모수적 방법론과 비모수적 방법론을 어떨 때 쓸 수 있나요?¶
한 줄 정의¶
모수적: 분포 가정 O (정규분포 등) | 비모수적: 분포 가정 X
핵심 차이¶
| 구분 | 모수적 (Parametric) | 비모수적 (Non-parametric) |
|---|---|---|
| 분포 가정 | 특정 분포 가정 (정규 등) | 가정 없음 |
| 추정 대상 | 분포의 파라미터 (μ, σ) | 순위, 중앙값 등 |
| 검정력 | 가정 맞으면 높음 | 상대적으로 낮음 |
| 표본 크기 | 작아도 OK (가정 맞으면) | 큰 표본 선호 |
언제 무엇을 쓸까?¶
모수적 방법 사용: - 데이터가 정규분포에 가까움 - 표본 크기가 충분히 큼 (CLT 적용) - 분산 분석 등 복잡한 분석 필요
비모수적 방법 사용: - 정규성 가정 위반 - 극단적 이상치 존재 - 순서형/서열 데이터 - 표본 크기가 매우 작음
대응 관계¶
| 상황 | 모수적 | 비모수적 |
|---|---|---|
| 두 독립 그룹 비교 | t-test | Mann-Whitney U |
| 두 대응 그룹 비교 | paired t-test | Wilcoxon signed-rank |
| 세 그룹 이상 비교 | ANOVA | Kruskal-Wallis |
| 상관 분석 | Pearson | Spearman, Kendall |
코드 예시¶
from scipy import stats
import numpy as np
group_a = [23, 25, 28, 30, 32]
group_b = [30, 35, 37, 40, 45]
# 모수적: t-test (정규성 가정)
t_stat, p_value_t = stats.ttest_ind(group_a, group_b)
# 비모수적: Mann-Whitney U (가정 없음)
u_stat, p_value_u = stats.mannwhitneyu(group_a, group_b)
print(f"t-test p-value: {p_value_t:.4f}")
print(f"Mann-Whitney p-value: {p_value_u:.4f}")
판단 플로우차트¶
데이터 분포 확인
│
├─ 정규분포? ──Yes──→ 모수적 방법
│
└─ No
│
├─ n > 30? ──Yes──→ CLT 적용, 모수적 OK
│
└─ No ──────────→ 비모수적 방법
ML에서의 적용¶
| 유형 | 모수적 | 비모수적 |
|---|---|---|
| 회귀 | Linear Regression | Decision Tree, KNN |
| 분류 | Logistic Regression, LDA | Random Forest, SVM |
| 밀도추정 | GMM | KDE (Kernel Density) |
면접 포인트¶
- 분포 가정 여부가 핵심 차이
- 비모수적 = "분포 무관"이지 "모수 없음"이 아님
- 가정 위반 시 비모수적 방법이 더 안전
통계에서 사용되는 bootstrap의 의미는 무엇인가요?¶
한 줄 정의¶
원본 데이터에서 복원 추출을 반복하여 통계량의 분포를 추정하는 리샘플링 기법
핵심 아이디어¶
절차¶
1. 원본 데이터 (n개)에서 n개를 복원 추출 → 부트스트랩 샘플
2. 부트스트랩 샘플에서 관심 통계량 계산
3. 1-2를 B번 반복 (보통 B=1000~10000)
4. B개의 통계량으로 분포, 신뢰구간 추정
코드 예시¶
import numpy as np
data = np.array([23, 25, 28, 30, 32, 35, 40, 45])
n_bootstrap = 10000
# 부트스트랩으로 평균의 분포 추정
boot_means = []
for _ in range(n_bootstrap):
# 복원 추출 (같은 값이 여러 번 뽑힐 수 있음)
sample = np.random.choice(data, size=len(data), replace=True)
boot_means.append(np.mean(sample))
# 95% 신뢰구간
ci_lower = np.percentile(boot_means, 2.5)
ci_upper = np.percentile(boot_means, 97.5)
print(f"95% CI: [{ci_lower:.2f}, {ci_upper:.2f}]")
왜 유용한가?¶
| 장점 | 설명 |
|---|---|
| 분포 가정 불필요 | 정규분포 등 가정 없이 신뢰구간 추정 |
| 복잡한 통계량 | 중앙값, 분위수, 상관계수 등 공식 없는 통계량도 OK |
| 소표본 | 표본이 작아도 적용 가능 |
| 범용성 | 거의 모든 추정 문제에 적용 가능 |
신뢰구간 계산 방법¶
| 방법 | 설명 | 코드 |
|---|---|---|
| Percentile | 단순 분위수 | np.percentile(boot, [2.5, 97.5]) |
| BCa | 편향 보정 | scipy.stats.bootstrap() |
| Basic | 반사 방법 | 2×원래추정 - percentile |
ML에서의 활용¶
- Bagging (Bootstrap Aggregating)
- Random Forest의 기반
-
여러 부트스트랩 샘플로 모델 학습 → 앙상블
-
모델 불확실성 추정
- 예측값의 신뢰구간
-
Feature importance의 안정성
-
Out-of-Bag (OOB) Error
- 부트스트랩에서 안 뽑힌 샘플로 검증
- 별도 validation set 불필요
주의사항¶
- 원본 데이터가 모집단을 잘 대표해야 함
- 독립성 가정 (시계열에는 Block Bootstrap)
- 극단적 이상치가 있으면 영향 받음
면접 포인트¶
- 복원 추출 (replacement=True)
- 분포 가정 없이 신뢰구간 추정
- Random Forest의 Bagging과 연결
필요한 표본의 크기를 어떻게 계산합니까?¶
한 줄 정의¶
효과 크기, 유의수준, 검정력을 고려하여 원하는 정밀도를 달성할 최소 표본 수 계산
필요한 정보¶
| 요소 | 설명 | 일반적 값 |
|---|---|---|
| α (유의수준) | Type I Error 허용 | 0.05 |
| Power (검정력) | 1 - Type II Error | 0.8 |
| Effect Size | 탐지하고 싶은 최소 차이 | Cohen's d 등 |
| σ (표준편차) | 데이터의 변동성 | 파일럿 데이터에서 |
표본 크기 공식¶
두 그룹 평균 비교 (t-test):
n = 2 × ((z_α + z_β) / d)²
- z_α = 1.96 (α=0.05, 양측)
- z_β = 0.84 (power=0.8)
- d = Cohen's d = (μ1 - μ2) / σ
비율 비교:
Python으로 계산¶
from statsmodels.stats.power import TTestIndPower, NormalIndPower
# 1. 평균 비교 (t-test)
analysis = TTestIndPower()
n = analysis.solve_power(
effect_size=0.5, # Cohen's d: 0.2(소), 0.5(중), 0.8(대)
alpha=0.05,
power=0.8,
ratio=1.0, # 두 그룹 비율
alternative='two-sided'
)
print(f"t-test: 각 그룹 {n:.0f}명 필요") # 약 64명
# 2. 비율 비교 (A/B 테스트)
from statsmodels.stats.power import zt_ind_solve_power
n = zt_ind_solve_power(
effect_size=0.1, # 비율 차이 (예: 5% → 6%)
alpha=0.05,
power=0.8,
ratio=1.0
)
print(f"비율 비교: 각 그룹 {n:.0f}명 필요")
Effect Size 가이드 (Cohen's d)¶
| 크기 | d 값 | 예시 |
|---|---|---|
| 소 (Small) | 0.2 | 미세한 차이 |
| 중 (Medium) | 0.5 | 눈에 보이는 차이 |
| 대 (Large) | 0.8 | 확실한 차이 |
A/B 테스트 실무 예시¶
# 전환율 5% → 6% (상대 20% 개선) 탐지하려면?
from statsmodels.stats.proportion import proportion_effectsize
from statsmodels.stats.power import NormalIndPower
baseline = 0.05
target = 0.06
effect = proportion_effectsize(target, baseline)
power_analysis = NormalIndPower()
n = power_analysis.solve_power(effect, alpha=0.05, power=0.8)
print(f"각 그룹 {n:.0f}명 필요") # 약 3,000명
표본 크기와 Trade-off¶
| 크기 ↑ | 결과 |
|---|---|
| 효과 크기 ↑ | 필요 n ↓ |
| 검정력 ↑ | 필요 n ↑ |
| 유의수준 ↓ | 필요 n ↑ |
| 분산 ↑ | 필요 n ↑ |
면접 포인트¶
- 효과 크기, 검정력, 유의수준 3가지 필요
- 작은 효과 탐지하려면 큰 표본 필요
- A/B 테스트 전에 사전 계산 필수
Bias를 통제하는 방법은 무엇입니까?¶
한 줄 정의¶
체계적 오차(Bias)를 줄이기 위해 실험 설계, 데이터 수집, 분석 단계에서 다양한 통제 기법 적용
Bias의 종류¶
| 유형 | 설명 | 예시 |
|---|---|---|
| 선택 편향 (Selection) | 표본이 모집단을 대표하지 않음 | 온라인 설문 → 인터넷 사용자만 |
| 측정 편향 (Measurement) | 측정 방식의 체계적 오차 | 설문 문항의 유도 |
| 생존 편향 (Survivorship) | 실패 케이스 누락 | 성공 기업만 분석 |
| 확증 편향 (Confirmation) | 원하는 결과만 선택 | 유의미한 결과만 보고 |
| 교란 편향 (Confounding) | 제3의 변수 영향 | 아이스크림 ↔ 익사 |
통제 방법¶
1. 실험 설계 단계
| 방법 | 설명 |
|---|---|
| 무작위 배정 | 처리 그룹 랜덤 할당 |
| 블라인드 | 피험자/연구자가 그룹 모름 |
| 대조군 | 비교 기준 설정 |
| 층화 추출 | 그룹별 비율 유지 |
# 층화 추출로 선택 편향 통제
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(
X, y,
stratify=y, # 클래스 비율 유지
test_size=0.2,
random_state=42
)
2. 데이터 수집 단계
| 방법 | 설명 |
|---|---|
| 표준화된 측정 | 일관된 측정 도구 사용 |
| 다중 소스 | 여러 출처에서 데이터 수집 |
| 대표성 확보 | 모집단 특성 반영 |
3. 분석 단계
| 방법 | 설명 |
|---|---|
| 공변량 통제 | 회귀에서 교란변수 포함 |
| 매칭 | 유사한 특성끼리 비교 |
| Propensity Score | 처리 확률로 보정 |
| Instrumental Variable | 도구변수로 인과추론 |
# 공변량 통제 예시
import statsmodels.formula.api as smf
# 교란변수(age, income) 통제
model = smf.ols('outcome ~ treatment + age + income', data=df)
result = model.fit()
4. ML에서의 Bias 통제
| 문제 | 해결책 |
|---|---|
| Class Imbalance | Oversampling, SMOTE, Class weights |
| High Bias (Underfitting) | 모델 복잡도 증가, Feature 추가 |
| Data Leakage | 올바른 train/test 분리 |
| Sampling Bias | 층화 샘플링, 데이터 증강 |
Bias-Variance Trade-off¶
Total Error = Bias² + Variance + Noise
High Bias: 모델이 너무 단순 → Underfitting
High Variance: 모델이 너무 복잡 → Overfitting
면접 포인트¶
- Bias의 종류를 알고 있는지
- 무작위 배정이 가장 강력한 통제
- ML에서 Bias = Underfitting (다른 맥락)
R square의 의미는 무엇인가요?¶
한 줄 정의¶
종속변수의 변동 중 독립변수로 설명되는 비율 (0~1, 1에 가까울수록 좋음)
수식¶
| 요소 | 의미 |
|---|---|
| SS_tot | 총 변동 = Σ(y - ȳ)² |
| SS_res | 잔차 변동 = Σ(y - ŷ)² |
| SS_reg | 설명된 변동 = SS_tot - SS_res |
해석¶
| R² 값 | 해석 |
|---|---|
| 0.0 | 모델이 아무것도 설명 못함 |
| 0.5 | 변동의 50%를 설명 |
| 1.0 | 완벽하게 설명 (과적합 의심) |
from sklearn.metrics import r2_score
from sklearn.linear_model import LinearRegression
model = LinearRegression()
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
r2 = r2_score(y_test, y_pred)
print(f"R²: {r2:.3f}") # 예: 0.85 → 85% 설명력
주의사항¶
1. 변수 추가하면 항상 R² 증가
2. R²가 높아도 좋은 모델이 아닐 수 있음 - 과적합 가능성 - 인과관계를 의미하지 않음 - 잔차 분석도 필요
3. 분야별 기준이 다름
| 분야 | 좋은 R² |
|---|---|
| 물리학 | > 0.99 |
| 사회과학 | > 0.3 |
| 주가 예측 | > 0.1 |
다른 지표와 비교¶
| 지표 | 특징 |
|---|---|
| R² | 설명력 (0~1) |
| MSE | 절대적 오차 크기 |
| MAE | 이상치에 덜 민감 |
| MAPE | 상대적 오차 (%) |
코드 예시¶
import numpy as np
from sklearn.metrics import r2_score
y_true = np.array([3, 5, 7, 9, 11])
y_pred = np.array([2.8, 5.2, 6.8, 9.1, 11.2])
# R² 직접 계산
ss_res = np.sum((y_true - y_pred) ** 2)
ss_tot = np.sum((y_true - np.mean(y_true)) ** 2)
r2_manual = 1 - (ss_res / ss_tot)
# sklearn 사용
r2_sklearn = r2_score(y_true, y_pred)
print(f"R² (manual): {r2_manual:.4f}") # 0.9926
print(f"R² (sklearn): {r2_sklearn:.4f}") # 0.9926
면접 포인트¶
- "설명된 분산의 비율"
- 변수 추가 시 항상 증가 → Adjusted R² 필요
- 높다고 좋은 모델이 아님 (과적합, 인과 아님)
로그 함수는 어떤 경우 유용합니까?¶
한 줄 정의¶
오른쪽으로 꼬리가 긴 분포를 정규분포에 가깝게 변환하거나, 곱셈을 덧셈으로 바꿀 때 유용
언제 쓰는가?¶
1. 오른쪽 치우친 분포 정규화
import numpy as np
# 소득, 가격 등 오른쪽 꼬리가 긴 데이터
income = np.array([30000, 35000, 40000, 50000, 100000, 500000])
log_income = np.log(income) # 더 정규분포에 가까워짐
2. 곱셈 → 덧셈 변환
3. 지수적 성장 → 선형 변환
4. 탄력성 해석
회귀분석에서의 변환¶
| 모델 | 해석 |
|---|---|
| Y ~ X | X 1단위 ↑ → Y β 단위 ↑ |
| log(Y) ~ X | X 1단위 ↑ → Y β×100% ↑ |
| Y ~ log(X) | X 1% ↑ → Y β/100 단위 ↑ |
| log(Y) ~ log(X) | X 1% ↑ → Y β% ↑ (탄력성) |
ML에서의 활용¶
| 상황 | 로그 사용 |
|---|---|
| Cross-Entropy | -log(p) |
| Log-Likelihood | Σlog P(x) |
| Feature 변환 | 가격, 인구 등 |
| Softmax 안정화 | log-sum-exp trick |
# Log 변환 예시
from sklearn.preprocessing import FunctionTransformer
log_transformer = FunctionTransformer(np.log1p) # log(1+x)
X_log = log_transformer.fit_transform(X)
면접 포인트¶
- 오른쪽 꼬리 분포 정규화
- 곱셈 → 덧셈 (수치적 안정성)
- 회귀에서 탄력성 해석 가능
평균(mean)과 중앙값(median)중에 어떤 케이스에서 뭐를 써야할까요?¶
한 줄 정의¶
평균: 모든 값의 합 / 개수 (이상치에 민감) | 중앙값: 정렬 후 가운데 값 (이상치에 강건)
언제 무엇을 쓸까?¶
| 상황 | 권장 | 이유 |
|---|---|---|
| 정규분포 | 평균 | 평균 = 중앙값 |
| 이상치 있음 | 중앙값 | 극단값 영향 적음 |
| 비대칭 분포 | 중앙값 | "대표값"으로 적절 |
| 총합이 중요 | 평균 | 평균 × n = 합계 |
예시¶
import numpy as np
# 일반적인 데이터
normal_data = [30, 35, 40, 45, 50]
print(f"평균: {np.mean(normal_data)}") # 40
print(f"중앙값: {np.median(normal_data)}") # 40
# 이상치가 있는 데이터 (소득)
income = [30000, 35000, 40000, 45000, 1000000]
print(f"평균: {np.mean(income)}") # 230,000 ← 왜곡!
print(f"중앙값: {np.median(income)}") # 40,000 ← 대표적
실무 사례¶
| 지표 | 권장 |
|---|---|
| 가구 소득 | 중앙값 (부자가 평균 끌어올림) |
| 집값 | 중앙값 |
| 시험 점수 | 평균 (정규분포에 가까움) |
| 응답 시간 | 중앙값 또는 P95 (긴 꼬리) |
비교 시각화¶
면접 포인트¶
- 이상치 있으면 중앙값
- 분포가 대칭이면 평균 ≈ 중앙값
- "대표값"의 목적에 따라 선택
아웃라이어의 판단하는 기준은 무엇인가요?¶
한 줄 정의¶
데이터의 일반적 패턴에서 크게 벗어난 값. IQR, Z-score 등으로 탐지
탐지 방법¶
1. IQR (Interquartile Range) 방법
import numpy as np
Q1 = np.percentile(data, 25)
Q3 = np.percentile(data, 75)
IQR = Q3 - Q1
lower = Q1 - 1.5 * IQR
upper = Q3 + 1.5 * IQR
outliers = data[(data < lower) | (data > upper)]
2. Z-score 방법
- 평균에서 표준편차 3배 이상 - 정규분포 가정3. Modified Z-score (MAD 기반)
median = np.median(data)
MAD = np.median(np.abs(data - median))
modified_z = 0.6745 * (data - median) / MAD
outliers = data[np.abs(modified_z) > 3.5]
4. Isolation Forest (ML 기반)
from sklearn.ensemble import IsolationForest
clf = IsolationForest(contamination=0.1)
pred = clf.fit_predict(data.reshape(-1, 1))
outliers = data[pred == -1]
비교¶
| 방법 | 장점 | 단점 |
|---|---|---|
| IQR | 분포 가정 없음 | 극단값에 민감 |
| Z-score | 해석 쉬움 | 정규분포 가정 |
| MAD | 이상치에 강건 | 계산 복잡 |
| Isolation Forest | 다변량 가능 | 블랙박스 |
이상치 처리 전략¶
| 전략 | 언제 |
|---|---|
| 제거 | 명백한 오류 |
| 대체 | 중앙값, 경계값으로 |
| 변환 | Log, Winsorization |
| 유지 | 의미 있는 극단값 |
| 별도 분석 | 이상 탐지가 목적 |
면접 포인트¶
- IQR: Q1-1.5×IQR ~ Q3+1.5×IQR
- Z-score: |z| > 3
- 제거 전에 왜 이상치인지 확인 필요
missing value가 있을 경우 채워야 할까요?¶
한 줄 정의¶
결측 패턴에 따라 다름. MCAR이면 제거 OK, MAR/MNAR이면 대치 필요
결측 유형 (Missing Mechanism)¶
| 유형 | 설명 | 예시 |
|---|---|---|
| MCAR | 완전 무작위 결측 | 설문지 실수로 누락 |
| MAR | 관측값에 의존 | 고소득자가 소득 미응답 |
| MNAR | 결측값 자체에 의존 | 우울한 사람이 우울 척도 미응답 |
처리 전략¶
1. 제거 (Deletion)
- MCAR일 때만 안전 - 데이터 손실2. 대치 (Imputation)
| 방법 | 코드 | 언제 |
|---|---|---|
| 평균/중앙값 | SimpleImputer(strategy='mean') |
빠른 처리 |
| 최빈값 | SimpleImputer(strategy='most_frequent') |
범주형 |
| KNN | KNNImputer(n_neighbors=5) |
유사 샘플 활용 |
| MICE | IterativeImputer() |
변수 간 관계 반영 |
from sklearn.impute import SimpleImputer, KNNImputer
# 평균 대치
imputer = SimpleImputer(strategy='mean')
X_imputed = imputer.fit_transform(X)
# KNN 대치
knn_imputer = KNNImputer(n_neighbors=5)
X_imputed = knn_imputer.fit_transform(X)
3. 결측 표시 (Missing Indicator)
from sklearn.impute import MissingIndicator
indicator = MissingIndicator()
missing_flags = indicator.fit_transform(X)
# 결측 여부를 새 feature로 추가
결정 플로우¶
결측률 확인
│
├─ > 50%? ─────→ 해당 컬럼 제거 고려
│
└─ ≤ 50%
│
├─ MCAR? ──────→ 제거 또는 단순 대치
│
└─ MAR/MNAR ───→ 다중 대치 (MICE, KNN)
+ 결측 indicator 추가
주의사항¶
- 대치 후 불확실성 증가 (분산 과소추정)
- 다중 대치로 불확실성 반영
- 테스트셋에는 학습셋 통계 사용
면접 포인트¶
- MCAR/MAR/MNAR 구분
- 무조건 채우는 것이 아니라 패턴 분석 먼저
- KNN, MICE 등 고급 기법 언급
모수가 매우 적은 케이스의 예측 모델 수립 방법은?¶
한 줄 정의¶
데이터가 적을 때는 단순한 모델 + 정규화 + 사전지식 활용으로 과적합 방지
전략¶
1. 단순한 모델 선택
| 데이터 크기 | 권장 모델 |
|---|---|
| n < 50 | 선형 모델, 나이브 베이즈 |
| n < 500 | SVM, 결정 트리 |
| n < 5000 | Random Forest, XGBoost |
| n > 5000 | 딥러닝 가능 |
2. 강한 정규화
from sklearn.linear_model import Ridge, Lasso
# L2 정규화 (Ridge) - 큰 alpha
model = Ridge(alpha=10.0)
# L1 정규화 (Lasso) - Feature selection 효과
model = Lasso(alpha=1.0)
3. 데이터 증강 - 이미지: 회전, 뒤집기, 크롭 - 텍스트: 동의어 치환, 역번역 - 표형식: SMOTE (불균형 시)
4. 전이 학습 (Transfer Learning)
# 사전학습 모델 활용
from transformers import AutoModel
model = AutoModel.from_pretrained("bert-base")
# Fine-tuning with small data
5. 베이지안 접근
# Prior로 사전지식 반영
from sklearn.naive_bayes import GaussianNB
model = GaussianNB(var_smoothing=1e-9) # Prior smoothing
6. Cross-Validation 강화
from sklearn.model_selection import LeaveOneOut, cross_val_score
# 데이터 매우 적을 때
loo = LeaveOneOut()
scores = cross_val_score(model, X, y, cv=loo)
비교¶
| 전략 | 핵심 |
|---|---|
| 단순 모델 | Variance ↓ |
| 정규화 | Overfitting 방지 |
| 데이터 증강 | 표본 크기 ↑ |
| 전이 학습 | 외부 지식 활용 |
| 베이지안 | Prior로 불확실성 보완 |
면접 포인트¶
- 단순한 모델이 복잡한 모델보다 유리
- 정규화 강화 (높은 alpha)
- 전이 학습으로 사전지식 활용
콜센터 통화 지속 시간에 대한 분석 계획을 세워주세요¶
한 줄 정의¶
분포 파악 → 세그먼트별 비교 → 요인 분석 → 예측 모델 순으로 진행
분석 프레임워크¶
1단계: 데이터 이해 및 EDA
import pandas as pd
import matplotlib.pyplot as plt
# 기초 통계
df['duration'].describe()
# 분포 확인 (보통 오른쪽 꼬리)
plt.hist(df['duration'], bins=50)
plt.title('통화 시간 분포')
# 로그 변환 후 분포
plt.hist(np.log1p(df['duration']), bins=50)
2단계: 세그먼트별 분석
| 세그먼트 | 분석 내용 |
|---|---|
| 문의 유형 | 결제/배송/환불별 평균 시간 |
| 시간대 | 오전/오후/야간별 차이 |
| 상담원 | 상담원별 효율성 |
| 고객 유형 | 신규/기존 고객 차이 |
# 그룹별 비교
df.groupby('issue_type')['duration'].agg(['mean', 'median', 'std'])
# 통계적 검정 (ANOVA)
from scipy import stats
stats.f_oneway(*[group['duration'] for name, group in df.groupby('issue_type')])
3단계: 요인 분석
import statsmodels.formula.api as smf
# 회귀 분석: 어떤 요인이 통화 시간에 영향?
model = smf.ols('log_duration ~ issue_type + time_slot + agent_exp + is_repeat', data=df)
result = model.fit()
print(result.summary())
4단계: 이상치 탐지
# 비정상적으로 긴 통화 탐지
threshold = df['duration'].quantile(0.99)
long_calls = df[df['duration'] > threshold]
# 원인 분석
long_calls['issue_type'].value_counts()
5단계: 예측 모델 (선택)
from sklearn.ensemble import RandomForestRegressor
# 통화 시간 예측
features = ['issue_type_encoded', 'time_slot', 'customer_history', ...]
X = df[features]
y = df['duration']
model = RandomForestRegressor()
model.fit(X_train, y_train)
주요 인사이트 예시¶
| 발견 | 액션 |
|---|---|
| 환불 문의가 평균 2배 길다 | 환불 프로세스 개선 |
| 특정 상담원이 효율적 | 베스트 프랙티스 공유 |
| 점심 시간에 길어짐 | 인력 재배치 |
면접 포인트¶
- 오른쪽 꼬리 분포 예상 → 중앙값 사용
- 세그먼트별 비교가 핵심 인사이트 제공
- 실무적 액션 연결까지 언급