데이터분석의 일환으로 캐글코리아 유한님의 캐글 커널 필사를 따라 공부하기 시작했습니다.

간혹 글귀가 정형화되지 않은 점 유의해주시기 바랍니다.

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

plt.style.use('seaborn')
sns.set(font_scale=2.5)
# 유한님 스타일, 일일히 graph의 font size를 지정할 필요없이 seaborn의 font_scale을 사용하면 편함.

import missingno as msno

import warnings
warnings.filterwarnings('ignore')

%matplotlib inline
from google.colab import drive
drive.mount('/gdrive')

앞으로 해나갈 프로세스

  1. 데이터셋 확인 - null data 확인
  2. 탐색적 데이터 분석(exploratory data analysis) - feature 들 간의 상관관계 확인
  3. feature engineering - one-hot encoding, class로 나누기, 구간으로 나누기, 텍스트 데이터 처리
  4. model 만들기 - sklearn
  5. 모델 학습 및 예측
  6. 모델 평가
df_train = pd.read_csv('/gdrive/My Drive/Colab Notebooks/Kaggle_필사/train.csv')
df_test = pd.read_csv('/gdrive/My Drive/Colab Notebooks/Kaggle_필사/test.csv')
df_train.head()
df_train.describe()
df_test.describe()

1.1Null Data check

for col in df_train.columns:
    msg = 'column: {:>10}\t Percent of NaN value: {:.2f}%'.format(col, 100 * (df_train[col].isnull().sum() / df_train[col].shape[0]))
    print(msg)
for col in df_test.columns:
  msg = 'column:{:>10}\t Percent of NaN value: {:2f}%'.format(col, 100*(df_test[col].isnull().sum() / df_test[col].shape[0]))
  print(msg)
  • train, test set에서 age(둘다 20%), cabin(둘다 약 80%), embarked(train만 0.22%) null data 존재

  • Mano 라는 라이브러리를 사용하면 null data의 존재를 더 쉽게 볼 수 있다.

msno.matrix(df=df_train.iloc[:,:], figsize=(8,8), color=(0.8,0.5,0.2))
msno.bar(df=df_train.iloc[:,:], figsize = (8,8), color=(0.8,0.5,0.2))
msno.bar(df=df_test.iloc[:,:], figsize = (8,8), color=(0.5,0.5,0.2))

1.2 target label 확인

  • target label이 어떤 distribution을 가지고 있는 지 확인 필요
  • 지금 같은 binary classification 문제의 경우에서 1과 0의 분포가 어떠나에 따라 모델의 평가 방법이 달라 질 수 있다.
f, ax = plt.subplots(1,2, figsize = (12,6))

df_train['Survived'].value_counts().plot.pie(explode=[0,0.1], autopct='%1.1f%%', ax=ax[0], shadow=True)
ax[0].set_title('Pie plot - Survived')
ax[0].set_ylabel('')
sns.countplot('Survived', data=df_train, ax=ax[1])
ax[1].set_title('Count plot - Survived')

plt.show()
  • 죽은 사람이 많음
  • 38.4%가 살아남음
  • target label의 분포가 균일함. 불균일할 경우, 예를 들어, 100중 1이 99, 0이 1개인 경우에는 만약 모델이 모든 것을 1이라 해도 정확도가 99%가 나오게 됨. 0을 찾는 문제라면 이 모델은 원하는 결과를 줄 수 없음. 지금 문제에서는 그렇지 않으니 계속 진행

2. Exploratory data analysis

  • 이제 본격적으로 데이터 분석 시작. 데이터는 매우 많다. 이 많은 데이터 안에 숨겨진 사실을 찾기 위해선 적절한 시각화 필요
  • 시각화 라이브러리는 matplotlib, seaborn, plotly 등이 있음. 특정 목적에 맞는 소스코드를 정리해두어 필요할 때마다 참고하면 편함

2.1 Pclass

  • Pclass는 ordinal, 서수형 데이터임. 카테고리이면서, 순서가 있는 데이터 타입
  • 먼저 Pclass에 따른 생존률의 차이를 살펴보겠음. 엑셀의 피벗차트와 유사한 작업을 하게 되는데, pandas dataframe에서는 groupby를 사용하면 쉽게 할 수 있음. 또한 pivot이라는 메소드도 있음
  • 'Pclass','Survived'를 가져온 후, pclass 로 묶습니다. 그러고 나면 각 pclass 마다 0,1이 count가 되는데, 이를 평균내면 각 pclass 별 생존률이 나옴
  • 아래와 같이 count()를 하면, 각 class에 몇명이 있는 지 확인할 수 있으며, sum()을 하면, 216명 중 생존한 사람(survived=1)의 총합을 주게됨

Survived의 생존자는 1의 값을 가지므로 총합은 곧 생존자의 합

df_train[['Pclass', 'Survived']].groupby(['Pclass'], as_index=True).count()
df_train[['Pclass','Survived']].groupby(['Pclass'], as_index=True).sum()
  • pandas의 crosstab을 사용하면 좀 더 위 과정을 수월하게 볼 수 있음
pd.crosstab(df_train['Pclass'], df_train['Survived'], margins=True).style.background_gradient(cmap='summer_r')
  • grouped 객체에 mean()을 하게 되면, 각 클래스별 생존율을 얻을 수 있음. class 1이면 아래와 같음

80/(80+136) = 0.63

df_train[['Pclass', 'Survived']].groupby(['Pclass'], as_index=True).mean().sort_values(by='Survived', ascending=False).plot.bar()
  • 보다시피, Pclass가 좋을수록 생존률이 높은 것을 확인
  • 좀더 보기 쉽게 그래프를 그려보겠다. seaborn의 countplot을 이용하면, 특정 label에 따른 개수를 확인해볼 수 있다.
y_position = 1.02
f, ax = plt.subplots(1,2,figsize=(12,6))
df_train['Pclass'].value_counts().plot.bar(color=['#CD7F32','#FFDF00','#D3D3D3'], ax=ax[0])
ax[0].set_title('Number of Passengers By Pclass', y=y_position)
ax[0].set_ylabel('Count')
sns.countplot('Pclass', hue='Survived',data=df_train, ax=ax[1])
ax[1].set_title('Pclass: Survived vs Dead', y=y_position)

plt.show()
  • 클래스가 높을 수록, 생존확률이 높은걸 확인할 수 있다. pclass 1,2,3 순서대로 63%, 48%, 25%
  • 우리는 생존에 pclass가 큰 영향을 미친다고 생각해볼수 있으며, 나중에 모델을 세울때 이 feature를 사용하는 것이 좋을 것이라 판단할 수 있음

2.2 Sex

  • 이번에는 성별로 생존률이 어떻게 달라지는 지 확인해보겠습니다.
  • 마찬가지로 pandas groupby와 seaborn countplot을 사용해서 시각화해봄
f, ax = plt.subplots(1,2,figsize=(18,8))
df_train[['Sex','Survived']].groupby(['Sex'], as_index=True).mean().plot.bar(ax=ax[0])
ax[0].set_title('Survived vs Sex')
sns.countplot('Sex',hue='Survived', data=df_train, ax=ax[1])
ax[1].set_title('Sex: Survived vs Dead')
plt.show()
df_train[['Sex', 'Survived']].groupby(['Sex'], as_index=False).mean().sort_values(by='Survived', ascending=False)
pd.crosstab(df_train['Sex'], df_train['Survived'], margins=True).style.background_gradient(cmap='summer_r')
  • Pclass와 마찬가지로 Sex도 예측모델에 쓰일 중요한 feature 임을 알 수 있음

2.3 Both Sex and Pclass

  • 이번에는 Sex, Pclass 두가지에 관하여 생존이 어떻게 달라지는 지 확인해봅시다
  • seaborn의 factorplot을 이용하면, 손쉽게 3개의 차원으로 이루어진 그래프를 그릴 수 있음
sns.factorplot('Pclass','Survived', hue='Sex', data=df_train, size=6, aspect=1.5)
  • 모든 클래스에서 female이 살 확률이 male보다 높은 걸 알 수 있음
  • 또한, 남자, 여자 상관없이 클래스가 높을 수록 살 확률 높음
  • 위 그래프는 hue대신 column으로 하면 아래와 같아짐
sns.factorplot(x='Sex', y='Survived', col='Pclass', data=df_train, satureation=.5, size=5, aspect=1)

2.4 Age

  • 이번에는 Age feature를 살펴봅시다
print('the oldest passensger: {:.1f} years'.format(df_train['Age'].max()))
print('The yongest Passenger: {:.1f} years'.format(df_train['Age'].min()))
print("Aveage Passenger's Age: {:.1f} years".format(df_train['Age'].mean()))
  • 생존에 따른 Age의 histogram을 그려보겠습니다
fig, ax = plt.subplots(1,1,figsize=(9,5))
sns.kdeplot(df_train[df_train['Survived']==1]['Age'], ax=ax)
sns.kdeplot(df_train[df_train['Survived']==0]['Age'], ax=ax)
plt.legend(['Survived==1', 'Survived==0'])
plt.show()
#Age distribution withing classes
plt.figure(figsize=(8,6))
df_train['Age'][df_train['Pclass']==1].plot(kind='kde')
df_train['Age'][df_train['Pclass']==2].plot(kind='kde')
df_train['Age'][df_train['Pclass']==3].plot(kind='kde')
                
plt.xlabel('Age')
plt.title('Age Distribution within classes')
plt.legend(['1st Class','2nd Class', '3rd class'])
  • Class가 높을 수록 나이 많은 사람의 비중이 커짐
  • 나이대가 변하면서 생존률이 어떻게 되는 지 보려고 함
  • 나이범위를 점점 넓혀가며, 생존률이 어떻게 되는지 한번 봅시다.
cummulate_survival_ratio=[]
for i in range(1, 80):
    cummulate_survival_ratio.append(df_train[df_train['Age'] < i]['Survived'].sum() / len(df_train[df_train['Age'] < i]['Survived']))
  
plt.figure(figsize=(7,7))
plt.plot(cummulate_survival_ratio)
plt.title('Survival rate change depending on range of Age', y=1.02)
plt.ylabel('Survival rate')
plt.xlabel('Range of Age(0~x)')
plt.show()
  • 보시다시피, 나이가 어릴 수록 생존률이 확실히 높음
  • 우리는 이 나이가 중요한 feature로 쓰일 수 있음을 확인

2.5 Pclass, Sex, Age

  • 지금까지 본 Sex, Pclass, Age, Survived 모두에 대해서 보고 싶습니다. 이를 쉽게 그려주는 것이 seaborn의 violinplot입니다.
  • x축은 우리가 나눠서 보고 싶어하는 case(여기선, Pclass, Sex)를 나타내고, y축은 보고 싶어하는 distribution (Age)입니다.
f,ax = plt.subplots(1,2,figsize=(18,8))
sns.violinplot('Pclass','Age', hue='Survived', data=df_train, scale='count', split=True, ax = ax[0])
ax[0].set_title('Pclass and Age vs Survived')
ax[0].set_yticks(range(0,110,10))
sns.violinplot('Sex',"Age", hue="Survived", data=df_train,scale='count', split=True, ax=ax[1])
ax[1].set_title('sex and Age vs Survived')
ax[1].set_yticks(range(0,110,10))
plt.show()
  • 왼쪽그림은 클래스 별로 연령의 분포가 어떻게 다른지 거기에 생존여부에 따라 구분한 그래프
  • 오른쪽그림도 마찬가지 성별, 생존에 따른 분포가 어떻게 다른지 보여주는 그래프
  • 생존만 봤을 때, 모든 클래스에서 나이가 어릴 수록 생존을 많이 한것을 볼 수 있다.
  • 오른쪽그림에서 보면, 명확히 여자가 생존을 많이 한 것을 볼 수 있다.
  • 여성과 아이를 먼저 챙긴것을 볼 수 있다

2.6 Embarked

  • Embarked는 탑승한 항구를 나타냄
  • 위에서 해왔던 것과 비슷하게 탑승한 곳에 따른 생존률을 보겠다
f, ax = plt.subplots(1, 1, figsize=(7, 7))
df_train[['Embarked', 'Survived']].groupby(['Embarked'], as_index=True).mean().sort_values(by='Survived', ascending=False).plot.bar(ax=ax)
  • 보시다시피 조금의 차이는 있지만, 생존률은 좀 비슷한거 같다. 그래도 C가 제일 높다
  • 모델에 얼마나 큰영향을 미칠지는 모르겠지만, 그래도 사용
  • 사실, 모델을 만들고 나면 우리가 사용한 feature들이 얼마나 중요한 역할을 했는지 확인해 볼 수 있다. 이는 추후에 모델을 만들고 난 다음에 살펴볼 예정
  • 다른 feature로 split하여 한번 살펴보자
f, ax = plt.subplots(2,2,figsize=(20,15))
sns.countplot('Embarked', data=df_train, ax=ax[0,0])
ax[0,0].set_title('(1) No. of passengers Boarded')
sns.countplot('Embarked', hue='Sex', data=df_train, ax=ax[0,1])
ax[0,1].set_title('(2) Male-Female split for embarked')
sns.countplot('Embarked', hue='Survived', data=df_train, ax=ax[1,0])
ax[1,0].set_title('(3) Embarked vs Survived')
sns.countplot('Embarked', hue='Pclass', data=df_train, ax=ax[1,1])
ax[1,1].set_title('(4) Embarked vs Pclass')
plt.subplots_adjust(wspace=0.2, hspace=0.5)
plt.show()
  • Figure(1) - 전체적으로 봤을때, S에서 가장 많은 사람이 탑승했다.
  • Figure(2) - C와 Q는 남녀의 비율이 비슷하고, S는 남자가 더 많다
  • Figure(3) - 생존확률이 S 경우 많이 낮다
  • Figure(4) - Class로 Split해서 보니, C가 생존확률이 높은건 클래스가 높은 사람이 많이 타서 그렇다. S는 3rd class가 많아서 생존확률이 낮게 나온다.

2.7 Family-SibSP(형제자매)+Parch(부모 자녀)

  • SibSp와 Parch를 합하면 Family가 될것 Family 로 합쳐서 분석해보자
df_train['FamilySize'] = df_train['SibSp']+df_train['Parch']+1 # 자신을 더해야 하니깐
df_test['FamilySize']=df_test['SibSp']+df_test['Parch']+1
print('Maximum size of Family: ', df_train['FamilySize'].max())
print("Minumum size of Family: ",df_train['FamilySize'].min())
  • FamilySize와 생존의 관계를 한번 살펴봅시다
f,ax=plt.subplots(1,3,figsize=(40,10))
sns.countplot('FamilySize', data=df_train, ax=ax[0])
ax[0].set_title('(1) No. of passengers Boarded', y=1.02)

sns.countplot('FamilySize', hue='Survived',data=df_train, ax=ax[1])
ax[1].set_title('(2) Survived countplot depending on FamilySize', y=1.02)

df_train[['FamilySize', 'Survived']].groupby(['FamilySize'], as_index=True).mean().sort_values(by='Survived', ascending=False).plot.bar(ax=ax[2])
ax[2].set_title('(3) Survived rate depending on FamilySize', y=1.02)

plt.subplots_adjust(wspace=0.2, hspace=0.5)
plt.show()
  • Figure(1): 가족크기가 1~11까지 있음 대부분 1명이고 그다음으로 2,3,4 순
  • Figure(2), (3): 가족크기에 따른 생존비교. 가족이 4명인 경우가 가장 생존확률이 높음

2.8 Fare

  • Fare는 탑승요금. continuous feature
fig,ax = plt.subplots(1,1,figsize=(8,8))
g = sns.distplot(df_train['Fare'], color='b', label='Skewness : {:.2f}'.format(df_train['Fare'].skew()), ax=ax)
g = g.legend(loc='best')
  • 보시다시피 ditribution이 매우 비대칭인 것을 알 수 있다. (high skewness). 만양 이대로 모델에 넣어준다면 자칫 모델이 잘못 학습할 수도 있다. 몇개 없는 outlier 에 대해서 너무 민감하게 반응한다면, 실제 예측 시에 좋지 못한 결과를 부를 수 있다.
  • outlier의 영향을 줄이기 위한 fare에 log를 취하겠다.
  • 여기서 우리는 pandas의 유용한 기능을 사용할 겁니다. dataframe의 특정 칼럼에 공통된 작업을 적용하고 싶으면 아래의 map, apply를 사용하면 매우 손쉽게 적용 가능
  • 우리가 지금원하는 것은 fare columns의 데이터 모두를 log 값 취하는 것인데, 파이썬의 간단한 lambda 함수를 이용해 간단한로그를 적용하는 함수를 mpa에 인수로 넣어주면 fare columns 데이터에 그대로 적용 됨 매우 유용한 기능이니 꼭 숙지!!!
df_test.loc[df_test.Fare.isnull(), 'Fare'] = df_test['Fare'].mean()
# testset 에 있는 nan value 를 평균값으로 치환합니다.

df_train['Fare'] = df_train['Fare'].map(lambda i: np.log(i) if i > 0 else 0)
df_test['Fare'] = df_test['Fare'].map(lambda i: np.log(i) if i > 0 else 0)
fig, ax = plt.subplots(1,1, figsize = (8,8))
g = sns.distplot(df_train['Fare'], color='b', label='Skewness : {:.2f}'.format(df_train['Fare'].skew()),ax=ax)
g=g.legend(loc='best')
  • 로그를 취하니, 이제 비대칭성이 많이 사라진 것을 볼 수 있다.
  • 우리는 이런 작업을 사용해 모델이 좀 더 좋은 성능을 내도록 할 수 있다.
  • 사실 방금한 것은 feature engineering에 들어가는 부분인데 여기서 작업했다.
  • 모델을 학습시키기 위해, 그리고 그 모델의 성능을 높이기 위해 feature들에 여러 조작을 가하거나, 새로운 feature를 추가하는 것을 feature engineering이라고하는데 우리는 이제 그것을 살펴볼 것이다

2.9 Cabin

  • 이 feature는 NaN이 대략 80%이므로 생존에 영향을 미칠 중요한 정보를 얻어내기가 쉽지는 않습니다.
  • 그러므로 우리가 세우려는 모델에 포함시키지 않겠다
df_train.head()

2.10 Ticket

  • 이 feature는 NaN은 없다. 일단 string data이므로 우리가 어떤 작업들을 해주어야 실제 모델에 사용할 수 있는데 이를 위해선 사실 아이디어가 필요하다
df_train['Ticket'].value_counts()
  • 보시다시피 ticket number는 매우 다양하다 우리는 여기서 어떤 특징을 이끌어내서 생존과 연결시킬 수 있을까?
  • 직접 한번 아이디어를 내보자! 이것이 본격적인 캐글 레이스의 시작점이다

'10. IT > 12. 머신러닝' 카테고리의 다른 글

[머신러닝] 지도학습  (0) 2019.02.01
[머신러닝] 머신러닝은 무엇인가?  (0) 2019.01.31

지도학습

지도학습에서는 주어진 데이터셋이 있거나, 투입물과 산출물 간의 관계가 주어진다.

지도학습 문제는 회귀분석 Regression과 분류 Classification으로 구분된다. 회귀분석에서는 투입물에 대한 연속적인 함수에 따라 도출된 연속적인 산출물로 예측한다. 분류는 정해진 산출물에 의해 예측한다. 즉, 주어진 투입물을 정해진 카테고리에 표식한다.

예시:
부동산 시장에서 집들의 크기가 주어졌을 때, 가격을 예측하라.
-> 회귀분석 (특정 요구 가격보다 큰 지, 작은 지에 대한 예측 일땐, 분류가 될 수 있음)



Supervised Learning

In supervised learning, we are given a data set and already know what our correct output should look like, having the idea that there is a relationship between the input and the output.

Supervised learning problems are categorized into "regression" and "classification" problems. In a regression problem, we are trying to predict results within a continuous output, meaning that we are trying to map input variables to some continuous function. In a classification problem, we are instead trying to predict results in a discrete output. In other words, we are trying to map input variables into discrete categories. 

Example 1:

Given data about the size of houses on the real estate market, try to predict their price. Price as a function of size is a continuous output, so this is a regression problem.

We could turn this example into a classification problem by instead making our output about whether the house "sells for more or less than the asking price." Here we are classifying the houses based on price into two discrete categories.

Example 2:

(a) Regression - Given a picture of a person, we have to predict their age on the basis of the given picture

(b) Classification - Given a patient with a tumor, we have to predict whether the tumor is malignant or benign. 

By. Machine Learning, Andrew. ng




머신러닝은 무엇인가?

Tom Mitchell : 머신러닝은 과제 Task, T에 대한 경험 Experience, E로 부터 학습되고 성과 Performance, P에 의해 측정된다.
Arthur Samuel : '기계가 일일이 코드로 명시하지 않은 동작을 데이터로 부터 학습하여 실행할 수 있도록 하는 알고리즘을 개발하는 연구 분야'
 
 
예시) 체스게임
 
E = 많은 체스 선수들과의 체스게임
 
T = 체스 게임 내에서의 이기는 룰
 
P = 다음 게임에서 이길 확률
 
 
보통, 머신러닝은 크게 두가지 분류로 나뉘어진다.
 
지도학습과 비지도 학습
 
 

What is Machine Learning?

Two definitions of Machine Learning are offered. Arthur Samuel described it as: "the field of study that gives computers the ability to learn without being explicitly programmed." This is an older, informal definition.

Tom Mitchell provides a more modern definition: "A computer program is said to learn from experience E with respect to some class of tasks T and performance measure P, if its performance at tasks in T, as measured by P, improves with experience E."

Example: playing checkers.

E = the experience of playing many games of checkers

T = the task of playing checkers.

P = the probability that the program will win the next game.

In general, any machine learning problem can be assigned to one of two broad classifications:

Supervised learning and Unsupervised learning.

By. Machine Learning, Andrew. ng

 

 

 

코딩을 공부하다 보면, 어려운 부분에 대한 설명이 필요할 때가 있고 이전의 코드를 남기고, 새로운 코드를 남기고 싶을 때가 있습니다.

이때 주석이 필요합니다.

 

파이썬에서 주석을 작성하는 방법으론 두 가지가 있습니다.

 

한줄 주석: # 코드 상단에 주석 한 줄을 달거나, 코드 옆에 주석을 추가할 수 있습니다.

 

# 매개 변수 인코딩
values = {
    'stnId' : regionNumber # 지역 번호
}

 

전체 주석: 

"""

코드 블록을 지정해서 전체를 주석으로 지정할 수 있습니다.

"""

 

"""
    values = {
    'stnId' : regionNumber # 지역 번호
    }
"""

 

주석 단축키는 Ctrl + / 입니다.

Mac에선 command + / 으로 주석을 추가할 수 있습니다.

 

+) 매개변수: 함수를 정의할 때 사용하는 이름

def print_rount(number):
    rounded = round(number)
    return rounded

 

+ Recent posts