실습_3. 확률

Updated:

팩토리얼

얼마 전 인터넷 상에서 화제가 되었던, 초등학생 수학 문제로 보는 “문과-이과 구분법” 을 아시나요?

40-32/2 = ?
의 정답은 무엇일까요?

초등학생은 이에 4!라고 대답했습니다. 이 초등학생의 답을 보고

이과생은 “잘 알고 있네.” 라고 했고,

문과생은 “역시 잘 모르는구나.” 라고 대답하고 있습니다.

혹시 여러분은 왜 이런지 아시겠나요? 이 유머는 문,이과 상관없이 팩토리얼(!) 에 대해서만 알면 되는데요. 한 번 4! 을 계산해보겠습니다.

그럼 이제 4명의 학생을 뽑는 경우의 수를 계산해보겠습니다. 첫 번째로는 4명을 모두 뽑을 수 있고, 두 번째에서는 첫 번째에서 뽑힌 학생을 제외한 3명, 세 번째에서는 첫,두 번째에서 뽑힌 학생을 제외한 2명, 마지막에서는 앞에서 뽑힌 3명을 제외한 1명이 남으므로 4!과 같습니다.

이렇게 n개의 요소들을 순서대로 배치하는 경우의 수를 팩토리얼로 구할 수 있습니다.

  • 문제

fac 함수가 문제에서 의도한 값을 반환하도록 올바르게 구현해보세요.

fac 함수는 정수 하나를 받아, 그 정수의 팩토리얼을 계산한 값을 반환해줍니다.

팩토리얼의 정의는 다음과 같습니다.

0! = 1
n! = n * (n-1)!
  • 출력 예시
print(fac(4))
>>>24
# ! 함수 정의 
def fac(n):
    facto = 1
    for i in range(1,n+1):
        facto*=i
    
    return facto 
    
# 4! 계산
print(fac(4))

순열

파이썬의 itertools 모듈에 있는 permutations함수를 이용해 순열을 계산해보도록 하겠습니다.

  • 문제

순열
permutations 을 사용하여 nPr을 계산하겠습니다.

수강생분들을 뽑아 경품 추첨을 하게 되었습니다! 참가한 학생은 6명인데, 이 중 2명에게 상품을 주려 합니다. 하지만, 등수마다 경품이 다릅니다.

6명의 학생 중 순서를 고려하여 2명을 뽑는 경우의 수는 rank_per 에, 몇 가지 인지 계산한 것은 rank_per_num 에 저장해보겠습니다.

rank_per = list(permutations(["가","나","다","라","마","바"],2))
rank_per_num = len(rank_per)

학생들의 이름은 자유롭게 설정하여도 상관 없습니다.

print(fac(5))
>>>120
from itertools import permutations 
from itertools import combinations

# 순열 : 6명 수강생 중 2명에게 순위별 상품을 주는 경우의 수 
rank_per = list(permutations(["가","나","다","라","마","바"],2))
rank_per_num = len(rank_per)

print(rank_per)
print(rank_per_num)

조합

파이썬의 itertools 모듈에 있는 combinations 함수를 이용해 조합을 계산해보도록 하겠습니다.

  • 문제

조합
combinations 라는 함수를 사용하여 nCr을 계산해보겠습니다.

수강생분들을 뽑아 경품 추첨을 하게 되었습니다! 참가한 학생은 6명인데, 이 중 2명에게 상품을 주려 합니다.

그럼 순서를 고려하지 않고 6명 중 2명을 뽑는 경우의 수는 rank_com 에, 이 경우의 수가 몇 가지인지 계산해 rank_com_num 에 저장해보겠습니다.

rank_com = list(combinations(["가","나","다","라","마","바"],2))
rank_com_num = len(rank_com)

학생들의 이름은 자유롭게 설정하여도 상관 없습니다.

from itertools import permutations 
from itertools import combinations

# 조합 : 6명 수강생 중 2명에게 순위 상관없이 상품을 주는 경우의 수 
rank_com = list(combinations(["가","나","다","라","마","바"],2))
rank_com_num = len(rank_com)

print(rank_com)
print(rank_com_num)

중복순열

n개 중 r개를 중복을 허용하여 순서대로 나열하는 경우의 수를 출력해보도록 하겠습니다.

  • 문제

중복순열
지난 실습에서 순열을 계산하는 방법 permutations 을 사용하여 nPr을 계산해보았습니다.

이번에는 product 를 활용하여 중복순열 n∏r을 계산해보겠습니다.

자전거 비밀번호를 바꾸려고 합니다. A부터 E까지의 알파벳 5개 중 하나씩을 뽑아 3자리의 비밀번호를 만든다고 하면, 이에 대한 경우의 수는 몇 가지 일까요? 3자리 수는 1번째 자리 수에 온 알파벳이 두 번째, 세 번째 자리에 와도 됩니다.

3자리의 비밀번호중 A~E를 뽑은 것은 re_per 에, 몇 가지 인지 계산한 것은 re_per_num 에 저장해보겠습니다.

re_per = list(product([‘A’, ‘B’,’C’,’D’,’E’], repeat = 3)) re_per_num = len(re_per)

from itertools import product
from itertools import combinations_with_replacement

# 중복순열

re_per = list(product(['A', 'B','C','D','E'], repeat = 3))
re_per_num = len(re_per)

print(re_per)
print(re_per_num)

중복조합

n개 중 r개를 중복을 허용하여 순서와 상관 없이 나열하는 경우의 수를 출력해보도록 하겠습니다.

  • 문제

중복조합
지난 실습에서 조합을 계산하는 방법을 사용하여 n개 중 r개를 뽑을 수 있는 combinations 라는 함수를 사용해봤습니다. 이번에는 중복을 허용하여 뽑는 중복조합 combinations_with_replacement 를 활용하여 nHr을 계산해봅시다.

자전거 비밀번호를 바꾸려고 합니다. A부터 E까지의 알파벳 5개 중 3개를 뽑아 비밀번호를 만든다고 합니다. 근데 순서는 보고 나중에 정하려고 합니다. 이에 대한 경우의 수는 몇 가지 일까요?

그럼 순서를 고려하지 않고 5가지 중 3개를 중복 가능하여 뽑는 경우의 수는 re_com 에, 이 경우의 수가 몇 가지인지 계산해 re_com_num 에 저장해보겠습니다.

re_com = list(combinations_with_replacement(['A','B','C','D','E'], 3))
re_com_num = len(re_com)
from itertools import product
from itertools import combinations_with_replacement

# 중복조합

re_com = list(combinations_with_replacement(['A','B','C','D','E'], 3))
re_com_num = len(re_com)

print(re_com)
print(re_com_num)

조건부 확률과 독립

어떤 조건을 주고 이에 대한 확률 값을 계산하여 조건에 따른 확률 값을 확인해보겠습니다. 그리고 독립인지도 확인해보겠습니다.

실제 데이터들은 어떤 조건이 만족하면 이런 결과가 나오는 경우가 많기 때문에 조건부 확률을 잘 계산해야 합니다.

  • 문제

엘리스에서 수강생 여러분들 중 30명을 선택하여 임의로 설문조사를 했습니다.

Q1. 엘리스 토끼가 체셔보다 더 귀여운가요? 라는 질문에

A : 아니요. 체셔가 더 귀여워요

B : 네. 토끼가 더 귀여워요

Q2. 엘리스 토끼가 체셔보다 더 예쁜가요? 라는 질문에

A : 아니요. 체셔가 더 예뻐요

B : 네. 토끼가 더 예뻐요

응답지 두 개를 주었습니다. 두 가지 질문의 A,B 응답 확률은 0.5 라고 가정합니다.

모두 A 응답 하나는 A, 하나는 B응답 모두 B응답 1/4 1/2 1/4

모두 A 응답 하나는 A 하나는 B응답 모두 B응답
1/4 1/2 1/4

조건부 확률을 사용하여 1번 문항에 A를 응답한 경우(사건A)에서 두 문항 모두에 A를 응답한 경우(사건B)의 확률을 구해보면 P(B|A) = P(B∩A)/P(A) = P(B)/P(A) = 1/2 이므로 직관적으로 납득할 수 있는 값입니다.

그렇다면 이와는 반대로, 최소 한 문항에 A를 응답한 경우(사건O) 일 때, 두 문항 모두에 A를 응답한 경우(사건B) 의 확률을 계산해보면 다른 결과가 나옵니다. P(B|O) = P(B, O)/P(O) = P(B)/P(O) = 1/3

이러한 내용을 random 을 사용해서 각각의 질문에 임의로 학생들이 할 대답을 뽑는 함수random_answer을 만들어보겠습니다.

def random_answer():
    return random.choice(["A", "B"])

이를 for 문과 if문을 활용하여 30명의 응답을 알아보고, 2번째 질문에 A라 응답한 학생수를answer_Q2,

두 질문 모두에 A라 응답한 학생수를 answer_Q1andQ2,

둘 중 하나의 질문에 A라 응답한 학생수를 answer_Q1orQ2 에 카운트해 저장해보겠습니다.

for i in range(30):
    Q1 = random_answer()
    Q2 = random_answer()
    if Q2 == "A":
        answer_Q2 += 1
    if Q2 == "A" and Q1 == "A":
        answer_Q1andQ2 += 1
    if Q2 == "A" or Q1 == "A":
        answer_Q1orQ2 += 1
저장한 값을 바탕으로 P(B A), P(B O) 를 계산해 print 해보겠습니다.
print( "P(Q1 and Q2 | Q2 ):", answer_Q1andQ2/answer_Q2)
print( "P(Q1 and Q2 | Q1 or Q2 ):", answer_Q1andQ2/answer_Q1orQ2)

두 물음에 대한 대답은 독립일까요? 아닐까요?

import random
answer_Q1andQ2 = 0
answer_Q2 = 0
answer_Q1orQ2 = 0
random.seed(4)

# 함수 정의 
def random_answer():
    return random.choice(["A", "B"])

# 30명의 응답 결과
for i in range(30):
    Q1 = random_answer()
    Q2 = random_answer()
    if Q2 == "A":
        answer_Q2 += 1
    if Q2 == "A" and Q1 == "A":
        answer_Q1andQ2 += 1
    if Q2 == "A" or Q1 == "A":
        answer_Q1orQ2 += 1

# 조건부 확률과 독립
print( "P(Q1 and Q2 | Q2 ):", answer_Q1andQ2/answer_Q2)
print( "P(Q1 and Q2 | Q1 or Q2 ):", answer_Q1andQ2/answer_Q1orQ2)

확률변수

무작위 랜덤 확률변수를 만들어보겠습니다. 확률분포는 4주차에서 구체적으로 다루게 되므로 이번 주차에서는 확률변수에 대한 실습으로 마무리하겠습니다!

파이썬에는 공정한 주사위의 면을 만드는 듯한 함수인 Die 함수가 있습니다. 이를 활용해서 유한한 확률변수를 만들어보겠습니다.

  • 문제
  1. Die 함수를 사용해 6개의 면이 있는 공정한 주사위의 확률변수를 만들어보고 분포도 확인해보겠습니다.
Die6 = Die('Die6', 6)
Die6_dict = density(Die6).dict
  1. given 으로 조건을 주어 다시 확률변수를 만들어보겠습니다. 3 초과의 면만 나오는 주사위를 만드는 조건을 condi 에 저장해보고 분포를 condi_dict 에서 확인해보겠습니다.
condi = given(Die6, Die6 > 3)
condi_dict = density(condi).dict
from sympy.stats import given, density, Die

## Q1. 6개의 면이 있는 주사위 생성
Die6 = Die('Die6', 6)
Die6_dict = density(Die6).dict
print(Die6)
print(Die6_dict)


## Q2. 3 초과의 면만 나오는 조건을 가진 주사위 생성
condi = given(Die6, Die6 > 3)
condi_dict = density(condi).dict
print(condi)
print(condi_dict)

Leave a comment