베이즈 (Bayes) 정리를 가장 쉽게 설명해 보자

베이즈 (Bayes) 정리를 가장 쉽게 설명해 보자





Bayes’ theorem

최근에는 베이지안 통계에 집중하고 있습니다. 그래서 개념 정리도 할 겸 베이즈 정리 (Bayes’ theorem)에 대해 최대한 쉽게 한번 설명해 보겠습니다.

Kaggle 에서 데이터를 하나 가져오겠습니다.

https://www.kaggle.com/datasets/cameronseamons/electronic-sales-sep2023-sep2024

이 데이터는 전자 마트에서 고객의 소비 성향을 분석한 데이터 입니다. Kaggle 에서 회원가입 후 데이터를 다운로드 받을 수 있습니다.

저는 파이썬 코드로 바로 데이터를 가져오겠습니다. 참고로 저는 구글 코랩 (Google Colab) 을 사용합니다.

<파이썬 코드 정리>

1) Google Colab에 Google Drive를 연결합니다. 

#to mount Google Drive on Google Colab
from google.colab import drive
drive.mount('/content/drive')

2. 파이썬에서 Kaggle 데이터를 바로 가져오기 위해서 아래와 같이 코드를 입력합니다.

# JSON file download
! mkdir -p ~/.kaggle
! cp /content/drive/MyDrive/Colab/0_archive/kaggle.json ~/.kaggle
! chmod 600 ~/.kaggle/kaggle.json
# 본인 구글 드라이브의 파일 경로 확인

3. Kaggle 에 있는 해당 데이터의 API 와 그 파일이 저장될 경로를 지정합니다.

# to download dataset from Kaggle
!kaggle datasets download -d cameronseamons/electronic-sales-sep2023-sep2024 -p "/content/drive/MyDrive/Colab/1_data_download"
# API
# 본인 구글 드라이브의 파일 경로 확인

이렇게 코드를 실행하면 electronic-sales-sep2023-sep2024.zip 파일이 지정한 구글 드라이브 경로에 저장이 됩니다.

4. 저장된 zip 파일을 sales 라는 변수 이름으로 저장하겠습니다.

# path to the directory containing the zip file
import zipfile
import os
sales= "/content/drive/MyDrive/Colab/1_data_download/electronic-sales-sep2023-sep2024.zip"
# 본인 구글 드라이브의 파일 경로 확인

5. 그리고 그 파일이 저장될 경로를 지정하겠습니다. 

# Path to the directory where you want to extract the contents
sales_path= "/content/drive/MyDrive/Colab/Python_code/Bayes"
# 본인 구글 드라이브의 파일 경로 확인

6. 이제 zip 파일에서 파일을 위에 지정된 파일 경로로 추출하겠습니다.

# Unzip the file
with zipfile.ZipFile(sales, 'r') as zip_ref:
     zip_ref.extractall(sales_path)

7. 어떤 파일이 저장되었는지 확인해 보겠습니다. 

# List the contents of the extracted directory
extracted_sales = os.listdir(sales_path)
print("Extracted files:", extracted_sales)

Extracted files: ['Electronic_sales_Sep2023-Sep2024.csv']

Electronic_sales_Sep2023-Sep2024.csv 이라는 파일이 지정된 경로에 저장이 되었습니다.

8. 이제 이 파일을 구글 코랩 에서 작업을 위해 불러 오겠습니다.

# Set up the path that contains the dataset
%cd /content/drive/MyDrive/Colab/Python_code/Bayes
# 본인 구글 드라이브의 파일 경로 확인

import pandas as pd
sales= pd.read_csv("Electronic_sales_Sep2023-Sep2024.csv", index_col=0)
sales.head()

복잡해 보이지만 어려울게 하나도 없습니다. 아래 코드를 본인의 구글 코랩에 복사/붙여넣기 하고 본인 구글 코랩의 파일 경로만 수정하면 됩니다.

from google.colab import drive
import pandas as pd
import zipfile
import os

drive.mount('/content/drive')

! mkdir -p ~/.kaggle
! cp /content/drive/MyDrive/Colab/0_archive/kaggle.json ~/.kaggle
! chmod 600 ~/.kaggle/kaggle.json

!kaggle datasets download -d cameronseamons/electronic-sales-sep2023-sep2024 -p "/content/drive/MyDrive/Colab/1_data_download"

sales= "/content/drive/MyDrive/Colab/1_data_download/electronic-sales-sep2023-sep2024.zip"

sales_path= "/content/drive/MyDrive/Colab/Python_code/Bayes"

with zipfile.ZipFile(sales, 'r') as zip_ref:
     zip_ref.extractall(sales_path)

%cd /content/drive/MyDrive/Colab/Python_code/Bayes

sales= pd.read_csv("Electronic_sales_Sep2023-Sep2024.csv", index_col=0)
sales.head()

자 이렇게 저는 Kaggle 에서 데이터를 바로 가져 왔습니다.

이 과정이 복잡하다 생각되시면 그냥 Kaggle 에서 데이터 다운로드 받으셔서 본인 구글 드라이브에 바로 업로드 해도 됩니다. 참고로 파이썬 사용시 쥬피터 노트북을 사용하시는 분은 그에 맞게 데이터를 로컬 폴더에 넣고 업로드 하면 됩니다.

위 데이터를 보면 성별 (Gender), 멤버십 (Loyalty Member), 상품 구매 타입 (Product type), 상품 구매 방법 (Payment Method) 등의 정보들이 있습니다. 이 데이터를 가지고 베이즈 정리를 차근 차근 이해해 봅시다.






1. 확률 (Probability)

확률은 “모든 일어날 수 있는 경우의 수 가운데 어떤 일이 일어날 가능성” 을 나타냅니다. 위 데이터에서 우리가 임의로 데이터를 선택했을 때 그 사람이 남자일 확률은 어떻게 될까요? 파이썬 코드로 바로 알아 봅시다.

male= (sales['Gender']=="Male")

def prob(A):
  return A.mean()

prob(male)
0.5082

우리가 위 데이터에서 한 사람을 선택 했을 때 그 사람이 남자일 확률은 50.82% 입니다. 그냥 쉽게 엑셀 파일에서 전체 데이터 열이 20,000 행인데 남자가 10,164 행을 차지하고 있으니 10164/20000 = 0.5082 입니다.

male.sum() / len(sales)
0.5082





2. 논리곱 (Logical conjunction)

두번째로는 논리곱에 대해 알아 보겠습니다. 논리곱은 AND 논리 연산자의 다른 이름 입니다. 두개의 명제 A 와 B 가 있을 때 A 와 B 모두 참이면 A 와 B 의 논리곱은 참이며, 아닌 경우는 거짓이 됩니다.

쉽게 이야기 하자면 위 데이터에서 임의로 데이터를 선택 했을 때 남자이면서 Tablet 을 구매한 사람의 확률을 논리곱으로 구할 수 있습니다.

# 남자일 확률
male= (sales['Gender']=="Male")

def prob(A):
  return A.mean()

prob(male)
0.5082

# Tablet 을 구매할 확률
tablet= (sales['Product Type']=="Tablet")

def prob(A):
  return A.mean()

prob(tablet)
0.2052

즉, 남자이면서 Tablet 을 구매할 확률은 0.5082 * 0.2052 = 0.104 입니다. 아래와 같은 코드로 계산할 수도 있습니다.

male= (sales['Gender']=="Male")
tablet= (sales['Product Type']=="Tablet")

def prob(A):
  return A.mean()

prob (male & tablet)
0.104

위 계산을 통해 우리는 논리곱은 교환 가능하다는 것을 예상할 수 있습니다. 즉, A and B 와 B and A 는 같습니다.

즉, 임의로 데이터를 선택 했을 때 “남자이면서 Tablet 을 구매한 사람의 확률” 은 “Tablet 을 구매한 사람이면서 남자일 확률” 은 같다는 말 입니다.

def prob(A):
  return A.mean()

prob (tablet & male)
0.104

저는 여기서 이면서 라는 단어를 사용했습니다. 사실 단어 하나 차이로 확률 계산은 완전히 달라집니다.






3. 조건부 확률 (Conditional probability)

이제 조건부 확률을 알아 보겠습니다. 이제 제가 궁금한 것은,

남자 Tablet 을 구매한 사람의 확률 입니다. 아래와 같이 파이썬으로 계산해 보겠습니다.

tablet[male].sum() / male.sum() or
prob (tablet & male) / prob (male)
0.205

그 확률 값은 20.5% 입니다. 이 차이를 이해 하셨나요?

남자이면서 Tablet 을 구매한 사람의 확률 값은 10.4% 였습니다. 하지만 남자 Tablet 을 구매한 사람의 확률 값은 20.5% 가 됩니다. 단어 하나 차이에 이렇게 확률 값에 차이가 나게 됩니다.

위 데이터에서 남자는 총 male.sum() = 10,164 였습니다. 그리고 남자 중 tablet 을 구매한 사람은 tablet[male].sum() = 2,088 이었습니다. 즉, 2,088 / 10,164 = 0.205 입니다. 이 계산식은 아래와 같은 코드로 나타낼 수 있습니다.

def prob(A):
  return A.mean()

prob(tablet[male])
0.205

conditional 이라는 함수를 사용해서 좀 더 쉽게 코드를 만들어 보겠습니다.

def conditional (proposition, given):
  return prob(proposition[given])

conditional (tablet, male)
0.205

###

여기서 중요한 개념이 나옵니다. 조건부 확률은 교환 가능하지 않다는 것 입니다. 즉, “Tablet 을 구매한 사람 중 남자일 확률”과 “남자 중 Tablet 을 구매한 사람의 확률” 은 다를 것입니다.

위 데이터에서 tablet 구매자는 tablet.sum() = 4,104 였습니다. 그리고 tablet 구매자 중 남자는 male[tablet].sum() = 2,088 였습니다. 즉, 2,088 / 4,104 = 0.509 입니다.

male[tablet].sum() / tablet.sum()
0.509

def conditional (proposition, given):
  return prob(proposition[given])

conditional (male, tablet)
0.509

남자 중 Tablet 을 구매한 사람의 확률은 10.4% 이지만, Tablet 을 구매한 사람 중 남자일 확률은 50.9% 입니다. 즉, 조건부 확률은 교환 가능하지 않습니다.






확률 법칙

앞에서 확률, 논리곱 그리고 조건부 확률에 대해 설명을 했습니다. 이 3 가지 관계를 서로 도출해 보겠습니다.

[1] 확률
P(A): A 에 대한 확률

[2] 논리곱
P(A and B): A 와 B의 논리곱의 확률. A 와 B 모두 참일 확률

[3] 조건부 확률
P(A|B): B가 주어졌을 때 A 가 참일 확률

앞에서 남자 중 Tablet 을 구매한 사람의 확률은 0.205 라고 했습니다.

# P(A|B)
def conditional (proposition, given):
  return prob(proposition[given])

conditional (tablet, male)
0.205

그리고 이 확률은 아래처럼 계산 된다고 했습니다.

# P(A and B) / P(B)
prob (tablet & male) / prob (male)
0.205

그러면 우리는 아래와 같은 계산식을 도출할 수 있습니다.

이 계산식은 아래와 같이 정리 됩니다.

그러면 아래와 같은 계산식도 가능할 것입니다.

논리곱은 교환 가능하다고 했습니다; P(A and B) = P(B and A). 그러면 아래와 같은 계산식이 성립 됩니다.

위에 식은 아래와 같이 정리 될 수 있습니다.

그리고 이 마지막 계산식을 베이즈 정리라고 부릅니다.

B 의 조건에서 A 의 확률A 의 확률 x A 의 조건에서의 B 의 확률 을 B 의 확률로 나눈 값과 동일합니다.






베이즈 정리






Comments are closed.