주제

1. Classification 모델 종류
2. Classification 모델 성능 평가
3. scikit-learn의 데이터 전처리 기능
4. 숙제

 

1. Classification 모델 종류

  • 데이터를 다야한 클래스로 분류하는 데 사용
  • 종류 :
    • 이진 분류(Binary Classification) : 두 개의 클래스로 분류
    • 다중 클래스 분류(Multiclass Classification) : 3개 이상의 클래스로 분류
    • 다중 레이블 분류(Multilabel Classification) : 한 레코드가 여러 클래스에 할당될 수 있음
  • 알고리즘의 종류 :
    • Logistic Regression : 이진 분류 문제에 사용
    • Decision Tree : 직관적이고 시각화가 쉬움
    • Random Forests
    • Support Vector Machine : 복잡한 분류 문제에 효과적
    • Deep Learning : 고급 분류 문제에 사용(이미지 및 음성 인식 등)

1.1 Logisitic Regression vs. Softmax Regression

Linear Regression Logisitic Regression Softmax Regression
regression binary classification multi-label classification
공부 시간에 따른 시험 점수 예측 공부 시간에 따른 시험 합격 예측 공부시간에 따른 학점 예측

 

1.2 Support Vector Machine

  • feature space를 변환하여 분류 작업 수행

SVM

1.3 Decision Tree

  • 회귀 문제에도 사용 가능
  • 피쳐의 중요도가 나오고 동작 방식을 상대적으로 이해하고 설명이 가능함

 

2. Classification 모델 성능 평가

 

2.1 Confusion Matrix

  • Precision = TP / (TP + FP) → 양성으로 예측된 것중 실제로 양성인 것
  • Recall = TP / (TP + FN) → 실제 양성 중 얼마나 양성으로 예측되었는가
  • F1 score = 2 * (precision * recall) / (precision + recall) → precision과 recall의 조화평균
  • Accuracy = (TP + TN) / (TP + TN + FP + FN)
  • True Positive(TP) : 스팸을 스팸이라 판정하는 경우
  • False Positive : 정상리뷰를 스팸이라 판정하는 경우
    • 모든 리뷰를 스팸이라고 판정하면 TPR은 100%지만 FPR도 100%
    • 모든 리뷰를 정상이라고 판정하면 FPR은 0%지만 TPR도 0%
  • Binary classifier는 확률을 반환
    • 어떤 threshold(임계치)를 사용할지 결정하는게 ROC

 

2.2 ROC 커브

  • Receiver Operating Characteristic : Binary classifier의 정확도를 보기 위한 용도
  • True Positive Rate을 y축, False Positive Rate을 x축으로 그린 그래프
  • 이 그래프를 통해 TPR은 높게, FPR은 낮게 만드는 최적의 위치를 찾음
  • 이 커브의 밑 면적을 계산한 것이 AUC
  • AUC는 0 ~ 1 사이의 값을 가지며 1과 가까울수록 모델이 정확함을 의미
  • AUC값을 보고 이진 분류의 경우에는 threshold를 결정함

 

 

3. scikit-learn의 데이터 전처리 기능

  • 큰 흐름 :
    • 머신 러닝 알고리즘과 모델 성과 지표 결정
    • 데이터셋 로딩
    • 데이터셋을 훈련/테스트 세트로 분리
    • 훈련 데이터 전처리
    • 훈련 데이터로 모델 빌딩
    • 테스트 데이터 전처리
    • 레이블 정보 제외 테스트 데이터를 모델에 입력으로 지정
    • 결과물과 정답을 비교하여 성과 계산

3.1 피쳐 추출과 변환

  • 피쳐값들을 훈련에 적합한 형태로 바꾸는 것(Data Transformations)
  • 데이터 전처리
  • 비어있는 필드값 채우기(Imputation of missing values)
    • Imputer를 이용하여 기본값을 정해서 결측치 채우기
    • sklearn.preprocessing 패키지 안에 2개의 Imputer가 존재
      • SimpleImputer : 간단한 통계를 지정하여 누락된 값을 대체
      • IterativeImputer : 결측값이 있는 각 피쳐를 다른 피쳐들의 함수로 지정
import numpy as np
from sklearn.impute import SimpleImputer

# Example dataset with missing values
data = np.array([
    [1, np.nan, 3],
    [4, 3, np.nan],
    [np.nan, 6, 9],
    [8, 5, 2]
])
imputer = SimpleImputer(missing_values=np.nan, strategy='mean')
imputed_data = imputer.fit_transform(data)

print("Original Data:")
print(data)
print("\nImputed Data:")
print(imputed_data)

SimpleImputer로 평균값을 기본값으로 지정

from sklearn.experimental import enable_iterative_imputer
from sklearn.impute import IterativeImputer

iterative_imputer = IterativeImputer(max_iter=10, random_state=0)
imputed_data = iterative_imputer.fit_transform(data)

print("Original Data:")
print(data)
print("\nImputed Data:")
print(imputed_data)

IterativeImputer

  • 카테고리를 숫자로 변환
    • sklearn.preprocessing 패키지 안에 여러 인코더가 존재함
      • OneHotEncoder : 서로 관계 없는 카테고리들을 인코딩하는 경우
      • LabelEncoder : 레이블 필드를 인코딩하는 경우
      • OrdinalEncoder : 순서가 있는 카테고리들을 인코딩하는 경우
    • OneHotEncoder vs. OrdinalEncoder
from sklearn.preprocessing import OrdinalEncoder
from sklearn.preprocessing import OneHotEncoder

data = [['seoul'], ['tokyo'], ['beijing']]
encoder = OrdinalEncoder()
result = encoder.fit_transform(data)

encoder.categories_

result

result(OrdinalEncoder)

enc = OneHotEncoder(sparse=False)
enc.fit(data)
X_ohe = enc.transform(data)

X_ohe

X_ohe(OneHotEncoder)

from sklearn.preprocessing import LabelEncoder

y = ['recurrence-events', 'no-recurrence-events', 'recurrence-events']

label_encoder = LabelEncoder()
y_labeled = label_encoder.fit_transform(y)

print(y_labeled)

y_labled(LabelEncoder)

  • 숫자 필드값의 범위 표준화
    • sklearn.preprocessing 패키지 안에 여러 스케일러가 존재함
      • StandardScaler : 각 값에서 평균을 빼고 표준편차로 나눔. 값의 분포를 정규분포를 따르도록 변환
      • MinMaxScaler : 모든 값을 0과 1사이로 스케일. 각 값에서 최소값을 빼고(최대값 - 최소값)으로 나눔
      • RobustScaler, MaxAbsScaler, etc...
from sklearn.preprocessing import StandardScaler
from sklearn.preprocessing import MinMaxScaler
import numpy as np

X_train = np.array([[ 1., -1.,  2.],
    [ 2.,  0.,  0.],
    [ 0.,  1., -1.]])
scaler = StandardScaler().fit(X_train)
X_scaled = scaler.transform(X_train)
print(X_scaled)

 

StandardScaler

 

scaler = MinMaxScaler().fit(X_train)
X_scaled = scaler.transform(X_train)
print(X_scaled)

MinMaxScaler

 

3.2 파이프라인 사용해보기

  • 파이프라인으로 표준화와 알고리즘 학습까지 한번에 묶어 실시
from sklearn.datasets import make_classification
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler

X, y = make_classification(random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=42)

pipe = make_pipeline(StandardScaler(), LogisticRegression())
pipe.fit(X_train, y_train)
pipe.score(X_test, y_test)

 

3.3 Classification 리포트 생성

  • 각종 성능 평가 지표를 한번에 볼 수 있는 리포트 생성
from sklearn.metrics import classification_report

classificationReport = classification_report(y_test, predicted)
print(classificationReport)

classification report

 

 

4. 숙제

  • Age 필드의 빈 값을 SingleImputer를 이용하여 평균으로 채우기
  • Embarked 필드 :
    • 빈 값을 가장 흔한 값으로 채우기
    • OneHotEncoder를 사용하여 변환 후 학습 필드로 추가하여 모델링 진행해보기
  • 최종 classification report 실행 후 화면 제출

4.1 Age 필드 채우기

  • 결측치를 채우기 전 데이터의 info

  • Age는 714개의 데이터가 존재
  • SimpleImputer를 사용하여 평균값으로 결측치 대체
# Age의 빈 값을 평균으로 채우기
imputer = SimpleImputer(strategy='mean')
train[['Age']] = imputer.fit_transform(train[['Age']])

Age가 다 채워진 모습

 

4.2 Embarked 필드

  • Embarked 필드도 마찬가디로 889개의 데이터가 존재(2개의 결측치 확인)
  • SimpleImputer로 가장 흔한 값으로 채워넣기
# Embarked 필드의 결측치를 가장 흔한 값으로 채우기
imputer = SimpleImputer(strategy='most_frequent')
train[['Embarked']] = imputer.fit_transform(train[['Embarked']])
train.info()

채워진 모습

  • Embarked의 고유값은 총 3개(C, S, Q)로 승선지역의 이니셜을 나타냄
  • OneHotEncoder를 사용하여 인코딩 진행
# Embarked 필드 인코딩하기
from sklearn.preprocessing import OneHotEncoder

embarked_col = train[['Embarked']]
encoder = OneHotEncoder(sparse_output=False)
embarked_encoded = encoder.fit_transform(embarked_col)

# 데이터 프레임으로 변환
embarked_df = pd.DataFrame(embarked_encoded)

인코딩된 모습

  • 원래 데이터에 결합하고 column명 변경
train_encoded = pd.concat([train, embarked_df], axis=1)

train_encoded.rename(columns={0: 'C', 1: 'Q', 2: 'S'}, inplace=True)

 

4.3 모델링

  • 훈련 데이터 만들기
train = train_encoded.drop(
  ['PassengerId', 'Name', 'Ticket', 'Cabin', 'Sex', 'Embarked', 'Parch', 'SibSp'],
  axis=1
)

필요없는 컬럼은 모두 제거

  • 훈련 세트 / 테스트 세트 나누기
# 훈련 데이터 만들기
X = train[["Pclass", "Gender", "Age", "C", "Q", "S"]]
y = train["Survived"]
X_train, X_test, y_train, y_test = train_test_split(X,y,test_size = 0.2)
  • 스케일링 진행
# 스케일링
scaler = MinMaxScaler()
scaler.fit(X_train)
X_scaled = scaler.transform(X_train)
X_test_scaled = scaler.transform(X_test)
  • 로지스틱 회귀 모델 만들기
# Logistic Regression 모델 만들기
lr = LogisticRegression(random_state=1)
log_reg = lr.fit(X_scaled, y_train)
  • 검증
expected   = y_test
predicted  = log_reg.predict(X_test_scaled)

classificationReport = classification_report(expected, predicted, target_names=["Died", "Survived"])
print(classificationReport)

최종 classification report

 

4.4 결과 해석

  • Embarked 필드를 추가하지 않고 학습한 모델의 정확도는 81%였다.
  • Embarked 필드를 추가한 후의 정확도는 82%로 큰 차이를 보이지 않았다.
  • 이는 승객의 승선지역은 생존 여부에 큰 영향을 미치지 않은 것으로 보인다.

 

 


느낀점 

타이타닉 데이터를 처음 접했을 때는 머신러닝을 몰라서 단순하게 성별과 나이, 등급 정도로만 사용하여 단순 예측을 했었는데(정확도가 약 75% 정도였던 것으로 기억), 머신 러닝 알고리즘을 사용하여 데이터 스케일링도 하고 학습시켜보니 정확도가 올라가는게 신기하다. 숙제를 하면서도 크게 어렵지 않게 재밌게 했다. 알고리즘을 바꾸면 더 높은 정확도가 나오지 않을까...? 시간나면 해봐야겠다. 아무튼 머신 러닝 수업 시작 전에는 마냥 무서웠는데 막상 해보니 재미가 더 큰 것 같다. 더 깊게 공부해보고 싶다는 생각도 든다. 

+ Recent posts