본문 바로가기

CS/AI

[ML] Scikit-learn을 활용해서 캐글 데이터 분석하기!

반응형

안녕하세요. 책 하나 겁나 파고 있는 짐민입니다.

 

이번에는 

 

파이썬 머신러닝 완벽 가이드 | 권철민 - 교보문고

파이썬 머신러닝 완벽 가이드 | 자세한 이론 설명과 파이썬 실습을 통해 머신러닝을 완벽하게 배울 수 있습니다!《파이썬 머신러닝 완벽 가이드》는 이론 위주의 머신러닝 책에서 탈피해, 다양

product.kyobobook.co.kr

 

이 책에서 캐글 데이터를 하나 불러와서 직접 3가지 알고리즘을 통해서 데이터 정확도를 비교해보겠습니다.

 

캐글 데이터 중에서 타이타닉 탑승자 데이터를 가지고 실습하는 부분을 해보았습니다.

 

 

이런 데이터입니다.


전처리

 

우선 데이터를 사용하기 전에 전처리 과정을 거쳐야 합니다.

Nullish한 값들을 모두 제거해주겠습니다.

def handleNa(df):
  df.fillna({
      'Age': titanic_df['Age'].mean(),
      'Cabin' : 'N',
      'Embarked':'N',
      'Fare' : 0
      }, inplace=True)

  return df

 

함수로 만들어서 사용하겠습니다.

 

 
titanic_df['Age'].fillna(titanic_df['Age'].mean(), inplace=True)

 

책에는 이렇게 하라고 나와있는데, Pandas 3 업데이트 때 deprecated되는 방식이라고 에러가 자꾸 떠서

위 방식대로 했습니다. 더 보기도 좋은 건 덤.

 

from sklearn.preprocessing import LabelEncoder

def encode_features(df):
  df['Cabin'] = df['Cabin'].str[:1]
  features = ['Cabin', 'Sex', 'Embarked']
  for feature in features:
    le = LabelEncoder()
    le = le.fit(df[feature])
    df[feature] = le.transform(df[feature])

  return df

 

레이블 인코딩을 진행해줍니다.

LabelEncoder을 사용하면 레이블의 String값을 숫자로 변환해줍니다.

 

features_titanic_df = titanic_df.drop(['Survived', 'PassengerId', 'Name', 'Ticket'], axis=1)
label_titanic_df = titanic_df['Survived']

 

마지막으로 여러 값들에 따라 생존 여부가 어떻게 갈리는지 테스트해보기 위해 feature과 label로 나눕니다.

이 과정에서 필요없는 이름이나 ID 같은 값은 날려버립니다.

NaN 없음, 모두 숫자로 이루어진 데이터들

 

그러면 이렇게 예쁜 데이터들이 나왔습니다.

 

from sklearn.model_selection import train_test_split, cross_val_score, GridSearchCV
from sklearn.ensemble import RandomForestClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.linear_model import LogisticRegression

f_train, f_test, label_train, label_test = train_test_split(features_titanic_df, label_titanic_df, test_size=0.2)

dt_clf = DecisionTreeClassifier(random_state=11)
rf_clf = RandomForestClassifier(random_state=11)
lr_clf = LogisticRegression(solver='liblinear')

 

결정 트리, 랜덤 포레스트, 로지스틱 회귀 알고리즘을 사용해볼게요.

 

피쳐와 레이블을 모두 학습용과 테스트용으로 각각 8:2로 나누고

각 분류 알고리즘을 불러오겠습니다.

(로지스틱 회귀는 회귀 알고리즘이라고 하지만 분류에도 쓰인다고 하네요)

 

dt_clf.fit(f_train, label_train)
dt_pred = dt_clf.predict(f_test)
print('DTClassifier 정확도, {0:.4f}'.format(accuracy_score(label_test, dt_pred)))

rf_clf.fit(f_train, label_train)
rf_pred = rf_clf.predict(f_test)
print('RFClassifier 정확도, {0:.4f}'.format(accuracy_score(label_test, rf_pred)))


lr_clf.fit(f_train, label_train)
lr_pred = lr_clf.predict(f_test)
print('LogisticRegression 정확도, {0:.4f}'.format(accuracy_score(label_test, lr_pred)))

 

어차피 알고리즘 구현해서 쓰는 것도 아니고 다 fit() 후 predict()라서 사용법은 비슷비슷합니다.

 

 

로지스틱 회귀가 대체적으로 정확도가 높은 모습을 보였으나 매번 달라서 유동적입니다.

 

scores = cross_val_score(rf_clf, features_titanic_df, label_titanic_df, cv=5)
print("랜덤 포레스트 5회 평균: ", np.mean(scores))

 

한 번씩 돌려본 결과는 불확실하니까 여러 번 교차 검증을 통해 정확도를 살펴볼까요?

랜덤 포레스트 5회 평균이 0.8137153976523758이 나왔습니다.

parameters = {
    'max_depth': [2,3,5,10],
    'min_samples_split': [2,3,5],
    'min_samples_leaf': [1,5,8]
}

grid_dclf = GridSearchCV(dt_clf, param_grid=parameters, scoring='accuracy', cv=5)
grid_dclf.fit(f_train, label_train)

print('최적 하이퍼 파라미터:', grid_dclf.best_params_)
print('GridSearchCV 최적화 정확도:{0: .4f}'.format(grid_dclf.best_score_))
best_dclf = grid_dclf.best_estimator_

dpredictions = best_dclf.predict(f_test)
accuracy = accuracy_score(label_test, dpredictions)
print('테스트 세트에서의 DecisionTreeClassifier 정확도 : {0:.4f}'.format(accuracy))

 

GridSearchCV를 사용해서 하이퍼 파라미터를 구해 최적의 방법을 찾아보겠습니다.

 

결정 트리에는 

max_depth, min_samples_split, min_samples_leaf, criterion, max_features

이런 파라미터들의 조작을 통해 나올 수 정확도를 조정할 수 있습니다.

 

코드의 경우에는 앞의 세 개를 조절해보면서 5번의 교차 검증을 거칩니다.

 

즉 4*3*3 개의 파라미터 경우의 수마다 5번의 교차 검증을 거치기 때문에

이것만 해도 꽤 시간이 걸리는 작업입니다.

 

아무튼 하이퍼 파라미터를 찾아서 정확도를 높이는 데에도 성공했습니다!

 


 

이상 Scikit-learn을 활용하여 실제 데이터를 다루는 실습을 해보았습니다.

감사합니다.