(파이썬) 빅데이터 분석기사 실기 - 제2유형, 분류

Page content

작업형 2유형 최종정리

  • 작업형1 : 3문제 (30점), 데이터 전처리
  • 작업형2 : 1문제 (40점), 분류/회귀 예측 모델링
  • 작업형3 : 2문제 (30점), 가설 검정

주요 라이브러리

  • palmerpenguins : 팔머펭귄 데이터셋의 목표는 iris 데이터셋의 대안으로 데이터 탐색 및 시각화를 위한 데이터셋 제공.
  • scikit-learn : 머신러닝을 위한 라이브러리
  • lightgbm : LightGBM은 Microsoft에서 개발한 오픈 소스 기계 학습 라이브러리로, 대용량 데이터셋에서 빠른 속도와 높은 성능을 제공하는 것이 특징

주의

  • 각 코드에 대한 설명은 별도로 하지 않습니다.

데이터 불러오기

import pandas as pd 
from palmerpenguins import load_penguins 

penguins = load_penguins()
penguins['ID'] = penguins.reset_index().index + 1
penguins.head()

Untitled

  • 컬럼의 순서를 변경하도록 한다.
cols = penguins.columns.tolist()
cols = cols[-1:] + cols[:-1]
print(cols)

[결과]
['ID', 'species', 'island', 'bill_length_mm', 'bill_depth_mm', 'flipper_length_mm', 'body_mass_g', 'sex', 'year']
penguins = penguins[cols]
penguins

Untitled

데이터 가공

  • 지금까지 열린 대회에서는 결측치가 존재 하지 않았던 것으로 기억
    • 만약 잘못된 정보라면 알려주세요
    • 결측치를 제거한다.
  • sex 컬럼의 데이터는 male 1, female 0 이렇게 변환하기 위해 LabelEncoder를 사용한다.
from sklearn.preprocessing import LabelEncoder

# 결측치 제거
penguins = penguins.dropna().reset_index(drop=True)

# sex 성별 0과 1로 변경하기
le = LabelEncoder()
le.fit(penguins['sex'])

penguins['sex'] = le.transform(penguins['sex']) # male 1, female 0
penguins

Untitled

데이터셋 분리

  • 기사시험과 같이 데이터셋을 만들기 위해 데이터셋을 분리하고 저장한다.
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder

le = LabelEncoder()
le.fit(penguins['sex'])

penguins['sex'] = le.transform(penguins['sex']) + 1
y = penguins['sex']
X = penguins.drop(['sex'], axis=1)

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

X_train.to_csv("penguin_clf_X_train.csv", index=False)
X_test.to_csv("penguin_clf_X_test.csv", index=False)
y_train.to_csv("penguin_clf_y_train.csv", index=False)
y_test.to_csv("penguin_clf_y_test.csv", index=False)

분류모형 만들기 정리

  • 기본적으로 아래 데이터셋 불러오기는 제공된다.
import pandas as pd 

X_train = pd.read_csv("penguin_clf_X_train.csv")
X_test = pd.read_csv("penguin_clf_X_test.csv")
y_train = pd.read_csv("penguin_clf_y_train.csv")

ID 제거

X_train_id = X_train.pop("ID")
X_test_id = X_test.pop("ID")

데이터 확인

X_train.head()

Untitled

y_train.head()

Untitled

X_test.head()

Untitled

결측치 확인

X_train.isnull().sum()

[결과]
species              0
island               0
bill_length_mm       0
bill_depth_mm        0
flipper_length_mm    0
body_mass_g          0
year                 0
dtype: int64
X_test.isnull().sum()

[결과]
species              0
island               0
bill_length_mm       0
bill_depth_mm        0
flipper_length_mm    0
body_mass_g          0
year                 0
dtype: int64
y_train.isnull().sum()

[결과]
sex    0
dtype: int64
y_train.head()

Untitled

컬럼 분리

  • 범주형 컬럼과 숫자형 컬럼으로 분리
import numpy as np

cat_cols = X_train.select_dtypes(exclude = np.number).columns.tolist()
num_cols = X_train.select_dtypes(include = np.number).columns.tolist()
print(cat_cols, num_cols)

[결과]
['species', 'island'] ['bill_length_mm', 'bill_depth_mm', 'flipper_length_mm', 'body_mass_g', 'year']
  • year은 num_cols에서 제거한다.
num_cols.remove("year")
num_cols

[결과]
['bill_length_mm', 'bill_depth_mm', 'flipper_length_mm', 'body_mass_g']

데이터셋 분리

from sklearn.model_selection import train_test_split

X_tr, X_val, y_tr, y_val = train_test_split(
    X_train, y_train['sex'], 
    stratify = y_train['sex'], 
    test_size=0.3, 
    random_state=42
)

X_tr.shape, X_val.shape, y_tr.shape, y_val.shape

[결과]
((163, 7), (70, 7), (163,), (70,))

모형 만들기

  • pipeline을 활용하여 모형을 만들면, 매우 쉽게 작성할 수 있다.
  • OrdinalEncoder를 추가할 때는 아래와 같이 작성한다.
    • ord_encoder 영역만 살펴본다.
from sklearn.preprocessing import OrdinalEncoder
from sklearn.compose import ColumnTransformer

column_transformer = ColumnTransformer([
    ("scaler", StandardScaler(), num_cols),
    ("ohd_encoder", OneHotEncoder(), cat_cols)
    ("ord_encoder", OrdinalEncoder(categories=[["Adelie", "Gentoo", "Chinstrap"]]), ['species'])
], remainder="passthrough")
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline 
from sklearn.utils.fixes import loguniform
from sklearn.metrics import roc_auc_score
from lightgbm import LGBMClassifier
from sklearn.model_selection import RandomizedSearchCV

param_grid = {
    "clf__learning_rate": loguniform(0.0001, 0.1), 
    "clf__n_estimators" : np.arange(100, 500), 
    "clf__max_depth" : np.arange(3, 30, 2), 
    "clf__num_leaves" : np.arange(30, 50), 
    "clf__min_split_gain" : np.arange(0, 1.1, 0.1), 
    "clf__subsample" : np.arange(0.1, 0.9, 0.1)
}

column_transformer = ColumnTransformer([
    ("scaler", StandardScaler(), num_cols), 
    ("ohd_encoder", OneHotEncoder(), cat_cols)
], remainder="passthrough")

pipeline = Pipeline([
    ("preprocessing", column_transformer), 
    ("clf", LGBMClassifier(random_state=42))
])

random_search = RandomizedSearchCV(
    estimator=pipeline, 
    param_distributions = param_grid, 
    n_iter = 10, 
    scoring="roc_auc", 
    cv=5, 
    verbose=-1, 
    n_jobs=-1
)

random_search.fit(X_tr, y_tr)

[결과]
RandomizedSearchCV(cv=5,
                   estimator=Pipeline(steps=[('preprocessing',
                                              ColumnTransformer(remainder='passthrough',
                                                                transformers=[('scaler',
                                                                               StandardScaler(),
                                                                               ['bill_length_mm',
                                                                                'bill_depth_mm',
                                                                                'flipper_length_mm',
                                                                                'body_mass_g']),
                                                                              ('ohd_encoder',
                                                                               OneHotEncoder(),
                                                                               ['species',
                                                                                'island'])])),
                                             ('clf',
                                              LGBMClassifier(random_state=42))]),
                   n_jobs=-1,
                   param_distributions={'...
       451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463,
       464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476,
       477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489,
       490, 491, 492, 493, 494, 495, 496, 497, 498, 499]),
                                        'clf__num_leaves': array([30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
       47, 48, 49]),
                                        'clf__subsample': array([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8])},
                   scoring='roc_auc', verbose=-1)

평가확인

def get_score(model, X_tr, X_val, y_tr, y_val):
    tr_pred = model.predict(X_tr) # 만약 확률로 구할시, predict_proba()[:, 1]
    val_pred = model.predict(X_val)
    tr_score = roc_auc_score(y_tr, tr_pred)
    val_score = roc_auc_score(y_val, val_pred)
    return f"train: {tr_score}, validation: {val_score}"

get_score(random_search, X_tr, X_val, y_tr, y_val)

[결과]
'train: 0.9689759036144577, validation: 0.8839869281045751'

평가 제출

final_preds = random_search.predict(X_test)
result = pd.DataFrame({
    "ID" : X_test_id, 
    "preds": final_preds
})

result

Untitled