제2회 빅데이터 분석기사(실기) - 작업형:제2유형-종합
작성자 정보
- ◆딥셀◆ 작성
- 작성일
컨텐츠 정보
- 20,328 조회
- 5 댓글
본문
제2유형에 대한 교과서적인 종합 답안을 만들어 보았습니다. 특성추줄과 오버 샘플링, 초매개변수 최적화는 생략하였습니다. 예제의 경우 이러한 작업을 하여도 스코어에 큰 변화가 없습니다. 그리고 범주형 데이터 인코딩은 선형 모델과 결정나무 계열의 모델 모두 원핫 인코딩하였습니다. 결정나무 계열의 경우 라벨인코딩으로 할 수도 있으나 결과 차이가 별로 없으므로 단순하게 한 가지로 처리하였습니다. 스케일변환도 수치형데이터와 인코딩된 범주형 데이터를 동일하게 처라하였습니다.
아래의 코드는 전체 수행 코드를 모두 포함하며 시험에서는 부분적으로 실행을 하고 중간 결과를 확인하고 모델을 선택하면 됩니다.
시험 준비로 아래 코드를 외워서 쓸 수 있도록 반복 연습을 하면 유사 문제가 나올 경우 많은 도움이 될 것 같습니다.
# 1. 준비
import os
from time import time
import numpy as np
import pandas as pd
from pandas import read_csv, set_option
from sklearn.model_selection import cross_val_score, train_test_split, RepeatedStratifiedKFold #, KFold
from sklearn.model_selection import GridSearchCV, RandomizedSearchCV
from sklearn.preprocessing import MinMaxScaler, RobustScaler, StandardScaler
from sklearn.pipeline import Pipeline
# model
# linear
from sklearn.linear_model import LogisticRegression
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
# non-linear
from sklearn.naive_bayes import GaussianNB
from sklearn.neighbors import KNeighborsClassifier
from sklearn.svm import SVC
from sklearn.tree import DecisionTreeClassifier
# ensemble
from sklearn.ensemble import AdaBoostClassifier
from sklearn.ensemble import ExtraTreesClassifier
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.ensemble import RandomForestClassifier
# Neural lNetwork
from sklearn.neural_network import MLPClassifier
# XGBoost
from xgboost import XGBClassifier
# metric
from sklearn.metrics import accuracy_score, roc_auc_score
# utils
from sklearn.utils import resample, shuffle # imbalanced data를 up/down sampling할 때 사용
# b) 데이터 로드
data_dir = 'data'
X_train_file = os.path.join(data_dir, 'X_train.csv')
y_train_file = os.path.join(data_dir, 'y_train.csv')
X_test_file = os.path.join(data_dir, 'X_test.csv')
X_train_df = read_csv(X_train_file)
y_train_df = read_csv(y_train_file)
X_test_df = read_csv(X_test_file)
# 2. 데이터 분석(시각화는 생략)
# 기술 통계(descriptive statistics)
print(X_train_df.shape)
print(X_train_df.info())
print(X_train_df.describe())
print(y_train_df.groupby('gender').size())
print(X_test_df.info())
print(X_test_df.describe())
# 3 제출 파일 만들기 : 시험을 위한 코드(필수 암기)
exam_num = '0000'
submit_file = exam_num + '.csv'
col_1_name = 'cust_id'
col_2_name = 'gender'
default_value = 0.5 # 임의의 값을 대입하여 출력하는 경우 0점이라고 합니다.
col_1 = X_test_df.cust_id
test_row_num = len(X_test_df)
col_2 = np.full(test_row_num, default_value)
submit = pd.DataFrame({col_1_name:col_1, col_2_name:col_2})
submit.to_csv(submit_file, index=False)
# 4. 데이터 준비
# a) 데이터 정제 :
# - 결측데이터 처리(환불금액이 없는 데이터를 0으로 변경)
# - 이상데이터 제거(총구매액이 음수인 데이터를 제거 하려 하였으나
# 총구매액이 음수인 데이터가 테스트 데이터에도 있어서 그대로 트레이닝
train_df = pd.merge(X_train_df, y_train_df)
# train_df = train_df[train_df['총구매액']>=0]
train_df['환불금액'] = train_df['환불금액'].fillna(0)
X_test_df['환불금액'] = X_test_df['환불금액'].fillna(0)
X = train_df.drop(['cust_id', 'gender'], axis=1)
y = train_df.gender
X_test = X_test_df.drop(['cust_id'], axis=1)
# b) 데이터 변환
# - 범주형 데이터 인코딩(One-Hot Encoding) : 선형 모델의 경우 원핫 인코딩을 해야함, 결정나무 계열은 별 차이 없음
# - 스케일 변환(Standard or MinMax) : 스케일 변환은 데이터 분리와 관련이 있으므로 파이프라인과 함께 코딩
# 인코딩
X_encoded = pd.get_dummies(X)
X_test_encoded = pd.get_dummies(X_test)
lack_cols = set(X_encoded.columns) - set(X_test_encoded.columns)
remain_cols = set(X_test_encoded.columns) - set(X_encoded.columns)
print(lack_cols)
print(remain_cols)
# 부족한 컬럼은 0을 값으로 하는 컬럼으로 새로 만들기
for col in lack_cols:
X_test_encoded[col] = 0
# 남는 컬럼(테스트 데이터셋에만 있는 컬럼)은 제거
for col in remain_cols:
X_test_encoded.drop(col, axis=1)
# 약간의 오류가 있습니다. 컬럼의 순서가 달라지므로 컬럼의 순서를 동일하게 맞추어야 합니다.
### 준비된 데이터 : 인코딩
# 전체 트레이닝 데이터와 라벨 : X_encoded, y
# 전체 테스트 데이터 : X_test_encoded
# 5. 알고리즘 평가 : 성능이 좋은 알고리즘 찾기
# a) 테스트 옵션(변수) 설정
seed = 1 # random seed
num_fold = 5
num_repeat = 1
scoring = 'roc_auc'
cv = RepeatedStratifiedKFold(n_splits=num_fold, n_repeats=num_repeat, random_state=seed)
# b) 데이터 분리 : 트레이닝 데이터와 검증 데이터 분리
X_train, X_valid, y_train, y_valid = train_test_split(X_encoded, y, test_size=0.2, random_state=seed)
# 데이터를 표준 스케일 변환 후 트레이닝
start_time = time()
scaler = StandardScaler()
#scaler = MinMaxScaler()
pipelines = []
pipelines.append(('ScaledLR', Pipeline([('Scaler', scaler), ('LR', LogisticRegression(solver='liblinear'))])))
pipelines.append(('ScaledLDA', Pipeline([('Scaler', scaler), ('LDA', LinearDiscriminantAnalysis())])))
pipelines.append(('ScaledKNN', Pipeline([('Scaler', scaler), ('KNN', KNeighborsClassifier())])))
pipelines.append(('ScaledNB', Pipeline([('Scaler', scaler), ('NB', GaussianNB())])))
pipelines.append(('ScaledSVM', Pipeline([('Scaler', scaler),('SVM', SVC(gamma='auto'))])))
# pipelines.append(('ScaledSVM', Pipeline([('Scaler', scaler),('SVM', SVC(gamma='auto', class_weight='balanced', probability=True))])))
pipelines.append(('CART', Pipeline([('CART', DecisionTreeClassifier())])))
# ensemble
pipelines.append(('AB', Pipeline([('AB', AdaBoostClassifier())])))
pipelines.append(('GBM', Pipeline([('GBM', GradientBoostingClassifier())])))
pipelines.append(('RF', Pipeline([('RF', RandomForestClassifier())])))
pipelines.append(('ET', Pipeline([('ET', ExtraTreesClassifier())])))
results = []
names = []
for name, model in pipelines:
cv_results = cross_val_score(model, X_train, y_train, cv=cv, scoring=scoring)
# cv_results = cross_val_score(model, upsampled_X, upsampled_y, cv=cv, scoring=scoring)
# cv_results = cross_val_score(model, downsampled_X, downsampled_y, cv=cv, scoring=scoring)
results.append(cv_results)
names.append(name)
means = []
stds = []
for result in results:
means.append(result.mean())
stds.append(result.std())
results_df = pd.DataFrame({'mean': means, 'std': stds, 'name':names})
print('time : ', time()-start_time)
print(results_df.sort_values('mean', axis=0, ascending=False))
# 6. 최선의 모델 선택, 위 결과중 가장 성능이 좋은 모델을 선택하여 검증
# valid data로 검증
# best_model = AdaBoostClassifier()
# best_model = GradientBoostingClassifier()
best_model = Pipeline([('Scaler', scaler), ('LR', LogisticRegression(solver='liblinear'))])
# best_model = RandomForestClassifier(n_estimators=100)
# best_model = ExtraTreesClassifier(n_estimators=200)
# best_model = SVC(gamma='auto', probability=True)
# best_model = LinearDiscriminantAnalysis()
best_model.fit(X_train, y_train)
best_predict = best_model.predict_proba(X_valid)
best_score = roc_auc_score(y_valid, best_predict[:, 1] )
print('roc auc score : %f' %(best_score))
# 7. 전체 트레이닝 데이터를 이용하여 다시 트레이닝 및 예측
# 제출용 : 전체 trainind data로 트레이닝을 하고 예측
best_model.fit(X_encoded, y)
submit_predict = best_model.predict_proba(X_test_encoded)
# 8. 제출 파일 작성 및 제출
submit['gender'] = submit_predict[:, 1]
submit.to_csv(submit_file, index=False)
# 제출 전 파일 확인
submit_df = read_csv(submit_file)
print(submit_df.head(20))
관련자료
-
이전
-
다음
JACKIECHAN님의 댓글
- JACKIECHAN
- 작성일
2. 최대구매액도 음수가 나오면 안되는 피쳐이므로 처리를 해야하지 않나요?
올려주신 자료들 잘 보고 있습니다. 감사합니다!
◆딥셀◆님의 댓글
- ◆딥셀◆
- 작성일
감사합니다.
주석이 이상한 부분이 있어서 수정하였습니다.
JACKIECHAN님의 댓글
- JACKIECHAN
- 작성일
연속형 변수를 scaling 하고 범주형 변수들을 one hot encoding 하는게 자연스럽지 않나요??
◆딥셀◆님의 댓글의 댓글
- ◆딥셀◆
- 작성일
그리고 짧은 시험 시간에 쉽게 하기 위해 한번에 처리하였습니다.
사실 수치형과 범주형을 나누어서 따로 처리하고 합치고 하면 되는데 조금 더 번거롭고 시험볼 때는 가능한 한 단순한 것이 좋을 것 같아서 이렇게 해 보았습니다.(예제의 경우 결과 차이가 나지 않으므로)
JACKIECHAN님의 댓글의 댓글
- JACKIECHAN
- 작성일