
학습 내용
통계 기초 - 데이터를 한눈에 요약하는 기술
Level 2 마지막 강의입니다! 끝까지 화이팅!
학습 목표
이 레슨을 마치면 여러분은:
- •평균, 중앙값, 최빈값의 차이를 이해하고 Python으로 계산합니다
- •분산과 표준편차로 데이터의 퍼짐을 측정할 수 있습니다
- •상관계수로 두 변수 사이의 관계를 파악하고 시각화합니다
- •Min-Max 정규화와 Z-score 표준화를 직접 구현합니다
- •배치 정규화가 왜 신경망 학습에 도움이 되는지 압니다
"통계는 데이터의 이야기를 들려주는 번역기다. AI는 이 번역을 매 순간 사용한다."
1. 대표값 - 데이터를 한 숫자로 요약하기
비유: 반 학생들의 키를 한마디로?
"우리 반 학생들 키가 어때?" 라고 물으면, "대부분 165cm 정도야" 같은 대표값 하나로 답하게 됩니다. 이 대표값을 구하는 방법이 여러 가지인데, 각각 장단점이 있습니다.
평균 (Mean): 모든 값을 더해서 개수로 나누기
가장 익숙한 방법이죠. 하지만 이상치(극단값)에 약합니다.
중앙값 (Median): 정렬 후 가운데 값
이상치에 영향을 안 받아서, 소득 통계 같은 곳에서 많이 씁니다.
최빈값 (Mode): 가장 많이 나온 값
카테고리 데이터(좋아하는 색상 등)에서 유용합니다.
| 대표값 | 계산법 | 장점 | 단점 |
|---|---|---|---|
| 평균 | 합계 / 개수 | 모든 데이터 반영 | 이상치에 민감 |
| 중앙값 | 정렬 후 가운데 | 이상치에 강함 | 극단값 무시 |
| 최빈값 | 가장 빈번한 값 | 카테고리에 유용 | 연속 데이터에 부적합 |
실행해보기: 세 가지 대표값 비교
pythonimport numpy as np import matplotlib.pyplot as plt # 시나리오: 회사 직원 10명의 월급 (단위: 만원) salaries = np.array([250, 280, 300, 310, 320, 330, 350, 370, 400, 2000]) # 마지막 한 명이 CEO라서 월급이 매우 높음! mean_val = np.mean(salaries) median_val = np.median(salaries) # 최빈값은 numpy에 없으므로 직접 계산 values, counts = np.unique(salaries, return_counts=True) mode_val = values[np.argmax(counts)] plt.figure(figsize=(10, 5)) plt.bar(range(len(salaries)), sorted(salaries), color='#4ECDC4', edgecolor='black', linewidth=1) plt.axhline(y=mean_val, color='red', linestyle='--', linewidth=2, label=f'Mean: {mean_val:.0f}') plt.axhline(y=median_val, color='blue', linestyle='--', linewidth=2, label=f'Median: {median_val:.0f}') plt.xlabel('Employee (sorted)', fontsize=13) plt.ylabel('Salary', fontsize=13) plt.title('Mean vs Median with an Outlier', fontsize=14, fontweight='bold') plt.legend(fontsize=12) plt.tight_layout() plt.show() print(f'Data: {sorted(salaries)}') print(f'Mean: {mean_val:.0f} (CEO salary inflates it!)') print(f'Median: {median_val:.0f} (not affected by outlier)') print(f'Mode: {mode_val} (most frequent value)') print() print('When outliers exist, median is more representative!')
CEO 한 명의 높은 월급 때문에 평균이 확 올라갔지만, 중앙값은 거의 영향을 받지 않죠. 이것이 중앙값의 힘입니다!
2. 분산과 표준편차 - 데이터의 퍼짐 측정
비유: 같은 평균, 다른 느낌
두 반의 수학 점수 평균이 둘 다 70점이라고 해봅시다.
- •A반: 65, 68, 70, 72, 75 (다들 비슷비슷)
- •B반: 30, 50, 70, 90, 110 (편차가 엄청 큼)
평균만으로는 이 차이를 알 수 없습니다. 분산과 표준편차가 이 "퍼짐"을 숫자로 알려줍니다.
분산: 평균과의 거리를 제곱해서 평균
왜 제곱할까요? 양수/음수 차이가 서로 상쇄되지 않게 하려고입니다.
표준편차: 분산에 루트
분산은 단위가 "제곱"이라서 직관적이지 않습니다. 루트를 씌우면 원래 단위로 돌아옵니다!
| 측정값 | 공식 | 단위 | 직관성 |
|---|---|---|---|
| 분산 | 편차 제곱의 평균 | 원래 단위의 제곱 | 수학적 편의 |
| 표준편차 | 분산의 제곱근 | 원래 단위 | 사람이 이해하기 쉬움 |
실행해보기: 퍼짐이 다른 두 데이터 비교
pythonimport numpy as np import matplotlib.pyplot as plt np.random.seed(42) # 두 반의 시험 점수 (평균은 비슷, 퍼짐이 다름) class_A = np.random.normal(70, 5, 200) # std=5 (촘촘) class_B = np.random.normal(70, 20, 200) # std=20 (넓게 퍼짐) fig, axes = plt.subplots(1, 2, figsize=(12, 5), sharey=True) axes[0].hist(class_A, bins=20, color='#FF6B6B', edgecolor='black', alpha=0.8, density=True) axes[0].set_title(f'Class A: std={np.std(class_A):.1f}', fontsize=13, fontweight='bold') axes[0].set_xlabel('Score', fontsize=12) axes[0].set_ylabel('Density', fontsize=12) axes[0].set_xlim(0, 140) axes[0].axvline(np.mean(class_A), color='black', linestyle='--', linewidth=2) axes[1].hist(class_B, bins=20, color='#45B7D1', edgecolor='black', alpha=0.8, density=True) axes[1].set_title(f'Class B: std={np.std(class_B):.1f}', fontsize=13, fontweight='bold') axes[1].set_xlabel('Score', fontsize=12) axes[1].set_xlim(0, 140) axes[1].axvline(np.mean(class_B), color='black', linestyle='--', linewidth=2) plt.suptitle('Same Mean, Different Spread', fontsize=15, fontweight='bold', y=1.02) plt.tight_layout() plt.show() print('=== Class A ===') print(f' Mean: {np.mean(class_A):.2f}') print(f' Variance: {np.var(class_A):.2f}') print(f' Std Dev: {np.std(class_A):.2f}') print() print('=== Class B ===') print(f' Mean: {np.mean(class_B):.2f}') print(f' Variance: {np.var(class_B):.2f}') print(f' Std Dev: {np.std(class_B):.2f}') print() print('Same mean, but very different distributions!') print('Standard deviation tells you HOW spread out the data is.')
평균은 비슷한데 표준편차가 4배 차이나니, 그래프 모양이 완전히 다르죠!
3. 상관계수 - 두 변수 사이의 관계
비유: 키와 몸무게의 관계
키가 큰 사람은 몸무게도 무거운 경향이 있죠? 이런 관계를 숫자로 표현하는 것이 상관계수(correlation coefficient) 입니다. -1에서 +1 사이 값을 가집니다.
| 상관계수 r | 의미 | 예시 |
|---|---|---|
| r = +1 | 완벽한 양의 상관 | x 증가하면 y도 반드시 증가 |
| r = 0 | 상관 없음 | x와 y는 무관 |
| r = -1 | 완벽한 음의 상관 | x 증가하면 y는 반드시 감소 |
실행해보기: 상관관계 시각화
pythonimport numpy as np import matplotlib.pyplot as plt np.random.seed(42) n = 100 x = np.random.normal(0, 1, n) y_pos = 0.9 * x + 0.4 * np.random.normal(0, 1, n) y_none = np.random.normal(0, 1, n) y_neg = -0.85 * x + 0.5 * np.random.normal(0, 1, n) fig, axes = plt.subplots(1, 3, figsize=(14, 4.5)) datasets = [ (x, y_pos, 'Strong Positive', '#FF6B6B'), (x, y_none, 'No Correlation', '#4ECDC4'), (x, y_neg, 'Strong Negative', '#45B7D1'), ] for ax, (xi, yi, title, color) in zip(axes, datasets): ax.scatter(xi, yi, alpha=0.6, color=color, edgecolors='black', linewidth=0.5) r = np.corrcoef(xi, yi)[0, 1] ax.set_title(f'{title} (r={r:.2f})', fontsize=12, fontweight='bold') ax.set_xlabel('x', fontsize=11) ax.set_ylabel('y', fontsize=11) ax.grid(True, alpha=0.3) plt.suptitle('Correlation Coefficient Examples', fontsize=14, fontweight='bold', y=1.02) plt.tight_layout() plt.show() for xi, yi, name, _ in datasets: r = np.corrcoef(xi, yi)[0, 1] print(f'{name}: r = {r:.3f}') print() print('In AI, correlation helps with feature selection.') print('Highly correlated features = redundant information!')
AI에서 상관계수는 특성 선택(feature selection) 에 활용됩니다. 상관이 높은 특성들은 중복 정보이므로 하나만 남기면 됩니다!
4. 정규화와 표준화 - 스케일 맞추기
비유: 다른 단위를 같은 척도로
나이(2080세)와 연봉(200010000만원)을 동시에 사용하면,
숫자가 큰 연봉이 학습을 지배해버립니다.
이를 방지하려면 스케일을 맞춰야 합니다.
4-1. Min-Max 정규화: 0~1 사이로 압축
모든 값을 0과 1 사이로 만들어줍니다.
이미지 픽셀값(0255 → 01)에 많이 씁니다.
4-2. Z-score 표준화: 평균=0, 표준편차=1로 변환
데이터를 "평균에서 표준편차 몇 배 떨어져 있는가"로 바꿉니다. 이상치가 있을 때 더 안정적입니다.
| 방법 | 결과 범위 | 장점 | 주요 용도 |
|---|---|---|---|
| Min-Max | 0 ~ 1 | 범위가 직관적 | 이미지, 확률 출력 |
| Z-score | 제한 없음 (평균 0) | 이상치에 강함 | 신경망 입력, 통계 분석 |
실행해보기: 정규화 vs 표준화 비교
pythonimport numpy as np import matplotlib.pyplot as plt np.random.seed(42) ages = np.array([22, 25, 30, 35, 40, 45, 50, 55, 60, 65]) incomes = np.array([2200, 2800, 3500, 4200, 5000, 5500, 6200, 7000, 7500, 8000]) # Min-Max ages_minmax = (ages - ages.min()) / (ages.max() - ages.min()) incomes_minmax = (incomes - incomes.min()) / (incomes.max() - incomes.min()) # Z-score ages_zscore = (ages - np.mean(ages)) / np.std(ages) incomes_zscore = (incomes - np.mean(incomes)) / np.std(incomes) fig, axes = plt.subplots(1, 3, figsize=(15, 5)) axes[0].scatter(ages, incomes, s=100, color='#FF6B6B', edgecolors='black', zorder=5) axes[0].set_xlabel('Age', fontsize=12) axes[0].set_ylabel('Income', fontsize=12) axes[0].set_title('Original (different scales!)', fontsize=13, fontweight='bold') axes[0].grid(True, alpha=0.3) axes[1].scatter(ages_minmax, incomes_minmax, s=100, color='#4ECDC4', edgecolors='black', zorder=5) axes[1].set_xlabel('Age (Min-Max)', fontsize=12) axes[1].set_ylabel('Income (Min-Max)', fontsize=12) axes[1].set_title('Min-Max (0~1 range)', fontsize=13, fontweight='bold') axes[1].grid(True, alpha=0.3) axes[2].scatter(ages_zscore, incomes_zscore, s=100, color='#45B7D1', edgecolors='black', zorder=5) axes[2].set_xlabel('Age (Z-score)', fontsize=12) axes[2].set_ylabel('Income (Z-score)', fontsize=12) axes[2].set_title('Z-score (mean=0, std=1)', fontsize=13, fontweight='bold') axes[2].grid(True, alpha=0.3) plt.suptitle('Normalization vs Standardization', fontsize=15, fontweight='bold', y=1.02) plt.tight_layout() plt.show() print('=== Original ===') print(f' Age range: {ages.min()} ~ {ages.max()}') print(f' Income range: {incomes.min()} ~ {incomes.max()}') print() print('=== After Min-Max ===') print(f' Age range: {ages_minmax.min():.2f} ~ {ages_minmax.max():.2f}') print(f' Income range: {incomes_minmax.min():.2f} ~ {incomes_minmax.max():.2f}') print() print('=== After Z-score ===') print(f' Age mean={np.mean(ages_zscore):.4f}, std={np.std(ages_zscore):.4f}') print(f' Income mean={np.mean(incomes_zscore):.4f}, std={np.std(incomes_zscore):.4f}') print() print('Now both features are on the same scale!')
원본에서는 연봉의 숫자가 압도적으로 크지만, 정규화/표준화 후에는 두 특성이 같은 척도에서 비교됩니다. 신경망에 데이터를 넣기 전에 거의 항상 이 작업을 해줍니다!
5. 배치 정규화 (Batch Normalization)
비유: 층마다 스케일 리셋
신경망은 층(layer)이 여러 개 쌓여 있죠. 데이터가 층을 통과하면서 스케일이 점점 변해서 학습이 불안정해질 수 있습니다.
배치 정규화는 각 층에서 데이터의 평균과 분산을 다시 맞춰주는 기법입니다. 마치 매 층마다 "스케일 리셋 버튼"을 누르는 것과 같습니다.
배치 정규화의 효과:
| 효과 | 설명 |
|---|---|
| 학습 안정화 | 값이 폭발하거나 소멸하는 것을 방지 |
| 빠른 학습 | 더 큰 학습률을 사용할 수 있음 |
| 정규화 효과 | 드롭아웃 없이도 과적합 방지에 도움 |
현대 신경망에서는 거의 필수적으로 사용됩니다. 이전 레슨에서 배운 Z-score 표준화를 신경망 안에서 자동으로 해주는 것이라고 이해하면 됩니다!
Level 2 완료를 축하합니다!
여기까지 오셨다면 정말 대단합니다! Level 2에서 배운 내용을 정리해봅시다:
- •함수와 그래프: AI 모델의 기본 구조
- •미분, 편미분, 연쇄법칙: 경사하강법과 역전파의 수학적 기초
- •벡터와 행렬: AI가 데이터를 처리하는 형식
- •확률과 확률분포: AI가 불확실성을 다루는 언어
- •통계 기초: 데이터를 요약하고 전처리하는 도구
이 수학적 기초 위에 Level 3에서는 딥러닝의 핵심을 배웁니다!
핵심 요약
| 개념 | 공식/의미 | AI에서의 역할 |
|---|---|---|
| 평균 (Mean) | 합계 / 개수 | 데이터 중심, 손실함수 계산 |
| 중앙값 (Median) | 정렬 후 가운데 | 이상치에 강한 대표값 |
| 분산 (Variance) | 편차 제곱의 평균 | 데이터 퍼짐의 수학적 표현 |
| 표준편차 (Std) | 분산의 제곱근 | 직관적 퍼짐 측정 |
| 상관계수 | -1 ~ +1 | 특성 선택, 중복 제거 |
| Min-Max 정규화 | (x-min)/(max-min) | 0~1 범위 변환 |
| Z-score 표준화 | (x-mu)/sigma | 평균0, 표준편차1 변환 |
| 배치 정규화 | 층별 자동 표준화 | 학습 안정화 |
학습 체크리스트
- • 평균, 중앙값, 최빈값의 차이를 설명할 수 있다
- • 분산과 표준편차가 "퍼짐"을 측정한다는 것을 안다
- • 상관계수 +1, 0, -1의 의미를 설명할 수 있다
- • Min-Max 정규화와 Z-score 표준화의 차이를 안다
- • Python으로 기초 통계량을 계산하고 시각화할 수 있다
- • 배치 정규화가 신경망 학습을 안정시키는 이유를 안다
다음 단계: Level 3 - 딥러닝 핵심
Level 2의 수학 기초를 바탕으로, 손실 함수, 경사하강법, 역전파, 활성화 함수 등 딥러닝의 핵심 메커니즘을 배웁니다!
레슨 정보
- 레벨
- Level 2: 수학 기초
- 예상 소요 시간
- 7분 15초
- 참고 영상
- YouTube 링크
💡실습 환경 안내
코드 블록의 ▶ 실행 버튼을 누르면 브라우저에서 바로 Python을 실행할 수 있습니다.
별도 설치 없이 NumPy, Matplotlib 등 기본 라이브러리를 사용할 수 있습니다.