세로형
Recent Posts
Recent Comments
Link
04-20 00:01
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
Archives
Today
Total
관리 메뉴

꿈 많은 사람의 이야기

[1주차] 새벽 5시 캐글(kaggle) 필사하기 - 타이타닉(titanic) 편 본문

kaggle(캐글)

[1주차] 새벽 5시 캐글(kaggle) 필사하기 - 타이타닉(titanic) 편

이수진의 블로그 2019. 1. 12. 10:25

새해 첫 목표를 두고 있는 새벽 5시 캐글 필사 편 1주차 내용이다.

사실 원래 다른 데이터로 진행하려고 했는데 어쩌다 보니 타이타닉으로 넘어왔다.

머신러닝 탐구생활이라는 책으로 시작하려고 했지만 쉽지 않았기 때문이다. 또한, 데이터 분석을 한동안 안했더니 감을 잃은 것도 컸다.

그리고 마침 페이스북 그룹인 캐글 코리아(kaggle korea)에서 대회를 타이타닉을 주제로 하고 있기에 타이타닉으로 진행했다. 이 과정에서 1주일이 날라갔다 ㅠ

그래서 타이타닉 편으로 시작!

이 필사는 다양한 커널을 참조했다. 타이타닉 커널을 보면 open되어 있는 커널 중 인기 많은 커널 2개와 약간의 내 아이디어? 를 짬뽕시켜서 진행했다.

많이 참조한 대표적인 커널은 https://www.kaggle.com/ash316/eda-to-prediction-dietanic 이다.




대망의 스타트이다. 역시 처음에는 numpy, pandas 등의 라이브러리를 불러오고 시작한다.

그리고 head를 통해 간단히 데이터를 볼 수 있다.

승객 번호, 생존 여부, class 등급, 이름, 성별, 나이, (가족 등) 동승 숫자, 가격 등의 정보가 담겨 있다.



데이터를 더 보면 null 값이 있는지(결측값) 확인한다.

isnull.sum()을 확인하면 null의 개수를 확인할 수 있다.

 

이제 먼저 데이터에 대해서 분석을 해보자.

우리는 '살아남은 것'에 대해 초점이 맞추어져 있다. 그래서 생존을 기준으로 데이터를 쭉 분석한다



그냥 survived 컬럼을 가지고 분석을 해봤다.

pandas에서 plot.pie로 이용해 바로 파이차트를 그릴 수 있다. 아니면 seaborn countplot을 이용하거나.

생존하지 못한 사람이 더 많은 것을 볼 수 있다.



그럼 성별로 생존 여부는 어떻게 될까?

groupby를 통해 확인이 가능하다

성별과 survived를 엮어서 group을 해준다.



여기서 확실히 볼 수 있다.

여성이 더 많이 살아남았다. 이때 당시에는 ladies first가 있었기 때문에 그럴 것이라는 추측이 많다~



 

다음은 탑승한 클래스를 기준으로 봐보자.

pandas에는 crosstab이라는 것이 있다. 이거는 말 그대로 크로스를 해서 보여주는 것인데, (x, y)를 통해서 크로스할 컬럼을 넣어준다.

그럼 위와 같이 나오게 된다



data['pclass'].value_counts()를 통해서 각 클래스 별로 몇 명이 탑승했는지 볼 수 있다.

3번 클래스가 많이 있다.

아마 이게 3등석? 이런 것일 것이다. 1등석보다 3등석이 많았다.

그리고 생존을 보니까 1등석 사람들은 사망한 사람보다 살아남은 사람이 더 많았다. 반면 3등석은 살아남은 숫자가 적다



그리고 pandas crosstab을 이용해서 성별과 살아남은 것을 묶고, y 축으로 Pclass를 두어서 분석해본다.

그렇게 하면 하나의 표에 3개의 지표로 볼 수 있다. 성별, 클래스, 생존여부.

seaborn factorplot은 이럴 때 사용하기 좋다. sns.factorclass('Pclass', 'Survived', hue='구분값') 이런식으로 처리한다.

클래스 여부와 상관없이 여성이 다 많이 살아남았다. 그러나 3등급에서는 살아남은 여성의 수가 1,2 등급보다 적다



연령 별로 분석도 해보자.

다양한 연령이 있다. 이건 연속적인 값이기 때문에 그래프에서 yticks xticks를 이용하면 좋다

seaborn violinplot을 이용하면 쉽게 표현이 가능하다. 아니면 distplot도 사용하면 좋다

sns.violinplot("Pclass", "Age", hue="survived", data=data, split=True)등으로 셋팅을 하고 yticks에다가 range 값을 넣어주면 이쁘게 표현된다.



다음은 이름인데 이름에서 Mr, Mrs, Miss 등의 호칭이 있다. 이것들만 빼낸다.

빼내는 이유는 뒤에서 설명한다



근데 저렇게 상당히 다양한 것들이 있다.

만약 test 셋까지 포함시키면 Don말고 Dona도 있다.



이러한 데이터를 좀 뭉쳐준다. Miss, Mrs 5개로 합쳐준다.



합치고 나서 이니셜 정보를 보면 Mr, Miss, Mrs, Master, Other 5개가 있다. 그리고 여기서 왜 얘내 들을 뽑아냈냐면 아까 null값을 확인할 때 agenull이 상당히 많았다. 그냥 일반적으로 null값을 나이 평균값으로 내기에는 어린 사람은 0, 많은 사람은 80살 까지 있기 때문에 뭔가 부족하다. 그래서 이 Mr, Miss 등의 평균값을 이용하는 것이다.

Data.groupby를 이용해서 [‘Age’].mean()을 뽑아내면 저렇게 나온다.



이후 data.loc[(data[‘Age’].isnull()) & (data[‘Initial’]==’Mr’, ‘Age’) == 33 이런 식의 식을 통해서 나이를 채워준다.

다 진행되면 data[‘Age’].isnull().sum()을 보면 0이 나올 것이다.



그리고 plt.subplots으로 그래프를 그릴 영역을 나타내주고 살아남은 사람과, 살아남지 못한 사람을 연령대별로 시각화해준다.

Data[data[‘Survived’] ==0][‘Age’].plot.hist(ax=ax[0], bins=20, edgecolor=’’, color=’’ ) 쭉쭉 진행해준다.

이렇게 판다스에서 바로 그래프를 그릴 수 있는게 너무 편한 것 같다.



그리고 pandascrosstab에서 x, y 값에 1개만 넣을 수 있는 것이 아니라 배열을 통해 복수 개의 컬럼을 넣을 수 있다. 그러면 복수개로 엮어서 보여준다!



그리고 이건 factorplot으로 Embarked Survived를 보았다. C가 많이 살아남았다.



그리고 countplot을 이용하여 더 자세히 보면, EmbarkedPclass, 성별, Survived를 비교해보자. S에서 많은 사람들이 탑승했다. 그리고 각 탑승 항구마다 성별도 보인다.



S 탑승객이 많은 만큼 사망자도 많다. 또한 S에서는 1등급과 3등급 사람들이 많다. 그리고 2등급 승객의 대부분이 S에서 왔다



다시 factorplot으로 Embarkedcol값으로 주고 xPclass, ysurvived를 줘서 보면 역시나 여성들이 많이 살아남았고 S에서 여성들은 많이 살아남지 못했다.



그리고 EmbarkedNaN이 몇 개가 있는데 대부분의 탑승객이 S에서 왔기 때문에 여기도 S로 채워준다



이제 다음 컬럼인 SibSp를 확인한다(오타네요 사진은 ㅠ). 형재 자매, 배우자 수 총합이다.

이후에 나오는 Parch는 부모, 자녀수의 총합이다. 좀 헷갈린다 ㅠ

아무튼 SibSp를 기준으로 먼저 분석을 해본다. 먼저 crosstab을 이용해서 간단히 확인한다.

혼자인 사람은 0, 1은 형재 자매, 배우자 수 1, 22명 이렇게 된다.



그래프로 보면 좀 더 명확하게 보인다.

sns.barplot(‘SibSp’, ‘Survived’, data =data, ax=ax[0])을 이용해서 확인을 한다. 라인 그래프로 보고 싶으시면 factorplot(‘SibSp’, ‘Survived’)를 통해 확인!

그래프를 보니까 0(혼자)보다 1, 2명일 때 생존이 더 높다. 뒤로 갈수록 줄어든다.



이번에는 Pclass 별로 SibSp를 보자. 어떤 pclass에 따라서 SibSp 숫자를 확인할 수 있다.



다음은 Parch. 부모, 자녀 수를 나타낸다. 마찬가지로 역시 crosstab을 통해서 먼저 확인한다. 부모, 자녀와 함께 오지 않은 숫자가 더 많다!



그리고 Pclass에 따라서도 확인할 수 있다.



그래프로 좀 더 명확하게 봐 보자. sns.barplot(‘Parch’, ‘Survived’, data=data)를 통해서 barplot으로 본다. 0명보다 1~3명일 때가 더 생존 확률이 높다



다음은 Fare 속성을 봐 본다. 이거는 가격표다~ 비싼 건 512, 제일 낮은 가격은 0(이건 뭐지..)이다. 그리고 평균은 32. 평균에 비해서 5120은 좀 이상하게 느껴진다? 이런 것들이 이상치(outlier) 데이터라고 하는데, 일단 (제가.. 이상치 처리 방법을 잘 몰라서 ㅠ) 그냥 진행한다. 원래 이런 것들은 처리하는 것이 좋다.



여기서는 distplot으로 확인해본다. 아까는 violinplot으로 진행했지만 이렇게 distplot을 이용하여도 된다. Seaborn.displot(data[data[‘Plcass’] == 1][‘Fare’]) 이런 식으로 뽑아낸다. 저렇게 하면 조건에 따라 뽑아지기 때문! 이렇게 3개를 만들어 각 영역에 넣어준다. 그러면 Pclass 별 특징을 파악할 수 있다. Pclass12번째 작은 숫자가 100이 나오고, pclass2는 커봐야 80, 3도 커봐야 70정도이다. 가격 차이가 꽤 났던 것을 볼 수 있다.



이제 특성들의 특징은 꽤나 파악했다. 이제 이러한 특징 별로 correration을 확인할 수 있다. Pandascorr을 통해 연관이 있는 특성을 파악할 수 있다. 1에 가까울수록 양의 연관, -1에 가까울 수록 음의 연관을 띈다. 여기서 보니까 survivedFare가 연관이 좀 있다는 것을 볼 수 있다. 그리고 ParchSibSp가 연관성이 있는 것을 확인할 수 있다.

sns.heatmap(data.drop(‘PassengerId’, axis=1).corr(), annot=True)와 같이 만들 수 있다. Seabornheatmap을 사용하면 간단히 만들어준다



! 이제 기본적인 데이터 분석은 끝났다. del을 이용해 기존에 사용 중이던 data는 메모리에서 지운다. 그리고 traintest를 키워드로 데이터를 다시 읽어드린다.

그리고 train_test 배열에 traintest를 넣는다! 왜 이렇게 넣냐면 이제 데이터 전처리와 특성 공학을 진행할 것이다. 근데 train만 진행하면 안된다. Test도 진행되어 있어야 나중에 predict 등을 수행할 수 있기 때문이다. . Test 데이터의 전처리는 train 전처리를 기준으로 간다. 만약, train 데이터 따로, test 데이터 따로 전처리를 진행하면 이건 옳지 못하다. Train 데이터 셋을 기준으로 전처리를 진행한다.

그래서 초반에 진행했던 이름의 이니셜(initial)을 따오는 작업을 먼저 진행했다. 앞서 진행한 방법과 다르다. 저건 나만의 방식이고 위에꺼는 단순히 필사했던 부분이다.



train.head()로 확인하니까 Initial이 생긴 것을 확인할 수 있다. 이제 이거를 replace 해준다.



그리고 다시 각 initial별로 age 빈 값을 넣어준다. Masterage = 5 이렇게 말이다.



다음으로 initial을 숫자로 바꿔준다. 지금 Master, Mr, Miss 이렇게 되어 있는데 이것을 그대로 훈련값으로 넣으면 인식을 하지 못한다. 그래서 숫자로 바꿔준다. mapping이라는 dict을 생성해서 키워드를 넣어주고 pandas 데이터를 돌면서 data[‘Initial’].map(mapping).astype(int) 로 진행한다



그리고 성별도 마찬가지로 진행하고, Embarkednull 값이 포함되어 있다. 대부분 S가 많으니 S로 채워준다.



Embarked도 마찬가지로 mapping을 진행한다. 그 다음은 나이인데, 나이는 연속적인 값을 갖는다. 그래서 범위를 지정해서 categorical로 바꿔주어야 한다. 해당 커널은 16세 이하는 0, 16~321, 32~482 이런 식으로 category를 나눠주었다



! 그리고 잘 되었는지 확인하는 간단한 방법은 pandasunique()를 사용해서 고유 값들을 뽑아 내보자



또한 Fare에도 확인해보니 null값이 존재한다. 이거는 1개 뿐이니 그냥 median 값을 넣어준다!

그리고 Fare의 범위를 4단계로 추출해본다. 그러면 0~7.91, 7.91~14.454 이런 식으로 범위가 나눠진 것을 볼 수 있다. 이거를 FareBand 컬럼에 일단 넣어둔다.



그리고 이 Fare를 앞에서 본 범위 지정대로 categorical로 나눠준다. Unique를 확인해보니까 0~3까지 나온다.



다음은 family 컬럼을 추가해서 가족 구성원 컬럼을 만들어버린다. 왜냐하면 SibSpParch는 가족과 연관이 많기 때문에 이것들을 한데 묶어놓는 것이다.

그리고 train[[‘family’, ‘Suvived’]].groupby(‘Family’).mean()을 통해 확인하면 숫자 별 생존자 추이를 볼 수 있다



그리고 이 Family도 범위에 따라 categorical로 만들어준다! 그리고 나서 다시 groupby를 통해 보면 확실히 그룹별 생존 확률이 나뉘어지는 것을 볼 수 있다.



! 이제 데이터 전처리와 feature engineering이 어느정도 마무리 되었다. 이제 불필요한 컬럼을 지우자. Name, sibsp, parch, ticket, cabin은 일단 train, test 둘다 공통으로 필요없다. 지운다.

그리고 train에선 passengeridfareband는 필요 없기 때문에 마찬가지로 지운다.

그러면 최종적으로 train에서는 survived, pclass, sex, age, fare, embarked, initial, family가 남는다.



이제 데이터를 분류하고 진짜 머신러닝 모델을 만들어보자! X_train에는 survived가 빠진 값을 넣고 y_train에는 survived값을 넣는다



이제 필요한 모델 라이브러리를 load한다. Sklearn은 파이썬의 대표적인 머신러닝 라이브러리이며 로지스틱 회귀(logistic regression), 서포트 벡터 머신(SVM, SVC), KNN, 의사결정트리(decision tree), 랜덤포레스트(random forest), 기타 앙상블 모델(gradient boosting model, Ada boost model )이 있다


먼저 로지스틱 회귀를 사용해보자. 로지스틱 회귀는 딥러닝에서도 많이 사용되는 대표적인 알고리즘이다. clf = LogisticRegression()을 이용해서 로지스틱회귀 클래스를 만든다. 그리고 그 안에 있는 fit 메소드를 이용해서 나의 x_trainy_train값을 넣는다. Predict 값을 뽑아내려면 predict를 사용하면 되고 점수를 뽑아내고 싶으면 score를 통해서 뽑아낸다.

그리고 참고로 말하면 이렇게 훈련 시키면 안된다! 2주차 때 설명하겠지만 이렇게 훈련 시키면 100% 500% 오버피팅 걸린다.

어찌되었든 여기서 train 값으로 score를 뽑아내니 82% 나온다



다음은 서포트 벡터 머신인 SVC를 이용해보자. 똑같이 fit 메소드가 있어서 x_train, y_train값을 넣으면 된다. 여기선 83%가 나온다.



그리고 트리 구조를 이용해보자. DecisionTreeClassifier는 의사결정트리이다. 마찬가지로 fit 메소드가 있고 점수를 뽑아낼 땐 score를 이용한다. 87%가 나왔다!

randomForestClassifier는 랜덤포레스트이다. 여기서도 87%가 나왔다!


와 뭔가 정확도가 높게 나왔다. 이제 캐글에 제출해볼까?? 제출 방법은 다음과 같다.



commit을 한다



그리고 커널을 빠져나와서 여기 data를 보면 내가 제출한 submission.csv 파일이 보일 것이다.

그걸 제출하기 버튼을 눌러서 제출하면 된다! 아니면 그 csv 파일을 다운을 받아서 직접 submission 탭에 가서 직접 제출해도 된다



이렇게 진행하니까 78%가 나왔다. 확실한 오버피팅ㅋㅋㅋㅋㅋㅋㅋ




그리고 점수 확인! ㅋㅋㅋㅋㅋㅋㅋㅋㅋ 처참하다. 73등이다. 무려 top71%다. 처음 했을 때 71% 보고 숫자가 높아서 좋아했는데 다음날 보니까 그게 아니었닼ㅋㅋㅋ 크흠..


다음주 새벽 5시 캐글 커널 필사 타이타닉 편 2번째에서는 이 정확도를 좀 더 높여보겠다.

반응형
그리드형
Comments