Level 2: 수학 기초
📐

Level 2

확률의 기초

베이즈 정리와 AI의 의사결정

3분 24초
확률의 기초 강의 영상
강의 영상 보기 (새 탭에서 재생)YouTube

학습 내용

확률의 기초

학습 목표

이 레슨을 완료하면 여러분은:

  • 확률이 무엇인지, 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

실행해보기: 동전과 주사위 시뮬레이션

python
import 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%)

실행해보기: 조건부 확률 시뮬레이션

python
import 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(가설증거)**사후 확률

실행해보기: 베이즈 정리로 스팸 필터 만들기

python
import 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(지수함수)를 씌워서 큰 값은 더 크게, 작은 값은 더 작게 만들어 차이를 극대화합니다.

소프트맥스 공식

softmax(xi)=exij=1nexj\text{softmax}(x_i) = \frac{e^{x_i}}{\sum_{j=1}^{n} e^{x_j}}

핵심 특징:

  • 모든 출력값이 0~1 사이
  • 모든 출력값의 합 = 1 (확률의 조건!)
  • 가장 큰 입력값이 가장 큰 확률을 가짐

실행해보기: 소프트맥스 직접 구현하기

python
import 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 예측의 확률적 성격

python
import 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 등 기본 라이브러리를 사용할 수 있습니다.