어제와 이어서 하겠습니다.
로지스틱 회귀의 수식은
이렇게 되어 있으며, 저 z는 기본적인 회귀 모델의 수식의 값을 가지고 있습니다. 그렇기에 z의 값이 커지면 커질수록 전체의 값은 0에 더 가까워지며, 0에 가까워질수록 전체 값은 1에 가까워 집니다.
그러면 이제 강의에서 나온 코드를 가져오겠습니다.
import numpy as np
import pandas as pd
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
# 데이터 로드
data = load_breast_cancer()
X = data.data
y = data.target
# 데이터 분할
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 데이터 스케일링
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)
자, 이 코드는 전.처.리만 하는 코드입니다. 끝이 아니라는 말이죠. 왜냐? 로지스트 회귀로 표현하기 위해서는 LogisticRegression()하는 모델을 써야합니다. 하지만 여기서는 StandardScaler()라고 하는 모델이 쓰였는데요, 이 둘의 차이점을 알려드리겠습니다.
StandardScaler() -> 데이터의 스케일을 조정 하는 것입니다. 즉, 데이터간의 공백이 너무 크면 이것을 알맞게 조정해주는 하나의 전처리 과정이라고 생각하시면 편합니다. 이는 주로 선형 모델(로지스틱 회귀 포함)에서 중요한데, 특정 특성이 다른 특성보다 모델에 더 큰 영향을 미치지 않도록 하기 때문입니다
LogisticRegression() -> 분류 모델을 생성하고 학습 하는 것입니다. 입력 데이터를 바탕으로 최적의 결정 경계를 찾고, 각 클래스에 대한 확률을 계산합니다. 예측 결과는 0 또는 1의 클래스로 나타납니다.
StandardScaler()는 데이터의 특성값들을 평균이 0이고 표준편차가 1이 되도록 스케일링합니다. 왜냐하면 서로 간의 공백이 너무나 클 경우, 모델이 어떤 특성에 더 큰 가중치를 두게 될 수 있습니다. 게다가
LogisticRegression()은 predict(), 혹은 predict_proba()를 써서 확률을 구합니다
여기서
predict() -> 확률값을 바탕으로, 예를 들어 0.5를 기준으로 0 또는 1을 예측하는 역할을 합니다.
(즉 0 혹은 1을 반환)
predict_proba() -> 시그모이드 함수를 통해 확률을 계산하여 각 클래스(예: 0 또는 1)에 속할 확률을 반환합니다.
(즉, 확률 그대로 반환)
즉,
LogisticRegression() 클래스가 로지스틱 회귀의 수식 및 알고리즘을 적용하도록 모델을 설정하고, predict_proba()와 predict()가 실제로 수식을 사용해 결과를 예측하는 방식이므로 이 두개가 세트라고 생각하시면 편합니다.
어 그런데, 저 fit은 학습을 시킬 때 쓰는거 아닌가?
맞습니다, 하지만 그 전에 fit_transform에 대해 설명드리겠습니다.
말 그대로 fit()은 모델이나 변환기를 훈련 데이터에 적합(fit)시키는 과정입니다.
예를 들어, StandardScaler의 경우 fit() 메서드는 훈련 데이터의 평균과 표준편차를 계산합니다. 이 정보를 바탕으로 이후에 데이터를 스케일링할 때 사용할 수 있도록 준비합니다. 즉, 학습의 개념도 있지만, 받은 모델의 정보를 바탕으로 알맞게 변환시켜준다 라는 뜻도 있습니다.
그리고
transform()은 fit()에서 계산한 파라미터(예: 평균, 표준편차)를 사용하여 실제 데이터를 변환(transform)합니다. transform()은 스케일링의 개념에 더 중점을 두고 있습니다. 예를 들어, StandardScaler에서, transform()을 호출하면 각 특성값에서 평균을 빼고 표준편차로 나누어 주는 방식으로 데이터를 스케일링합니다.
잠깐 여기서 스케일링이란? (위에서 말했지만....한번 더) -> 데이터의 특성값들을 특정 범위로 조정하는 과정을 말합니다. 주로 평균이 0이고 표준편차가 1이 되도록 변환하여, 서로 다른 특성값들이 비슷한 스케일을 갖게 만드는 것입니다.
즉, fit을 통해 모델의 데이터를 학습하고, 바로 이어서 tranform()을 통해 스케일링을 한다는 말입니다.
이쯤되면 뭐가 회귀 모델이고, 뭐가 전처리용인지 헷갈리는 수가 있습니다.
그래서 제가 찾아본 결과, 작지만 구별하기 편하게 가져와봤습니다.
1. 전처리(Preprocessing)
전처리는 데이터의 품질을 높이고 모델이 더 잘 학습할 수 있도록 준비하는 과정이며, 이 과정에서 전처리에 사용되는 주요 기법들은 다음과 같습니다:
스케일링(Scaling): StandardScaler, MinMaxScaler, RobustScaler 등.
목적: 서로 다른 범위의 특성값들을 같은 스케일로 조정.
인코딩(Encoding): OneHotEncoder, LabelEncoder 등.
목적: 범주형 변수를 숫자형으로 변환.
결측치 처리: SimpleImputer 등.
목적: 결측값을 평균, 중앙값, 최빈값 등으로 대체.
특성 선택/제거: SelectKBest, VarianceThreshold 등.
목적: 모델에 가장 도움이 되는 특성을 선택하거나 불필요한 특성을 제거.
2. 학습(Learning)
학습 단계에서는 데이터를 바탕으로 모델이 예측할 수 있도록 만드는 과정이며, 주로 사용되는 기법들은 다음과 같습니다:
회귀(Regression): LinearRegression, Ridge, Lasso 등.
목적: 연속적인 값을 예측.
분류(Classification): LogisticRegression, RandomForestClassifier, SVC 등.
목적: 특정 클래스에 속하는지 여부를 예측.
군집화(Clustering): KMeans, DBSCAN 등.
목적: 데이터의 그룹을 찾아내는 것.
문제는 용도를 제일 먼저 이해하는 것! 각 라이브러리나 모듈의 문서에서 어떤 목적을 가지고 있는지 확인합니다.
아 참고로 transform()은 각 모델마다 다른 의미를 가지고 있습니다.
1. StandardScaler
transform(): 평균과 표준편차를 사용하여 데이터를 정규화합니다. (스케일링)
2. OneHotEncoder
transform(): 범주형 변수를 원-핫 인코딩 형식으로 변환합니다. (각 카테고리를 이진 변수로 변환)
3. MinMaxScaler
transform(): 데이터를 지정된 범위(예: 0과 1)로 변환합니다. (다른 스케일링 기법)
4. PolynomialFeatures
transform(): 입력 특성을 다항식 특성으로 변환합니다. (특성 확장)
아 말하는 걸 깜빡했는데 강의에서 비용 함수, 즉 로그 손실 함수라고 나왔는데, 수식이 어려우니, 간단하게 말해서
loss = log_loss(y_test, y_pred_proba) 이렇게 쓰시면 됩니다. log_loss() -> 이러면 안에 있는 수식이 자동으로 계산해 줍니다.
그런데 여기서 궁금증이 생길 수 있습니다. 왜
X_train에는 .fit_transform이, X_test에는 .transform이 쓰이고, y에는 스케일링이 되지 않을까요?
X_train과 X_test에 대한 스케일링
X_train에서 fit_transform 사용 이유: 훈련 데이터(X_train)는 모델이 학습하는 데이터입니다. 이 데이터에서 특징의 분포를 이해해야 하며, 이 분포를 바탕으로 스케일링을 적용해야 합니다. 즉, 계산된 값으로 학습을 해야하기 때문에 fit이 붙습니다.
계산: fit_transform을 사용하면 훈련 데이터의 평균과 표준편차를 계산하고, 이를 기반으로 스케일링을 진행합니다. 즉, 각 특징이 평균 0, 표준편차 1이 되도록 조정됩니다.
X_test에서 transform 사용 이유 : 테스트 데이터(X_test)는 모델의 성능을 평가하기 위한 데이터입니다. 이 데이터는 모델의 학습에 사용되지 않아야 하며, 훈련 데이터에서 얻은 정보로만 스케일링해야 합니다. 그렇기 때문에 fit은 쓰이지 않습니다.
기준 유지: transform 메서드는 훈련 데이터에서 계산된 평균과 표준편차를 사용하여 테스트 데이터를 스케일링합니다. 이렇게 함으로써, 테스트 데이터가 훈련 데이터와 같은 기준으로 변환됩니다.
Y에 대한 스케일링이 필요 없는 이유
y는 클래스 레이블!
y는 각 샘플의 클래스 레이블(타겟)을 나타냅니다. 예를 들어, 유방암 데이터셋에서는 0(양성) 또는 1(악성)으로 표현됩니다. 이는 범주형 데이터입니다. 그렇기에 스케일링은 일반적으로 연속형 데이터에 적용되어, 데이터의 범위를 통일하는 작업입니다. 클래스 레이블은 이미 특정한 값으로 구분되기 때문에 스케일링할 필요가 없습니다.
목표:
머신러닝 모델은 입력 데이터(X)를 바탕으로 해당하는 클래스 레이블(y)을 예측하는 것을 목표로 합니다. 따라서 y는 모델의 출력이며, 이 출력값은 스케일링의 대상이 아닙니다.
따라서,
y: 이미 0과 1로 구분된 클래스 레이블이기 때문에 스케일링할 필요가 없습니다. 이 값들은 모델이 예측해야 할 정답이므로, 그대로 사용됩니다.
X_train: 모델이 학습할 데이터로, 평균과 표준편차를 계산하여 스케일링해야 합니다. 따라서 fit_transform을 사용하여 이 데이터에 대한 통계 정보를 학습하고 이를 기반으로 스케일링합니다.
X_test: 모델의 성능을 평가하기 위한 데이터로, 이미 학습된 모델의 통계(훈련 데이터에서 계산된 평균과 표준편차)를 기반으로 스케일링해야 합니다. 그래서 transform만 사용하여 스케일링합니다. 이때 fit은 사용하지 않아서 모델이 이 데이터를 학습하지 않도록 합니다.
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix
# 모델 생성 및 학습
model = LogisticRegression()
model.fit(X_train, y_train)
# 예측
y_pred = model.predict(X_test)
# 평가
print(f"Accuracy: {accuracy_score(y_test, y_pred)}")
print(f"Classification Report:\n{classification_report(y_test, y_pred)}")
print(f"Confusion Matrix:\n{confusion_matrix(y_test, y_pred)}")
이제 여기서 LogisticRegression()을 통해 로지스틱 회귀의 개념을 학습(fit)시킵니다. 그리고 predict을 통해 예측을 합니다.
그런데
accuracy_score
classification_report
confusion_matrix
이 3가지에 대해 빠르게 설명드리겠습니다.
accuracy_score -> 모델의 정확도를 측정하는 지표로, 올바르게 분류된 샘플의 비율을 나타냅니다. 정확도는 직관적으로 모델이 얼마나 잘 작동하는지를 보여주지만, 클래스 불균형이 심한 경우에는 부정확할 수 있습니다.
classification_report -> 분류 모델의 성능을 요약한 보고서로, 여러 가지 중요한 지표를 제공하며, 그 지표로는,
정밀도(Precision): 올바르게 예측한 긍정 샘플 수를 전체 긍정 예측 수로 나눈 비율입니다.
재현율(Recall): 올바르게 예측한 긍정 샘플 수를 실제 긍정 샘플 수로 나눈 비율입니다.
F1 점수: 정밀도와 재현율의 조화 평균으로, 두 지표의 균형을 제공합니다.
confusion_matrix -> 모델의 예측 결과와 실제 결과를 비교한 행렬입니다. 그리고 그 결과로는:
TP (True Positive): 올바르게 긍정으로 예측된 샘플 수
TN (True Negative): 올바르게 부정으로 예측된 샘플 수
FP (False Positive): 잘못 긍정으로 예측된 샘플 수
FN (False Negative): 잘못 부정으로 예측된 샘플 수
즉, 혼동 행렬은 모델의 성능을 직관적으로 보여주는 방법으로, 어떤 클래스에서 잘못된 예측이 발생했는지 분석할 수 있게 해줍니다.
SVM
Support Vector Machine (SVM)은 지도 학습의 분류 알고리즘 중 하나로, 주로 이진 분류 문제에 사용됩니다. SVM은 데이터를 분리하기 위해 최적의 초평면(hyperplane)을 찾는 방식으로 작동합니다. 여기서 기본 개념들을 설명하겠습니다.
일단 이 사진을 보면 클래스라는 개념을 먼저 가져와야 합니다.
여기서 클래스란 분류하고자 하는 대상의 종류를 의미합니다. 예를 들어, 스팸 이메일을 분류하는 경우 "스팸"과 "비스팸" 두 가지 클래스가 있습니다. 또 다른 예로, 고양이와 개를 분류하는 경우 "고양이"와 "개"가 각각의 클래스입니다.
즉, 여기서는 빨간색 데이터 포인트의 클래스들과, 파란색 데이터 포인트의 클래스들이 있다고 할 수 있습니다.
그 다음은 초평면입니다. 사진에서 초평면은 중간에 위치한 검은색 선이라고 할 수 있습니다. 초평면은 n차원 공간에서 (n-1)차원인 평면인데, 예를 들어, 2차원 공간에서는 초평면이 직선이 되고, 3차원 공간에서는 평면이 됩니다. 여기선 2차원이기 때문에 직선이 되는데, 두 개의 클래스 데이터를 최대한 잘 분리하는 경계를 설정하는 데 사용됩니다. 즉, 두개의 클래스가 서로 얽히지 않도록 서로 잘 분리한 경계선이라고 할 수 있습니다. 빨간색 데이터 포인트와, 파란색 데이터 포인트가 서로 얽히지 않도록 구별하게 해주는 것이라고 생각하면 편합니다.
그 다음 서포트 벡터(Support Vectors)입니다. 서포트 벡터는 사진에서 볼 수 있듯이, 서로 다른 클래스들에 있는 데이터 포인트들중, 초평면에 제일 가까운 포인트를 서포트 백터라고 부릅니다. 이 데이터 포인트들은 초평면의 위치를 결정하는 데 중요한 역할을 하며, 마진의 경계를 형성합니다.
마진은 간단히 말해서, 서포트 백터간의 거리라고 생각하시면 됩니다. 즉, 빨간색 클래스의 서포트 벡터와 파란색 클래스의 서포트 벡터 간의 거리입니다. SVM은 이 마진을 최대화하는 방향으로 초평면을 최적화하여, 두 클래스가 가능한 한 멀리 떨어지도록 합니다. 이를 통해 모델이 더 안정적으로 학습하고, 새로운 데이터 포인트에 대해서도 높은 정확도로 분류할 수 있도록 합니다. 마지막으로 커널 함수입니다. 커널 함수는 선형적이지 않은 데이터 포인트들을 고차원으로 변형한 후, 선형적으로 만드는 것 입니다. 다른 의미로는 원래의 저차원 공간에서의 데이터를 고차원으로 매핑하여, 새로운 초평면을 정의하게 됩니다. 즉, 데이터 포인트를 4차원 이상의 공간으로 변환하여, 규칙적으로 분포되어 있지 않은 데이터들을 규칙적으로 바꿔주어서 분리할 수 있게 해주는 것을 뜻합니다.
고차원 -> 4차원 이상의 차원
예를 들어, 크기가 있다고 했을 때, 크기A, 크기B로 이렇게 나누면, 2차원이 아닌, 3차원, 4차원에서도 쓸 수 있게 만들어, 선을 기준으로 나눌 수 있게 됨으로(그냥 쓸 수 있는 데이터가 많아져, 분리하기 편해진다 생각하시면 됩니다) , 더 편하게 데이터를 분리할 수 있게 해줍니다.
종합적으로 정리하자면, 'SVM은 두 클래스(데이터 포인트)간의 거리를 최대한 큰 것을 찾는것을 기준으로(마진), 그 중간에 초평면을 만들어서, 커널 함수를 사용해 데이터들을 비선형 분리 문제를 해결한다'라고 생각해주시면 됩니다.
SVM의 마진을 최대화하면서 결정 초평면을 찾아 데이터 포인트를 정확하게 분류하는 것이기 때문에, 수식을 보면,
이렇게 되어있습니다. 여기서 w는 가중치 벡터, x는 입력 벡터, b는 절편입니다. 여기서 모델은 가중치 백터를 학습하는 것이고, 제일 중요한 포인트는 이 수식은 결국 차원에 따라, 데이터에서, 마진이 가장 큰 초평면은 찾는 것이 목표인 수식입니다.
그럼이 이제 강의에 나온 코드를 한번 더 보겠습니다.
아까 나온 유방암 코드인데, 밑 부분만 달라 가져왔습니다.
from sklearn.svm import SVC
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix
# 모델 생성 및 학습
model = SVC(kernel='linear')
model.fit(X_train, y_train)
# 예측
y_pred = model.predict(X_test)
# 평가
print(f"Accuracy: {accuracy_score(y_test, y_pred)}")
print(f"Classification Report:\n{classification_report(y_test, y_pred)}")
print(f"Confusion Matrix:\n{confusion_matrix(y_test, y_pred)}")
여기서 다른 점은 바로
from sklearn.svm import SVC와
model = SVC(kernel='linear') 입니다. 한번 천천히 보겠습니다
왜 SVM이 아니라 SVC일까?
사실은 SCV는 Support Vector Classifier의 약자로, SVM 모델을 생성하고 학습시키고, 예측할 수 있는 다양한 메소드를 제공하는 역할을 하기에, SVM이 SVC에 들어가 있다고 생각하면 됩니다.
그러면 이제 SVC를 써야합니다. 클래스이기에, SVC() 형태로 있습니다. 그러면 kernel이 있는데, 바로 이 부분이 고차원으로 변형하는 단계입니다. 참고로 'linear'말고도 여러 형태를 쓸 수 있습니다.
선형 커널 (linear):데이터가 선형적으로 분리 가능할 때 사용합니다. 데이터가 두 클래스 간의 선형 경계로 나눌 수 있을 때 적합합니다.
다항 커널 (poly):다항식 형태의 경계를 만들어 데이터 포인트를 분리합니다. 데이터가 복잡한 다항식 형태로 분포할 때 유용합니다.
가우시안 RBF 커널 (rbf):데이터 포인트 간의 거리를 기준으로 비선형적인 경계를 생성합니다. 데이터가 비선형적으로 분포되어 있을 때 적합합니다.
시그모이드 커널 (sigmoid):신경망에서 사용하는 활성화 함수처럼 동작하는 커널입니다.
즉. 이 코드는 커널을 linear로 써서, 두 클래스 간의 선형 경계로 나눌 때 쓴다는 뜻입니다.
KNN
KNN은 SVM보다는 쉬운 개념을 가지고 있습니다. 하지만 KNN의 동작 방식은 사실 알고리즘과 매우 흡사하게 작동하지만 그 개념 자체는 머신 러닝입니다.
이 사진을 보면 이해할 수 있습니다. KNN은 데이터를 펼친다에 가깝습니다. KNN은 새로운 데이터 포인트를 분류할 때, 주어진 데이터 포인트와 가장 가까운 K개의 이웃(데이터 포인트)을 찾으며, 가장 가까운 이웃의 레이블(클래스)을 보고, 다수결 원칙으로 새로운 데이터 포인트의 클래스를 결정합니다. 비슷한 특성을 가진 데이터는 비슷한 범주에 속하는 경향이 있다는 가정하에 사용합니다. 사진에서 보면 저 빨간색 세모는 비슷한 구역에 있는 노란색 네모 클래스에 속한다고 말할 수 있습니다. 이것처럼 K의 데이터를 보고, 주변의 가장 가까운 데이터에 속할 그룹을 판단하는 알고리즘이 K-NN 알고리즘이라고 할 수 있습니다.
하지만, 저 K는 사용자가 설정해야 하는 하이퍼파라미터입니다. K의 값이 작을수록 모델이 더 민감하게 반응하고, 값이 클수록 더 일반화된 결과를 제공합니다. 만약 K를 4로 설정을 하면, 그 K를 중심으로 가장 가까운 초록색에 해당하는 클래스가 될것이고, 3으로 설정하면 노란색이 더 많기 때문에 노란색 클래스에 포함이 되게 됩니다. 즉 설정한 값 안에 더 많이 있는 클래스에 속하게 되는것입니다.
이번에도 마찬가지로 실습 코드를 가져와봤습니다.
이번에도 윗 부분은 동일하기에, 밑 부분만 가져왔습니다.
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix
# 모델 생성 및 학습
model = KNeighborsClassifier(n_neighbors=5)
model.fit(X_train, y_train)
# 예측
y_pred = model.predict(X_test)
# 평가
print(f"Accuracy: {accuracy_score(y_test, y_pred)}")
print(f"Classification Report:\n{classification_report(y_test, y_pred)}")
print(f"Confusion Matrix:\n{confusion_matrix(y_test, y_pred)}")
이 코드에서도 마찬가지로, KNN을 구현하기 위해,
KNeighborsClassifier을 썼고, n_neighbors와 함깨 쓰입니다.
n_neighbors=5는 K의 값을 설정합니다. 즉, 예측할 때 5개의 가장 가까운 이웃을 고려하겠다는 의미입니다.
솔직히 궁금해서 한번 구현해달라고 했습니다
실제로 보니까 진짜 어지럽습니다. 안 그런가요? 이것을 컴퓨터가 해준다는 것에 감사해야 할 것 같습니다.
나이브 베이즈
확률 기반의 머신러닝 알고리즘으로, 주로 텍스트 분류 및 스팸 필터링과 같은 문제에 사용됩니다. 이 모델은 베이즈 정리에 기반하여 특정 클래스에 속할 확률을 계산합니다. 주로 텍스트 분류 문제에 널리 사용됩니다.
그 전에, 베이즈 정리의 수식을 알아봅시다
P(C∣X): 주어진 입력 X에 대한 클래스 C의 사후 확률(즉, X가 일어났을 때, C가 일어날 확률)
P(X∣C): 클래스 C에 대한 입력 X의 우도(likelihood)
P(C): 클래스 C의 사전 확률 (prior probability)
P(X): 모든 클래스에 대한 입력 X의 확률
예를 들어 C가 우산을 들고 갈 확률, X가 비가 올 확률이라고 가정하겠습니다. 즉, 이 수식은 P(우산을 들고 갔는데(C), 비가 올 확률(X), 즉 X|C) * P(우산을 들고 갈 확률(C)) / P(비가올 확률(P))이라고 할 수 있습니다.
예를 들어 스펨을 찾는 것을 비교해 보겠습니다. 전체적으로 스펨이 확률을 P(스펨), 모든 단어들 중에 "특가"라는 단어가 포험되어 있는 경우를 P(특가)라고 하겠습니다. 그러면 특가라는 단어가 나왔을 때, 스펨일 확률을 구할 수 있게되는 것입니다. 그렇게 되면, 수식은 P(스펨(C)) | P(특가(X)) = P(특가(X)) | P(스펨(C)) * P(스펨(C)) / P(특가(X)) 라고 할 수 있습니다. |
그런데 왜 하필 나이브라는 이름이 붙여졌을까요?
왜냐하면 각 특징이 독립적이라고 가정을 하기 때문입니다. 하지만 모든 특성이 독립적이라고 가정하므로, 실제로는 잘 맞지 않는 경우가 많습니다.
예를 들어, 동전을 던져서 앞이 나올 확률과, 주사위를 던져서 나올 확률에서 서로에게 전혀 관계가 없습니다(서로 독립적). 그렇기에 두 확률을 서로 곱해서 쓸 수 있다는 뜻입니다. 만약 서로간의 확률에 서로 영향을 미친다면 그것은 독립적이라고 할 수 없습니다.
나이브 베이즈의 종류
1. 가우시안 나이브 베이즈 (Gaussian Naive Bayes): 연속적인 특성이 정규 분포를 따른다고 가정합니다. (즉, 분포 중에서 정규 분포가 있는데, 정규 분포를 따를 때 사용하는 것)
2. 다항 나이브 베이즈 (Multinomial Naive Bayes): 각 클래스에서 특성이 카운트 데이터(예: 단어 수)를 따른다고 가정합니다. 텍스트 분류에서 일반적으로 사용됩니다. (다항 분포를 따를 때 사용하는 것)
3. 베르누이 나이브 베이즈 (Bernoulli Naive Bayes): 각 특성이 이진(0 또는 1) 값을 가질 때 사용됩니다.
Tip
여기서 말하는 분포란? -> 분포는 데이터가 어떻게 퍼져 있는지, 즉 각 특성(변수)의 값들이 어떻게 나타나는지에 대한 확률적인 패턴 을 의미합니다
강의에 나오는 실습을 보도록 하겠습니다.(여기서 거의 다를게 없는....)
from sklearn.naive_bayes import GaussianNB
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix
# 모델 생성 및 학습
model = GaussianNB()
model.fit(X_train, y_train)
# 예측
y_pred = model.predict(X_test)
# 평가
print(f"Accuracy: {accuracy_score(y_test, y_pred)}")
print(f"Classification Report:\n{classification_report(y_test, y_pred)}")
print(f"Confusion Matrix:\n{confusion_matrix(y_test, y_pred)}")
from sklearn.naive_bayes import GaussianNB을 사용하여 나이브 베이즈를 구현,
GuassianNB()를 이용해 나이브 베이즈를 사용합니다.
의사결정나무
의사결정나무는 쉽게 말해서 조건에 의해 계속해서 결과가 걸러진다고 생각하시면 편합니다.
즉, 규칙을 학습하여 이를 트리 구조로 표현합니다. 이 트리는 여러 질문을 하고, 그 질문에 따라 데이터를 가지(Branches)로 나눠가며 최종적으로 결론(Leaf Nodes)을 도출합니다.
여기서 주요 개념들이 있습니다.
1. 루트 노드(Root Node) : 트리의 가장 위에 있는 첫 번째 노드입니다. 이 노드는 데이터를 나누기 시작하는 첫 번째 기준을 결정합니다. 예를 들어 사진에 있는 제일 위에 있는 것이 루트 노드입니다.
2. 내부 노드(Internal Nodes) : 각 질문(조건)에 따라 나눠진 가지들의 중간 지점입니다. 이 노드들은 트리의 중간에서 데이터를 더 세분화합니다. 예를 들어 날 수 있나요? 지느러미가 있나요? 처럼 노드에서 계속해서 나뉘어지는 중간 중간 부분입니다.
3. 가지(Branches) : 각각의 조건에 따른 결과를 나타내는 선입니다. 트리에서 데이터를 조건에 따라 나눌 때, 그 조건에 따라 다른 가지로 나누어집니다. 예를 들어 사진에 있는 True, False 처럼 조건에 의해 걸러지는 것을 말합니다.
4. 잎 노드(Leaf Nodes) : 트리의 가장 끝 부분으로, 더 이상 데이터를 나누지 않는 결론을 나타냅니다. 이곳에서 최종적인 분류 결과나 예측 값이 나옵니다. 한 마디로, 더 이상 거를 데이터가 없느 상태, 마지막 잎을 말하는 겁니다.
의사결정나무에는 학습 과정이 있습니다.
질문 선정: 알고리즘은 데이터를 여러 가지 조건으로 나누어 보고, 가장 잘 분리하는 기준을 찾아냅니다. 이 기준은 주로 지니 불순도(Gini Impurity)나 엔트로피(Entropy) 같은 수식을 사용하여 결정됩니다.
가지 나누기: 각 질문에 따라 데이터를 나눕니다. 예를 들어, 키가 170cm 이상인지 아닌지를 묻고, 그 결과에 따라 두 그룹으로 데이터를 나눕니다.
반복: 각 그룹에 대해 다시 질문을 던지고, 다음 기준으로 나누는 과정을 반복합니다. 이 과정을 트리 구조로 표현하여 최종적으로 모든 데이터를 분류합니다.
종료: 더 이상 데이터를 나눌 필요가 없을 때, 즉 모든 데이터가 완벽하게 분류되었거나 더 이상 의미 있는 질문을 만들 수 없을 때 트리 생성을 멈춥니다.
잠깐! 지니 계수와 정보 이득(엔트로피)이란?
정보 이득:
불확실성을 나타내며, 값이 낮을수록 불확실성이 적습니다.
지니 계수:
불순도를 확인하며, 계수가 낮을수록 불순도가 적습니다.
오늘은 여기까지...고생하셨습니다.