지난 포스팅에서는 주요 칼럼이라고 생각되는 것들과 레이블 데이터인 생존(Survived)의 관계를 시각화하는 과정까지 했다.
레이블 인코딩
이번에는 문자열로 되어있는 데이터, 즉, DataFrame에서는 object 형이라고 표현되어있는 데이터를 숫자형으로 바꿔주는 작업을 할 것이다. 이런 과정을 LabelEncoding이라고 하고, Scikit learn에서는 LabelEncoder 클래스를 통해서 구현할 수 있다. LabelEncoder 객체를 통해서 fit / transform 과정을 거치면 0 ~ (카테고리 유형 수 -1) 까지의 숫자 값으로 변환된다.
from sklearn import preprocessing
def encode_features(dataDF):
features = ['Cabin', 'Sex','Embarked']
for feature in features:
le = preprocessing.LabelEncoder()
le = le.fit(dataDF[feature])
dataDF[feature] = le.transform(dataDF[feature])
return dataDF
titanic_df = encode_features(titanic_df)
titanic_df.head()
최종 전처리 함수 제작
이미지를 보면 기존에는 string 형태(object) 였던 'Sex', 'Cabin', 'Embarked' 칼럼의 데이터 값들이 전부 숫자형으로 바뀐 것을 확인할 수 있다. Null 처리 / 불필요한 속성 제거('PassengerId' ,' Name', 'Ticket') / 레이블 인코딩을 한꺼번에 수행하는 함수를 제작한다.
#Null 처리 함수
def fillna(df):
df['Age'].fillna(df['Age'].mean(), inplace = True)
df['Cabin'].fillna('N' , inplace= True)
df['Embarked'].fillna('N', inplace = True)
df['Fare'].fillna(0, inplace = True)
return df
#머신러닝 알고리즘에 불필요한 속성 제거
def drop_features(df):
df.drop(['PassengerId' ,'Name', 'Ticket'], axis = 1, inplace = True)
return df
#레이블 인코딩 수행
def format_features(df):
df['Cabin'] = df['Cabin'].str[:1]
features = ['Cabin', 'Sex', 'Embarked']
for feature in features:
le = preprocessing.LabelEncoder()
le = le.fit(df[feature])
df[feature] = le.transform(df[feature])
return df
#앞에서 설정한 데이터 전처리 함수 호출
def transform_features(df):
df = fillna(df)
df = drop_features(df)
df = format_features(df)
return df
학습 / 테스트 데이터 분리
원본 데이터를 다시 로딩하고, 전처리 함수(transform_features())를 실행한다. 이렇게 전처리한 데이터를 train_test_split() 메서드를 통해서 학습 데이터와 테스트 데이터로 분리한다.
#원본 데이터를 재로딩하고, 피처 데이터 세트와 레이블 데이터 세트 추출
titanic_df = pd.read_csv('./titanic_train.csv')
y_titanic_df = titanic_df['Survived']
X_titanic_df = titanic_df.drop('Survived', axis = 1)
X_titanic_df = transform_features(X_titanic_df)
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X_titanic_df, y_titanic_df, test_size = 0.2, random_state = 11)
학습 / 예측 수행
이제 Scikit-Learn에서 제공하는 결정 트리, 랜덤 포레스트, 로지스틱 회귀를 알고리즘 모델로 사용할 것이고, 정확도를 성능 평가 지표로 사용할 것이다. 그러기 위해서 Scikit-Learn으로부터 해당 모듈을 임포트하여 학습 - 예측 - 평가의 과정을 진행한다.
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
#결정트리, Random Forest, 로지스틱 회귀를 위한 사이킷런 Classifier 클래스 생성
dt_clf = DecisionTreeClassifier(random_state = 11)
rf_clf = RandomForestClassifier(random_state = 11)
lr_clf = LogisticRegression()
#Decision Tree 학습 / 예측 / 평가
dt_clf.fit(X_train, y_train)
dt_pred = dt_clf.predict(X_test)
print('DecisionTreeClassifier 정확도 : {0:.4f}'.format(accuracy_score(y_test, dt_pred)))
#RandomForestClassifier 학습 / 예측 / 평가
rf_clf.fit(X_train, y_train)
rf_pred = rf_clf.predict(X_test)
print('RandomForestClassifier 정확도 : {0:.4f} '.format(accuracy_score(y_test, rf_pred)))
#LogisticRegression 학습 / 예측 / 평가
lr_clf.fit(X_train, y_train)
lr_pred = lr_clf.predict(X_test)
print('LogisticRegression 정확도 : {0:.4f}'.format(accuracy_score(y_test, lr_pred)))
결정트리는 78%, 랜덤 포레스트는 83%, 로지스틱 회귀는 86%의 정확도가 나오는 것을 확인할 수 있다. 그 후에, 성능 향상을 위해서 교차 검증을 수행한다. 교차 검증은 KFold 혹은 cross_val_score가 있는데, 둘이 어떤 차이점을 가지고 있는지에 대해서도 알아볼 것이다.
교차 검증 (KFold, cross_val_score)
일단 KFold를 통해서 교차 검증을 수행하는 함수를 제작한다.
from sklearn.model_selection import KFold
def exec_kfold(clf, folds = 5):
#폴드 세트를 5개인 KFold 객체를 생성, 폴드 수만큼 예측 결과 저장을 위한 리스트 객체 생성
kfold = KFold(n_splits = folds)
scores = []
#KFold 교차 검증 수행
for iter_count, (train_index, test_index) in enumerate(kfold.split(X_titanic_df)):
#X_titanic_df 데이터에서 교차 검증별로 학습과 검증 데이터를 가리키는 index 생성
X_train, X_test = X_titanic_df.values[train_index], X_titanic_df.values[test_index]
y_train, y_test = y_titanic_df.values[train_index], y_titanic_df.values[test_index]
#Classifier 학습 / 예측 / 정확도 계산
clf.fit(X_train, y_train)
predictions = clf.predict(X_test)
accuracy = accuracy_score(y_test, predictions)
scores.append(accuracy)
print('교차 검증 {0} 정확도 : {1:.4f}'.format(iter_count, accuracy))
#5개 fold에서의 평균 정확도 계산
mean_score = np.mean(scores)
print('평균 정확도 : {0:.4f}'.format(mean_score))
#exec_kfold 호출
exec_kfold(dt_clf, folds = 5)
평균 정확도가 78.23%정도 나온 것을 확인할 수 있다. 이후에 cross_val_score를 통해서 교차 검증을 수행해본다.
from sklearn.model_selection import cross_val_score
scores= cross_val_score(dt_clf, X_titanic_df, y_titanic_df, cv = 5)
for iter_count, accuracy in enumerate(scores):
print('교차 검증 {0} 정확도 : {1:.4f}'.format(iter_count, accuracy))
print('평균 정확도 : {0:.4f}'.format(np.mean(scores)))
이 경우에는 78.35로 미세하게나마 성능이 향상된 것을 볼 수 있다. 이는 레이블 데이터의 비율을 맞춰서 학습 / 테스트 데이터로 분류하는 StratifiedKFold를 사용하기 때문이다. 또한, 함수를 제작하는 데에 많은 코드가 필요했던 KFold보다 cross_val_score 메서드를 이용하면 상대적으로 간단하게 교차 검증을 수행할 수 있다.
하이퍼 파라미터 튜닝 (GridSearchCV)
마지막으로 하이퍼 파라미터 마지막으로 하이퍼 파라미터 튜닝을 진행다. 'max_depth', 'min_samples_split', 'min_samples_leaf' 하이퍼 파라미터를 GridSearchCV를 통해서 최적의 파라미터를 찾는다.
from sklearn.model_selection import GridSearchCV
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(X_train, y_train)
print('GridSearchCV 최적 하이퍼 파라미터 : ', grid_dclf.best_params_)
print('GridSerachCV 최고 정확도 : {0:.4f}'.format(grid_dclf.best_score_))
best_dclf = grid_dclf.best_estimator_
#GridSearchCV의 최적 하이퍼 파라미터로 학습된 Estimator로 예측 및 평가 수행
dpredictions = best_dclf.predict(X_test)
accuracy = accuracy_score(y_test, dpredictions)
print('테스트 세트에서의 DecisionTreeClassifier 정확도 : {0:.4f}'.format(accuracy))
'max_depth'는 3, 'min_samples_leaf'는 1, 'min_samples_split'은 2일때 가장 정확도가 높다는 것을 확인할 수 있다. 이때의 정확도는 79.97%였고, 테스트 세트에서는 87.15%인 것을 확인할 수 있다. 이전에 약 78%였던 것을 감안하면 거의 10%가 올랐다. 이렇게 성능이 향상되는 것이 일반적인 경우는 아니지만, 데이터의 수가 적어서 예측 성능이 많이 증가한 것으로 추정된다.
'기계학습 > Kaggle' 카테고리의 다른 글
Kaggle (UCI) : Human Activity(파이썬 머신러닝 완벽 가이드) - 데이터 전처리, 결정트리 (2) | 2020.09.06 |
---|---|
Kaggle : Pima Indians Diabetes[파이썬 머신러닝 완벽 가이드] - 피처 스케일링, 평가 지표 (0) | 2020.09.01 |
Kaggle : Titanic [ 파이썬 머신러닝 완벽 가이드 ] - 1 (0) | 2020.08.26 |
최근댓글