
학습 내용
확률의 기초
학습 목표
이 레슨을 완료하면 여러분은:
- •확률이 무엇인지, 0과 1 사이의 숫자로 "가능성"을 표현하는 방법을 이해합니다
- •조건부 확률을 일상 예시로 이해하고 계산할 수 있습니다
- •베이즈 정리로 스팸 필터가 어떻게 작동하는지 직접 구현합니다
- •소프트맥스 함수가 신경망 출력을 확률로 바꾸는 원리를 체감합니다
핵심 메시지
"확률은 AI가 세상을 이해하는 언어입니다. AI의 모든 예측은 확률로 표현됩니다."
1. 확률이란 무엇인가?
비유: 일기예보
"내일 비 올 확률 70%"라는 말을 들어본 적 있죠? 이것은 "비슷한 날씨 패턴 100번 중 70번은 비가 왔다"는 뜻입니다.
확률은 어떤 일이 일어날 가능성을 0에서 1 사이 숫자로 표현한 것입니다.
| 확률값 | 의미 | 예시 |
|---|---|---|
| 0 | 절대 일어나지 않음 | 동전을 던져 3이 나올 확률 |
| 0.5 | 반반 | 동전 앞면 |
| 1 | 반드시 일어남 | 1~6 주사위에서 7 이하가 나올 확률 |
| 0.7 | 꽤 높음 | 내일 비 올 확률 |
확률의 기본 규칙
여사건(complement): 어떤 일이 안 일어날 확률 = 1 - (일어날 확률) 비 올 확률이 0.7이면, 안 올 확률은 0.3입니다.
독립 사건: 두 사건이 서로 영향을 주지 않으면, 동시에 일어날 확률은 곱합니다. 동전 앞면 AND 주사위 6 = 0.5 x (1/6) = 0.083
실행해보기: 동전과 주사위 시뮬레이션
pythonimport numpy as np np.random.seed(42) # 동전 던지기 시뮬레이션 n_flips = 10000 coins = np.random.choice(['앞면', '뒷면'], size=n_flips) heads_ratio = np.sum(coins == '앞면') / n_flips print(f'동전 {n_flips}번 던지기:') print(f' 앞면 비율: {heads_ratio:.4f} (이론값: 0.5)') # 주사위 던지기 시뮬레이션 n_rolls = 10000 dice = np.random.randint(1, 7, size=n_rolls) # 1~6 six_ratio = np.sum(dice == 6) / n_rolls print(f'주사위 {n_rolls}번 던지기:') print(f' 6이 나올 비율: {six_ratio:.4f} (이론값: {1/6:.4f})') # 여사건: 6이 안 나올 확률 not_six = np.sum(dice != 6) / n_rolls print(f' 6이 안 나올 비율: {not_six:.4f} (이론값: {5/6:.4f})') # 독립 사건: 동전 앞면 AND 주사위 6 # 이론값: 0.5 * 1/6 = 0.0833 both = 0 for i in range(n_flips): coin = np.random.choice([0, 1]) # 0=뒷면, 1=앞면 die = np.random.randint(1, 7) if coin == 1 and die == 6: both += 1 print(f'동전 앞면 AND 주사위 6: {both/n_flips:.4f} (이론값: {0.5/6:.4f})')
2. 조건부 확률 -- 새로운 정보가 믿음을 바꾼다
비유: 비 오는 날의 우산
"사람들이 우산을 들고 있을 확률"과 "비가 오는 날 사람들이 우산을 들고 있을 확률"은 다릅니다.
조건부 확률 P(A|B) 는 "B가 일어났다는 조건에서 A가 일어날 확률"입니다. "B가 주어졌을 때 A의 확률"이라고 읽습니다.
일상 속 조건부 확률
| 표현 | 수식 | 의미 |
|---|---|---|
| 비 올 때 우산 확률 | P(우산 | 비) |
| 공부하면 합격 확률 | P(합격 | 공부) |
| "무료"가 있으면 스팸 확률 | P(스팸 | "무료") |
조건부 확률 공식
P(A|B) = P(A와 B가 동시에 일어날 확률) / P(B)
예를 들어, 전체 이메일 중:
- •스팸이면서 "무료" 포함: 24%
- •"무료" 포함 이메일 전체: 31%
- •P(스팸|"무료") = 0.24 / 0.31 = 0.774 (약 77%)
실행해보기: 조건부 확률 시뮬레이션
pythonimport numpy as np np.random.seed(42) # 가상의 이메일 데이터 생성 n_emails = 10000 # 30%가 스팸 is_spam = np.random.random(n_emails) < 0.3 # "무료" 단어 포함 확률: 스팸이면 80%, 정상이면 10% has_free = np.zeros(n_emails, dtype=bool) for i in range(n_emails): if is_spam[i]: has_free[i] = np.random.random() < 0.8 # 스팸: 80% else: has_free[i] = np.random.random() < 0.1 # 정상: 10% # 조건부 확률 계산 # P(스팸 | "무료") = "무료"가 있는 이메일 중 스팸의 비율 free_emails = has_free.sum() spam_and_free = (is_spam & has_free).sum() p_spam_given_free = spam_and_free / free_emails print(f'전체 이메일: {n_emails}개') print(f'스팸 이메일: {is_spam.sum()}개 ({is_spam.mean():.1%})') print(f'"무료" 포함: {free_emails}개') print(f'"무료" + 스팸: {spam_and_free}개') print() print(f'P(스팸 | "무료") = {p_spam_given_free:.4f}') print(f'"무료"가 있으면 스팸일 확률이 약 {p_spam_given_free:.0%}!') print() # 비교: "무료"가 없을 때 스팸 확률 no_free_emails = (~has_free).sum() spam_and_no_free = (is_spam & ~has_free).sum() p_spam_given_no_free = spam_and_no_free / no_free_emails print(f'P(스팸 | "무료" 없음) = {p_spam_given_no_free:.4f}') print(f'"무료" 유무로 스팸 확률이 크게 달라집니다!')
3. 베이즈 정리 -- 증거로 믿음을 업데이트하기
비유: 탐정의 추리
탐정이 범인을 추리할 때를 생각해보세요. 처음에는 "용의자 A가 범인일 확률 30%"라고 생각했습니다 (사전 확률). 그런데 새로운 증거(알리바이가 없음)가 나왔습니다. 이 증거를 반영하면 확률이 70%로 올라갑니다 (사후 확률).
베이즈 정리는 바로 이 과정을 수학적으로 정확하게 해주는 공식입니다.
베이즈 정리 공식
P(가설|증거) = P(증거|가설) x P(가설) / P(증거)
| 용어 | 의미 | 스팸 필터 예시 |
|---|---|---|
| P(가설) | 사전 확률 | 스팸일 확률 30% |
| **P(증거 | 가설)** | 우도(likelihood) |
| P(증거) | 증거의 전체 확률 | "무료"가 나타날 전체 확률 |
| **P(가설 | 증거)** | 사후 확률 |
실행해보기: 베이즈 정리로 스팸 필터 만들기
pythonimport numpy as np # === 베이즈 스팸 필터 === # 사전 확률 p_spam = 0.3 # 전체 이메일 중 스팸 비율 p_normal = 1 - p_spam # 정상 이메일 비율 # 우도 (likelihood): 각 단어가 스팸/정상에 나타날 확률 # P(단어 | 스팸), P(단어 | 정상) word_probs = { '무료': {'spam': 0.80, 'normal': 0.10}, '당첨': {'spam': 0.70, 'normal': 0.05}, '안녕': {'spam': 0.20, 'normal': 0.60}, '회의': {'spam': 0.05, 'normal': 0.50}, '클릭': {'spam': 0.60, 'normal': 0.08}, } def bayes_spam_score(words, word_probs, p_spam, p_normal): """베이즈 정리로 스팸 확률 계산""" # 로그를 사용해 곱셈 대신 덧셈 (숫자가 너무 작아지는 것 방지) log_spam = np.log(p_spam) log_normal = np.log(p_normal) for word in words: if word in word_probs: log_spam += np.log(word_probs[word]['spam']) log_normal += np.log(word_probs[word]['normal']) # log를 다시 확률로 변환 max_log = max(log_spam, log_normal) spam_score = np.exp(log_spam - max_log) normal_score = np.exp(log_normal - max_log) p_spam_given_words = spam_score / (spam_score + normal_score) return p_spam_given_words # 테스트 이메일들 test_emails = [ (['무료', '당첨', '클릭'], '무료 당첨! 클릭하세요'), (['안녕', '회의'], '안녕하세요, 회의 일정입니다'), (['무료', '안녕'], '안녕, 무료 샘플 보내드려요'), (['회의', '클릭'], '회의 자료 링크 클릭해주세요'), ] print('=== 베이즈 스팸 필터 결과 ===') print() for words, description in test_emails: score = bayes_spam_score(words, word_probs, p_spam, p_normal) label = '스팸' if score > 0.5 else '정상' print(f'이메일: "{description}"') print(f' 포함 단어: {words}') print(f' 스팸 확률: {score:.1%} -> [{label}]') print()
4. 소프트맥스 -- 숫자를 확률로 바꾸는 마법
비유: 선거 득표율
후보 A가 500표, B가 300표, C가 200표를 받았다면, 득표율은 50%, 30%, 20%입니다. 합하면 100%죠.
소프트맥스도 비슷합니다. 신경망의 출력값(아무 숫자)을 합이 1이 되는 확률로 변환합니다.
다만 단순히 비율을 구하는 게 아니라, exp(지수함수)를 씌워서 큰 값은 더 크게, 작은 값은 더 작게 만들어 차이를 극대화합니다.
소프트맥스 공식
핵심 특징:
- •모든 출력값이 0~1 사이
- •모든 출력값의 합 = 1 (확률의 조건!)
- •가장 큰 입력값이 가장 큰 확률을 가짐
실행해보기: 소프트맥스 직접 구현하기
pythonimport numpy as np def softmax(x): """소프트맥스 함수 구현""" # 오버플로우 방지를 위해 최대값을 빼줌 exp_x = np.exp(x - np.max(x)) return exp_x / np.sum(exp_x) # 예시 1: 신경망의 출력값 (logits) logits = np.array([2.0, 1.0, 0.1]) probs = softmax(logits) print('=== 소프트맥스 변환 ===') print(f'입력 (logits): {logits}') print(f'출력 (확률): {np.round(probs, 4)}') print(f'확률 합계: {np.sum(probs):.6f}') print() # 예시 2: 이미지 분류 (고양이/개/새) labels = ['고양이', '개', '새'] logits2 = np.array([5.0, 2.0, 0.5]) probs2 = softmax(logits2) print('=== 이미지 분류 예시 ===') for label, logit, prob in zip(labels, logits2, probs2): bar = '#' * int(prob * 40) print(f' {label}: logit={logit:.1f} -> 확률={prob:.1%} {bar}') print() # 예시 3: 온도(temperature) 효과 # 온도가 낮으면 -> 확신이 강해짐, 높으면 -> 균등해짐 logits3 = np.array([2.0, 1.0, 0.5]) for temp in [0.5, 1.0, 2.0, 5.0]: probs_t = softmax(logits3 / temp) print(f'온도={temp}: {np.round(probs_t, 3)} ', end='') print(f'(가장 큰 확률: {max(probs_t):.1%})') print() print('온도가 낮을수록 -> 가장 확률 높은 것에 집중') print('온도가 높을수록 -> 골고루 퍼짐 (다양한 선택)') print('ChatGPT의 "temperature" 설정이 바로 이것!')
5. 확률과 AI -- 모든 예측은 확률이다
AI 모델은 "정답"을 출력하는 게 아니라 각 선택지의 확률을 출력합니다.
실행해보기: AI 예측의 확률적 성격
pythonimport numpy as np # ChatGPT의 다음 단어 예측 시뮬레이션 print('=== "오늘 날씨가 정말 ___" 다음 단어 예측 ===') print() words = ['좋다', '춥다', '덥다', '나쁘다', '맑다'] logits = np.array([3.5, 2.0, 1.5, 0.8, 2.8]) # softmax로 확률 변환 def softmax(x): exp_x = np.exp(x - np.max(x)) return exp_x / np.sum(exp_x) probs = softmax(logits) # 결과 출력 for word, prob in sorted(zip(words, probs), key=lambda x: -x[1]): bar = '#' * int(prob * 50) print(f' {word}: {prob:.1%} {bar}') print() print(f'확률 합계: {sum(probs):.4f}') print() # temperature=1로 여러 번 샘플링하면 다른 결과가 나옴 print('=== 같은 입력으로 5번 생성하면 매번 다른 결과! ===') np.random.seed(42) for i in range(5): chosen_idx = np.random.choice(len(words), p=probs) print(f' 시도 {i+1}: "오늘 날씨가 정말 {words[chosen_idx]}"') print() print('확률이 높은 단어가 자주 선택되지만, 매번 같지는 않습니다.') print('이것이 AI가 때로는 창의적이고 때로는 엉뚱한 이유입니다!')
6. 확률 개념과 AI 응용 총정리
| 확률 개념 | 핵심 아이디어 | AI 응용 |
|---|---|---|
| 기본 확률 (0~1) | 가능성을 숫자로 표현 | 모든 예측값은 확률 |
| 여사건 | P(not A) = 1 - P(A) | 이진 분류 (스팸/정상) |
| 독립 사건 | P(A and B) = P(A) x P(B) | 나이브 베이즈 가정 |
| 조건부 확률 | 새 정보로 확률 업데이트 | 문맥에 따른 예측 변화 |
| 베이즈 정리 | 증거로 가설 확률 계산 | 스팸 필터, 의료 진단 |
| 소프트맥스 | 숫자를 확률로 변환 | 신경망 출력층 |
| 온도(temperature) | 확률 분포의 날카로움 조절 | ChatGPT 창의성 조절 |
핵심 요약
| 개념 | 한줄 설명 | 비유 |
|---|---|---|
| 확률 | 0~1 사이의 가능성 숫자 | 일기예보의 강수확률 |
| 조건부 확률 | 조건이 달라지면 확률도 달라진다 | 비 오는 날 우산 확률 |
| 베이즈 정리 | 증거를 보고 믿음을 업데이트 | 탐정의 추리 과정 |
| 소프트맥스 | 아무 숫자를 확률(합=1)로 변환 | 선거 득표율 계산 |
학습 체크리스트
- • 확률이 0~1 사이 값이고, 여사건은 1에서 빼면 됨을 안다
- • 조건부 확률 P(A|B)가 "B일 때 A의 확률"임을 설명할 수 있다
- • 베이즈 정리의 핵심이 "증거로 믿음을 업데이트하는 것"임을 안다
- • 소프트맥스가 신경망 출력을 확률로 바꾸는 함수임을 안다
- • numpy로 동전/주사위 시뮬레이션을 할 수 있다
- • temperature가 AI 출력의 다양성을 조절함을 이해한다
다음 강의 예고
"확률분포" 정규분포와 AI에서의 활용! 가중치 초기화와 생성 AI의 비밀을 배웁니다.
레슨 정보
- 레벨
- Level 2: 수학 기초
- 예상 소요 시간
- 3분 24초
- 참고 영상
- YouTube 링크
💡실습 환경 안내
코드 블록의 ▶ 실행 버튼을 누르면 브라우저에서 바로 Python을 실행할 수 있습니다.
별도 설치 없이 NumPy, Matplotlib 등 기본 라이브러리를 사용할 수 있습니다.