Cute Hello Kitty 3
본문 바로가기
Data/통계

LS 빅데이터 스쿨 / 확률 변수와 확률 분포

by 민 채 2025. 3. 24.

1. 통계 용어 정리

  1. 랜덤 실험
    랜덤 실험은 가능한 결과가 여러 개 있고 실험 전에 구체적인 결과를 예측할 수 없습니다.
    발생 확률을 수치로 표현할 수 있는 실험입니다.
  • 동전을 한 번 던지는 경우
  • 두 개의 주사위를 동시에 던지는 경우
  • 농구 선수가 자유투를 하는 경우
  • 길거리 설문조사에서 유권자에게 후보에 대한 의견을 묻는 경우
  1. 표본 공간 (S)
    랜덤 실험에서 발생할 수 있는 모든 가능한 결과의 집합을 표본 공간이라 하며 통상적으로 로 표 기합니다 표본 공간의 예로는 다음이 있습니다
  • 동전 던지기의 경우: 앞면, 뒷면
  • 두개의 주사위를 던지는 경우: {(1, 1),(1, 2),…,(6, 6)}
  1. 사건
    사건은 표본 공간 S의 부분집합으로 실험 결과 중 특정 조건을 만족하는 결과들의 집합입니다.
    주로 대문자 알파벳으로 표현됩니다.
  2. 확률 변수
    표본 공간의 원소들에 실수 값을 할당하는 함수입니다.
    확률변수는 일반적으로 대문자 X, Y, Z 등으로 표현됩니다.

2. 베이즈 정리

  • 베이즈 정리는 어떤 사건이 발생할 확률을 업데이트하는 방법을 알려주는 공식입니다.
  • 처음에 알고 있던 확률 (사전 확률) 에 새로운 정보 (증거) 를 반영해서 더 정확한 확률 (사후 확률)을 구하는 데 사용됩니다.

2.1 베이즈 정리 공식

공식은 다음과 같습니다.

 

$ P(A | B) = \frac{P(B | A) \cdot P(A)}{P(B)} $

 

하지만 이 수식만 보면 어려울 수 있으니, 쉽게 풀어서 설명해 보겠습니다.


2.2 실생활 예제

🍊 오렌지 상자에서 썩은 오렌지를 찾는 문제

오렌지가 들어있는 두 개의 상자가 있다고 가정해 봅시다.

  • 첫 번째 상자에는 100개의 오렌지가 있고, 그중 10개, 10% 가 썩었습니다.
  • 두 번째 상자에는 100개의 오렌지가 있고, 그중 20개, 20% 가 썩었습니다.

이제 우리가 무작위로 한 개의 오렌지를 꺼냈는데, 썩어 있었다고 합시다.
그러면 이 오렌지가 첫 번째 상자에서 나왔을 확률은 얼마일까요?

이 문제를 베이즈 정리를 이용해서 해결해 보겠습니다.


2.3 베이즈 정리 적용

우리가 구해야 하는 값은 "썩은 오렌지가 첫 번째 상자에서 나왔을 확률"입니다.
즉, ( P(첫 번째 상자 | 썩은 오렌지) ) 를 구하는 것입니다.

베이즈 정리의 구성 요소를 정리하면 다음과 같습니다.

  1. 사전 확률 Prior Probability
    • 오렌지를 꺼낼 때, 첫 번째 상자를 선택할 확률: 50%
    • 즉, ( P(첫 번째 상자) = 0.5 )
  2. 우도 Likelihood
    • 첫 번째 상자에서 오렌지를 꺼냈을 때, 썩어 있을 확률: 10%
    • 즉, ( P(썩은 오렌지 | 첫 번째 상자) = 0.1 )
  3. 전체 확률 Evidence
    • 전체에서 썩은 오렌지가 나올 확률을 계산해야 합니다.
    • 첫 번째 상자에서 썩은 오렌지가 나올 확률: ( 0.5 \times 0.1 = 0.05 )
    • 두 번째 상자에서 썩은 오렌지가 나올 확률: ( 0.5 \times 0.2 = 0.1 )
    • 전체적으로 썩은 오렌지가 나올 확률: ( 0.05 + 0.1 = 0.15 )

이제 베이즈 정리를 적용합니다.

 

$$
P(\text{첫 번째 상자} | \text{썩은 오렌지}) = \frac{0.1 \times 0.5}{0.15} = \frac{0.05}{0.15} = 0.3333
$$

 

즉, 썩은 오렌지를 발견했을 때, 그것이 첫 번째 상자에서 나왔을 확률은 33.33% 입니다.


2.4 핵심 정리

베이즈 정리는 다음과 같은 원리를 따릅니다.

  1. 처음에 알고 있는 확률, 사전 확률: "이게 일어날 가능성이 얼마나 될까?"
  2. 새로운 정보, 증거: "새로운 단서가 추가되었을 때, 이 확률이 어떻게 변할까?"
  3. 업데이트된 확률, 사후 확률: "새로운 정보를 반영했을 때, 더 정확한 확률은 얼마일까?"

2.5 예제 문제 1

한 소프트웨어 회사에서 각 버전의 소프트웨어에
대해 버그 발생 비율을 조사한 결과는 다음과 같습니다.

버전 비율 버그 발생 확률
2022 0.16 0.05
2021 0.18 0.02
2020 0.20 0.03
기타 0.46 0.04

소프트웨어 버전이 2022, 2021, 2020인 소프트웨어 중 하나에서 버그가 발생했다고 합니다.
이 소프트웨어가 2022 버전일 확률을 계산하십시오. 소수점 셋째 자리에서 반올림하세요.

p_2022 = 0.16 * 0.05
p_2021 = 0.18 * 0.02
p_2020 = 0.20 * 0.03
p_bug = p_2022 + p_2021 + p_2020

p_2022_bug = p_2022 / p_bug

# 소수점 셋째 자리에서 반올림
round(p_2022_bug, 2)

2.6 예제 문제 2

한 회사에서 무작위로 선택된 직원이 건강 문제가 있을 확률은 0.25입니다.
건강 문제가 있는 직원은 건강 문제가 없는 직원보다 흡연자일 확률이 두 배 높습니다.

직원이 흡연자라는 사실을 알았을 때, 그가 건강 문제를 가지고 있을 확률을 계산하십시오.

# x에 어떤 숫자를 넣어도 상관 없다.
x = 3333
p_smoke_problem = 1/4 * x * 2
p_smoke_normal = 3/4 * x

p_smoke = p_smoke_normal + p_smoke_problem
ans = p_smoke_problem / p_smoke

확률 변수와 확률 분포 실습

1. 베르누이 분포

1.1 베르누이 분포 개념

  • 베르누이 분포는 실행 결과가 0 또는 1 두 가지 값만을 가지는 확률 분포입니다.
  • 예시: 동전 던지기

1.2 베르누이 분포 함수 구현

  • bernoulli() 함수 구현
  • 10,000,000번 실행하여 확률 확인
def bernoulli():
rng = np.random.default_rng()
return int(rng.uniform(0, 1) <= 0.5)
  • rng = np.random.default_rng() 을 통해 0 이상 1 미만의 균등 분포(Uniform Distribution)를 따르는 난수를 생성
  • <= 0.5 조건문 실행을 통해 50%의 확률로 True 를 반환하거나 False 를 반환합니다.
  • int() 를 사용하여 True 는 1로, False 는 0 으로 반환합니다.
  • 함수를 여러번 실행하면 1 또는 0 이 무작위로 return 됩니다.
cnt = 0
for i in range(10_000_000):
    cnt += bernoulli()
print(cnt / 10_000_000)   # 0.5001187
  • 10, 000, 000회 실행한 결과
  • 약 50% 의 확률로 1이 나온다는 것을 알 수 있다.

2. 확률 변수 이해하기

2.1 확률 변수 개념

확률 변수는 확률적으로 결정되는 값 을 의미합니다.
예를 들어, 동전을 던졌을 때, 주사위를 굴렸을 때, 시험 점수 등이 확률 변수입니다.
확률 변수에는 각 값이 나올 확률이 존재하며, 이를 확률 분포 라고 합니다.

 

예시

  • 확률 변수 X가 가질 수 있는 값: 0, 1, 2
  • 각 값에 대한 확률: [0.2, 0.5, 0.3]
p = [0.2, 0.5, 0.3]

def event_x():
    rng = np.random.default_rng()
    u = rng.uniform(0, 1)
    if u <= 0.2:    # 0% ~ 20%
        return 0
    elif u <= 0.7:  # 20% ~ 70%
        return 1
    else:
        return 2
event_x()

2.2 확률 변수 생성 최적화

  • X(size) : numpy 벡터 연산 활용
  • for_X(size) : for loop를 활용한 확률 변수 생성
  1. numpy 를 활용한 연산
# 확률 변수 X가 가질 수 있는 값
choice = np.array([0, 1, 2])    

def X(size):
    rng = np.random.default_rng()
    u = rng.uniform(0, 1, size)
    condition = np.array([u <= 0.2, u <= 0.7, u < 1])
    return np.select(condition, choice)
  • np.select()를 사용하여 조건에 맞는 값을 효율적으로 선택
  1. for loop를 활용한 연산
def for_X(size):
    rng = np.random.default_rng()
    u = rng.uniform(0, 1, size)
    for i in range(size):
        if u[i] <= 0.2:
            u[i] = 0
        elif u[i] <= 0.7:
            u[i] = 1
        else:
            u[i] = 2
    return u
  • for 문을 통해 반복문 실행

2.3 연산 속도 비교

import time 을 통해 numpy 연산과 for loop 연산의 속도를 비교

# numpy 연산속도
start = time.time()
X(10_000_000)
end = time.time()
numpy_speed = end - start

# for loop 연산 속도
start = time.time()
for_X(10_000_000)
end = time.time()
for_loop_speed = end - start

# 연산 속도 차이 비교
print(f'numpy: {round(numpy_speed, 2)}, for_loop: {round(for_loop_speed, 2)}')

# numpy: 0.18, for_loop: 2.1
  • 결과 값을 보면 표본이 10,000,000개 일 때 약 10배정도의 속도 차이가 발생한다.

3. 확률 변수의 확률 질량 함수

  • X는 0, 1, 2 중 하나의 값을 가질 수 있음
  • P(X=0) = 0.2 20%
  • P(X=1) = 0.5 50%
  • P(X=2) = 0.3 30%
x = np.array([0, 1, 2])
p_x = np.array([0.2, 0.5, 0.3])

3.1 확률 질량 함수 시각화

  • 확률 변수 X의 확률 질량 함수를 bar 그래프로 표현
x = np.array([0, 1, 2])
p_x = np.array([0.2, 0.5, 0.3])

plt.bar(x, p_x)
plt.xlabel('Random Variable X')
plt.ylabel('Probability')
plt.title('Probability of X')
plt.xticks(x)
plt.show()

x가 0일 확률은 0.2

x가 1일 확률은 0.5

x가 2일 확률은 0.3 임을 쉽게 확인할 수 있다.


3.2 확률 변수의 기대값

  • 확률 변수 X의 기대값(모평균) 계산
  • 표본 데이터를 생성하고, 표본 평균을 통해 모평균을 추정
x = np.array([0, 1, 2])
p_x = np.array([0.2, 0.5, 0.3])

# 모평균 E(X)
μ = np.sum(x * p_x) 

# 표본 데이터 생성
data = X(200)

# 표본평균
x̄ = data.mean()

 

모평균 계산하는 법

 

$ 0 \times 0.2 + 1 \times 0.5 + 2 \times 0.3 $

 

  • x 를 각각 대응되는 확률과 곱해준 뒤 모두 더해준다.
  • numpy 를 사용하면 간단하게 구할 수 있다.

 


3.3 확률 분포 시각화

  • 모평균: 빨간 점선 과 실제 표본 데이터 비교
  • 200개의 표본을 그래프화 한 뒤에 실제 모평균 값을 시각화

4. 평균이 같고 분산이 다른 확률 변수 비교

  • 확률 변수 X의 값: [0, 1, 2]
  • 확률 변수 Y의 값: [-1, 1, 3]
  • 확률 : [0.2, 0.6, 0.2]

  • 두 그래프는 평균이 같지만 각각 분산이 다른 것을 알 수 있다.
  • 평균은 데이터를 대표하는 대표값 중 하나이지만 분산에 따라 해석이 달라져야 함을 이해할 수 있다.

 

y = np.array([-1, 1, 3])
p_y = np.array([0.2, 0.6, 0.2])
e_Y = np.sum(y * p_y)
var_Y = np.sum(p_y * (y - e_Y) ** 2)  # 분산 계산
std_Y = np.sqrt(var_Y)  # 표준편차 계산

x = np.array([0, 1, 2])
p_x = np.array([0.2, 0.6, 0.2])
e_X = np.sum(x * p_x)
var_X = np.sum(p_x * (x - e_X) ** 2)  # 분산 계산
std_X = np.sqrt(var_X)  # 표준편차 계산
  • 각각의 확률변수 X와 Y의 평균, 분산, 표준편차를 계산하는 코드이다.

 


5. 확률 변수 X의 확률 분포 문제

  • 확률 변수 X가 가질 수 있는 값: [1, 2, 3, 4]
  • 각 값의 확률: [0.1, 0.3, 0.2, 0.4]

1. X의 평균 계산

e_x = np.sum(x * p_x)
  • x 를 각각 대응되는 확률과 곱해준 뒤 모두 더해준다.
  • numpy 를 사용하면 간단하게 구할 수 있다.

 


2. X의 분산 계산

var_x = np.sum(((x - e_x)**2) * p_x)
  • x 와 모평균의 차이를 구한 뒤 제곱해준다.
  • 위에서 구한 값에 확률을 곱해준다.
  • 위에서 구한 값을 모두 더해준다.

 


3. X에서 평균보다 큰 값이 나올 확률 계산

p_bigger = np.sum(p_x[x > e_x])
  • 평균보다 큰 값을 필터링한다.
  • 필터링 한 결과값으로 확률 array 에 똑같이 필터링 한다.
  • 필터링 해서 나온 값을 전부 더해준다.

 


4. 무작위로 5개의 표본을 추출하여 평균 계산

def X(size):
    rng = np.random.default_rng()
    u = rng.uniform(0, 1, size)
    condition = np.array([u <= 0.1, u <= 0.4, u <= 0.6, u < 1])
    return np.select(condition, x)
X(5).mean()
  • 랜덤으로 난수를 생성한다 (0~1)
  • 조건에 따라 필터링을 해준다.
    • 0.1 보다 작거나 같을 경우는 1 (0% ~ 10%)
    • 0.4 보다 작거나 같을 경우는 2 (10% ~ 40%)
    • 0.6 보다 작거나 같을 경우는 3 (40% ~ 60%)
    • 1보다 작을 경우는 4 (60% ~ 100%)
  • 필터링 한 결과값을 return 하고, 표본의 평균을 구해준다.

 


5. 확률 분포 그래프에 모평균: 빨간 선 과 표본 평균: 파란 선 추가

plt.bar(x, p_x)
plt.xlabel('Random Variable X')
plt.ylabel('Probability')
plt.xticks(x)
plt.title('Probability of X')
plt.axvline(e_x, label="μ", color="red")
plt.axvline(X(5).mean(), label="5 size mean", color="blue")
plt.axvline(X(20).mean(), label="20 size mean", color="green")
plt.legend()
plt.show()

 

  • 빨간선은 모평균 값이고,
  • 파란선은 표본의 개수가 5개일 때의 평균값이다.
  • 초록선은 표본의 개수가 20개일 때의 평균값이다.
  • 표본의 개수가 커질수록 모평균에 가까워진다.
  • 표본의 개수가 적을수록 변동폭이 크다는 사실을 확인할 수 있다.

 


확률 변수의 합과 확률 분포 구하기

1. 문제 소개

두 개의 동전을 던지는 실험을 진행하겠습니다.

각 동전은 앞면: 1 또는 뒷면: 0 이 나올 수 있으며, 앞면이 나올 확률은 30% 입니다.

 

이때, 두 개의 동전을 동시에 던졌을 때 앞면의 개수 Y 에 대한 확률을 계산해 보겠습니다.

즉, Y = 첫 번째 동전 결과 + 두 번째 동전 결과 입니다.

 


2. 확률 변수 X_1, X_2 정의

각 동전의 결과를 확률 변수 X_1 과 X_2 로 정의합니다.

동전 결과 확률
뒷면: 0 0 0.7 70%
앞면: 1 1 0.3 30%

이제 두 개의 동전을 동시에 던졌을 때, $ Y = X_1 + X_2 $ 가 될 확률을 계산해 보겠습니다.


3. Y 의 가능한 값과 확률 계산

우리는 두 개의 동전을 던지므로 Y 의 값은 0, 1, 2 중 하나입니다.

가능한 경우를 모두 살펴보겠습니다.

첫 번째 동전 X_1 두 번째 동전 X_2 ( Y = X_1 + X_2 ) 확률 계산
0 0 0 ( 0.7 \times 0.7 = 0.49 )
0 1 1 ( 0.7 \times 0.3 = 0.21 )
1 0 1 ( 0.3 \times 0.7 = 0.21 )
1 1 2 ( 0.3 \times 0.3 = 0.09 )

결과를 정리하면:

Y 값 확률 P(Y)
0 0.49
1 0.21 + 0.21 = 0.42
2 0.09

 

 

해석:

  • 동전 두 개를 던졌을 때, 두 개 모두 뒷면이 나올 확률은 49%
  • 하나만 앞면이 나올 확률은 42%
  • 두 개 모두 앞면이 나올 확률은 9%

 


4. 평균기대값과 분산 계산

확률 변수의 기대값/평균 은 다음과 같이 계산합니다.

 

$$
E(Y) = E(X_1) + E(X_2)
$$

 

e_x = 0 * 0.7 + 1 * 0.3  # X의 평균
e_y = e_x + e_x  # Y의 평균
print(f"E(Y) = {e_y}")  # 0.6

 

5. 확률 변수의 합 확장하기

만약 7개의 동전을 동시에 던진다면 어떻게 될까요?

 

$ Y = X_1 + X_2 + X_3 + X_4 + X_5 + X_6 + X_7 $ 일때, 각 YI값의 확률을 구해보겠습니다.

 


import numpy as np
from itertools import product

# X1 ~ X7의 가능한 값 (0 또는 1)
x_values = [0, 1]
p_x = [0.7, 0.3]  # 확률: 0이 나올 확률 0.7, 1이 나올 확률 0.3

# 모든 가능한 조합 생성
combinations = list(product(x_values, repeat=7))

# Y 값과 그에 해당하는 확률 계산
y_probabilities = np.zeros(8)  # Y는 0부터 7까지의 값을 가질 수 있음
for combination in combinations:
    y_value = sum(combination)
    prob = np.prod([p_x[val] for val in combination])
    y_probabilities[y_value] += prob

# 결과 출력
for y_value, prob in enumerate(y_probabilities):
    print(f"P(Y={y_value}) = {prob:.4f}")



출력 예시

 

P(Y=0) = 0.0478
P(Y=1) = 0.1722
P(Y=2) = 0.3177
P(Y=3) = 0.3025
P(Y=4) = 0.1361
P(Y=5) = 0.0224
P(Y=6) = 0.0016
P(Y=7) = 0.0001

 

 

2025.03.25 - [Data] - LS 빅데이터 스쿨 / 이항 분포 / python

 

LS 빅데이터 스쿨 / 이항 분포 / python

오늘은 문제 풀이를 통해 이항 분포에 대해 접했습니다.처음 접한 개념이라 생소했지만, 실제 문제를 통해 이해하니 보다 쉽게 이해할 수 있었습니다.이항분포에 대해 알아보고 이를 파이썬 코

kiminchae.tistory.com