Be Brave, Be Humble

빅데이터 분석기사 실기 Part5. 파이썬으로 초보 분석가 탈출하기_2 (프리렉) 본문

Statistics/Data Science

빅데이터 분석기사 실기 Part5. 파이썬으로 초보 분석가 탈출하기_2 (프리렉)

해쨔니 2022. 10. 25. 17:33

Open in Colab 누르면 코랩으로 이동 가능

 

ㅎㅎ.. 4회차 때 시험 준비하며 이미 전부 작성한 코드라 코랩으로 다시 옮겨 정리하기는 귀찮네요

복붙하셔서 스파이더로 보시면 나름 가독성 있어요..ㅎㅎ

In [ ]:

 

# -*- coding: utf-8 -*-
"""
Created on Thu Jun 23 00:59:02 2022

@author: FullSun

"""

###############################################
###   Part5. 파이썬으로 초보 분석가 탈출하기   ###
###############################################

#---------------------------------------------
#             2. 분류 모델 수행하기
#---------------------------------------------

#--------- <2-1> 데이터 탐색하기 ---------#

## 데이터 가져오기
import pandas as pd
X_train = pd.read_csv('C:/Users/titanic_x_train.csv', encoding='cp949')
X_test = pd.read_csv('C:/Users/titanic_x_test.csv', encoding='cp949')
y_train = pd.read_csv('C:/Users/titanic_y_train.csv', encoding='cp949')
print(X_train.describe()) # 운임요금 이상값
print(X_test.describe()) # 운임요금 이상값
print(X_train.head(1).T)

## 행/열 확인하기
print(X_train.shape, X_test.shape, y_train.shape,)

## 요약정보 확인하기
print(X_train.info())
# obj: 승객이름, 성별, 티켓번호, 객실번호, 선착장 
# NA: 나이, 객실번호, 선착장 
# 범주형 변수의 중복 제거한 값과 개수 확인
print(X_train['성별'].unique())
print(X_train['선착장'].unique())
print(X_train.groupby(['성별'])['성별'].count())
print(X_train.groupby(['선착장'])['선착장'].count())
print(X_train['승객이름'].unique().size)
print(X_train['티켓번호'].unique().size)
print(X_train['객실번호'].unique().size)
# 승객이름, 티켓번호, 객실번호는 수백개를 가지고 있음

## 기초통계량 확인하기
print(X_train.describe().T)

## 독립변수와 종속변수의 관계 확인하기
''' ** 독립변수와 종속변수의 관계를 파악하여, 생존여부를 가르는 중요한
    독립벼수의 영향도와 추세 파악 '''
# X_train, y_train을 통합
data = pd.concat([X_train, y_train], axis=1)
# '성별'에 따른 생존여부 평균 계산
print(data.groupby(['성별'])['Survived'].mean())
''' female: 0.74, male: 0.18 => 여자의 생존률이 더 높음 '''
# '티켓등급'에 따른 생존여부 평균 계산
print(data.groupby(['티켓등급'])['Survived'].mean())
''' 1등급의 생존률이 가장 높음 '''
# 선착장에 따른 생존여부 평균 계산
print(data.groupby(['선착장'])['Survived'].mean())
''' C 선착장이 제일 높음 '''

''' ** 이러한 결과를 통해 성벌/티켓등급/선착장은 survived와 연관있으므로
        분석에 꼭 포함시켜야 한다 ** '''



#--------- <2-2> 전처리 하기 ---------#

## 불필요한 칼럼 삭제하기
# 1) PassengerID 따로 빼기
X_test_ID = X_test['PassengerId']
X_test = X_test.drop(columns = 'PassengerId')
X_train = X_train.drop(columns = 'PassengerId')
y_train = y_train.drop(columns = '癤풮assengerId')
## 2) 티켓번호, 승객이름 삭제하기
''' 티켓번호와 승객이름은 범주값이 전체 데이터 대비 50% 이상임
    의미없는 변수 '''
X_train = X_train.drop(columns = '티켓번호')
X_test = X_test.drop(columns = '티켓번호')
X_train = X_train.drop(columns = '승객이름')
X_test = X_test.drop(columns = '승객이름')

## 결측치 처리하기
# 1) null값 세기
print(X_train.isnull().sum()) 

# 2) 나이
print(data[['나이','Survived']].corr()) # -0.077221 => 매우 낮으므로 분석 제외
X_train = X_train.drop(columns = '나이')
X_test = X_test.drop(columns = '나이')

# 3) 객실번호 
print(X_train['객실번호'].unique().size) # 148
print(X_train['객실번호'].isnull().sum()) # 678
# 결측치 처리가 어려운 변수이므로 삭제
X_train = X_train.drop(columns = '객실번호')
X_test = X_test.drop(columns = '객실번호')

# 4) 선착장
print(X_train['선착장'].isnull().sum()) # 2건
# 두 건 밖에 없으니 가장 많은 비율 차지하는 값으로 적용하기
print(X_train.groupby(['선착장'])['선착장'].count()) # S가 가장 많음
X_train['선착장'] = X_train['선착장'].fillna('S')
print(X_train.isnull().sum()) # 확인
print(X_test.isnull().sum()) # 운임요금 결측치 한개는..?

X_train_backup = X_train.copy()
X_test_backup = X_test.copy()

## 범주형 변수를 인코딩 하기
# 성별 원핫인코딩
from pandas import get_dummies
X_train['성별'] = pd.get_dummies(X_train['성별'], drop_first=True).rename(columns={'male':'성별'})

# male=1, female=0
# 선착장 원핫인코딩
선착장_dummy = pd.get_dummies(X_train['선착장'], drop_first = True).rename(columns={'Q':'선착장Q', 'S':'선착장S'})
X_train_cate = pd.concat([X_train['성별'], 선착장_dummy], axis=1)
X_train = X_train.drop(columns = ['성별', '선착장'])

X_test = pd.get_dummies(X_test, drop_first=True).rename(columns = {'성별_male':'성별', '선착장_Q':'선착장Q', '선착장_S':'선착장S'})
X_test_cate = X_test[['성별', '선착장Q', '선착장S']]
X_test = X_test.drop(columns = ['성별', '선착장Q', '선착장S'])

## 파생변수 만들기
# '형제재매배우자수'와 '부모자식수' 칼럼을 더하여 '가족수'
print(X_train[['형제자매배우자수','부모자식수']])
print(X_train['형제자매배우자수']+X_train['부모자식수'])
X_train['가족수'] = X_train['형제자매배우자수'] + X_train['부모자식수']
X_train = X_train.drop(columns = ['형제자매배우자수', '부모자식수'])

X_test['가족수'] = X_test['형제자매배우자수'] + X_test['부모자식수']
X_test = X_test.drop(columns = ['형제자매배우자수', '부모자식수'])
X_train_backup = X_train.copy()
X_test_backup = X_test.copy()

## 스케일링
# => 이 예제에선 스케일링을 안 함..
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_train_sc = pd.DataFrame(scaler.fit_transform(X_train), columns=X_train.columns)
X_test_sc = pd.DataFrame(scaler.transform(X_test), columns = X_test.columns)

# 최종 전처리
# 1) 스케일링 버전
X_train_sc = pd.concat([X_train_sc, X_train_cate], axis=1)
X_test_sc = pd.concat([X_test_sc, X_test_cate], axis=1)
# 2) 스케일링X 버전
X_train = pd.concat([X_train, X_train_cate], axis=1)
X_test = pd.concat([X_test, X_test_cate], axis=1)


#--------- <2-3> 학습하고 평가하기 ---------#

## 데이터 분리하기
from sklearn.model_selection import train_test_split
X_train1, X_val1, y_train1, y_val1 = train_test_split(X_train, y_train,
                                                      test_size=0.2, random_state=66)
X_train2, X_val2, y_train2, y_val2 = train_test_split(X_train_sc, y_train,
                                                      test_size=0.2, random_state=66)

print(X_train1.shape, X_val1.shape, y_train1.shape, y_val1.shape)

## 데이터 학습 및 파라미터 튜닝하기
''' 일반적으로 성능이 가장 잘 나오는 XGBoost 사용할 것 '''
# xgboost 라이브러리에서 제공하는 XGBClassifier 함수 가져오기
from xgboost import XGBClassifier
## [1st] default 모델 생성
model1 = XGBClassifier(eval_metric = 'error', random_state=66)
# eval_metric='error' << default
model1.fit(X_train1, y_train1)

model1_2 = XGBClassifier(eval_metric = 'error', random_state=66)
model1_2.fit(X_train2, y_train2)

## [2nd] 하이퍼 파라미터 조정
model2 = XGBClassifier(n_estimators=100, max_depth=5, 
                       eval_metric='error', random_state=10)
model2.fit(X_train1, y_train1)

model2_1 = XGBClassifier(n_estimators=100, max_depth=5,
                         eval_metric='error', random_state=10)
model2_1.fit(X_train2, y_train2)


## 결과 예측하기
y_val_predicted1 = pd.DataFrame(model1.predict(X_val1)).rename(columns = {0:'Survived'}) # 디폴트, 디폴트
y_val_predicted2 = pd.DataFrame(model1_2.predict(X_val2)).rename(columns = {0:'Survived'}) # 디폴트, 스케일링
y_val_predicted3 = pd.DataFrame(model2.predict(X_val1)).rename(columns = {0:'Survived'}) # 튜닝, 디폴트
y_val_predicted4 = pd.DataFrame(model2_1.predict(X_val2)).rename(columns = {0:'Survived'}) # 튜닝, 튜닝

## 모델 평가하기
from sklearn.metrics import roc_auc_score
print(roc_auc_score(y_val1, y_val_predicted1)) # 0.7779
print(roc_auc_score(y_val1, y_val_predicted2)) # 0.7779
print(roc_auc_score(y_val1, y_val_predicted3)) # 0.7822
print(roc_auc_score(y_val1, y_val_predicted4)) # 0.7822
''' 결과적으로 스케일링 여부는 영향을 주지 않았으며 튜닝한 모델의 성능이 조금 더 높음
    (아마 변수간 단위가 크게 다르지 않아서 그런 것으로 보임)           '''

## 최종 모델
y_test_predicted = pd.DataFrame(model2.predict(X_test)).rename(columns = {0:'Survived'})
final = pd.concat([X_test_ID, y_test_predicted], axis=1)
final.to_csv('C:/Users/titanic_fin.csv', index=False)
final = pd.read_csv('C:/Users/titanic_fin.csv')
final



#---------------------------------------------
#                최종 제출 코드
#---------------------------------------------

# 데이터 가져오기
import pandas as pd
X_train = pd.read_csv('C:/Users/titanic_x_train.csv', encoding='cp949')
X_test = pd.read_csv('C:/Users/titanic_x_test.csv', encoding='cp949')
y_train = pd.read_csv('C:/Users/titanic_y_train.csv', encoding='cp949')

# 전처리 하기
X_test_ID = X_test['PassengerId']
X_test = X_test.drop(columns = 'PassengerId')
X_train = X_train.drop(columns = 'PassengerId')
y_train = y_train.drop(columns = '癤풮assengerId')
X_train = X_train.drop(columns = ['티켓번호', '나이', '승객이름', '객실번호'])
X_test = X_test.drop(columns = ['티켓번호', '나이', '승객이름', '객실번호'])

# 결측치 처리하기
print(X_train.isnull().sum())
print(X_train.groupby(['선착장'])['선착장'].count())
X_train['선착장'] = X_train['선착장'].fillna('S')
X_test['선착장'] = X_test['선착장'].fillna('S')

# 인코딩 수행하기
from pandas import get_dummies
X_train = pd.get_dummies(X_train, drop_first = True)
X_test = pd.get_dummies(X_test, drop_first = True)

# 파생변수 만들기
X_train['가족수'] = X_train['형제자매배우자수'] + X_train['부모자식수']
X_test['가족수'] = X_test['형제자매배우자수'] + X_test['부모자식수']
X_train = X_train.drop(columns = ['형제자매배우자수', '부모자식수'])
X_test =  X_test.drop(columns = ['형제자매배우자수', '부모자식수'])

# 데이터 분리하기
from sklearn.model_selection import train_test_split
X_train1, X_val1, y_train1, y_val1 = train_test_split(X_train, y_train,
                                                      test_size=0.2, random_state=56)

# 모델 학습하기
from xgboost import XGBClassifier
model = XGBClassifier(n_estimators=100, max_depth=5,
                      eval_metric='error', random_state=56)
model.fit(X_train1, y_train1)

y_val_predicted = model.predict(X_val1)

# 모델 평가하기
from sklearn.metrics import roc_auc_score
print(roc_auc_score(y_val1, y_val_predicted))

# 최종 모델 적합하기
y_test_predicted = pd.DataFrame(model.predict(X_test)).rename(columns = {0:'Survived'})
final = pd.concat([X_test_ID, y_test_predicted], axis=1)
final.to_csv('C:/Users/titanic_fin2.csv', index=False)
final = pd.read_csv('C:/Users/titanic_fin2.csv')
print(final)
Comments