파이썬/NIPA 데이터분석 강의

NIPA 온라인선택 데이터 머신러닝 03 머신러닝을 위한 데이터 이해하기

mcdn 2020. 10. 4. 18:02
반응형

 

데이터는 세계를 표현하는 퍼즐의 하나의 조각이 된다 

어떤 측정도구를 사용해서 현상 기록한 것 

그래서 측정도구의 신뢰도 타당도를 많이 보게 됨 

 

데이터는 팩트. 항상 같은 결과가 나와야 하고 신뢰할 수 있어야 한다. 주관적인 데이터는 좋은 퀄리티가 되지 않는다. 

두번째 특징은 데이터 자체가 의미는 없다. context가 필요. 그리고 마지막으로 실제 세계를 표현한 것. 자연어를 처리하기 위한 유명한 알고리즘은 word2vec 단어를 벡터로 표현하는 알고리즘. 

 

feature

수치 또는 디지털화된 형태로 표현한걸 feature이라 한다. 

예를 들어 단어를 숫자형태로 만드는 것. 이미지변환이 가장 대표적인 예. 

타이타닉호 티켓을 보고 성별, 등급 등을 -> 컴퓨터의 디지털 형태로 변환. 

 

feature은 머신러닝에서 사용되는 단어로

다른 분야에서는 독립변수, 예측인자, input, attribute등 다양한 용어로 쓰인다. 

우리가 예측하려는 목표의 대상이 명확해야한다. 데이터 준비하는 과정에서 target -> 다음 target 위해 레이블링 과정이 중요하다. 

 

가설 그자체가 모델이기도 하다. 

머신러닝 모델은 논리, 함수식의 형태로 표현한 것 

 

머신러닝에서 알고리즘도 용어가 조금 다르다. 

함수식을 만들어내는 일련의 절차, 규칙을 의미한다. 

어떤 알고리즘을 사용하느냐 따라 다른 가설, 다른 함수식이 나온다. 

1장에서도 에러를 반영한다는 얘기를 많이 했었다. 

loss cost error 모두 다 비슷한 의미로 사용되는데 

타겟에서 조금 벗어나서 예측을 하거나 결과가 나오는걸 lost error 라고 한다.

그 에러 오차를 최소화하는 함수식을 찾아내는 과정은 학습 learning이라 한다. 

데이터를 준비하는 과정에서 가장 중요한건 실제 그 문제가 해결될 수 있는지 우리가 준비한 데이터가 효용이 있는지, 실제 문제와 연결이 되는지를 항상 고민해야 한다. 

심리학 공부를 했는데.. 실제 마음의 현상을 설명하는지 고민한다. 아무리 좋은 알고리즘, 복잡한 방법을 사용한더라도 데이터가 쓰레기면 결과는 쓰레기다. 

데이터 형태로 만들고 데이터 프로세싱 feature engineering 과정을 통해 feature 만든다. 

컴퓨터가 더 잘 이해하면 할수록 더 좋은 모델을 만들게 된다.

 

 데이터를 준비하는 파이프라인. 

feature engineering은 도메인에 대한 내용이 포함되기에 따로 또 다룰 예정 

 

 

도메인 지식 없이 데이터를 준비해보기

도메인 지식이 없더라도 Data Preprocessing과 Feature Engineering을 할 수 있습니다.

어떤 경우에는 일부러 데이터에 대한 이해 없이 를 보지 않고 기계적으로 작업을 하기도 합니다.

이번 실습에서는 다음의 3가지 Data Preprocessing 과정을 실습할 것입니다.

1) Variable Selection
2) Handling Missing Values
3) Vectorization

첫번째 load_titanic_dataset()

def load_titanic_dataset():
    print('>>> 타이타닉 데이터셋을 불러옵니다...')
    elice_utils.send_image("./data/image01.png")
    sleep(2)
    print(' ')
    return pd.read_csv('./data/titanic.csv')
	
==========================
>> 데이터 처리 결과는 다음과 같습니다.
     PassengerId  Survived  Pclass                          Name     Sex  \
61            62         1       1           Icard, Miss. Amelie  female   
270          271         0       1         Cairns, Mr. Alexander    male   
324          325         0       3      Sage, Mr. George John Jr    male   
734          735         0       2  Troupiansky, Mr. Moses Aaron    male   
584          585         0       3           Paulner, Mr. Uscher    male   
855          856         1       3    Aks, Mrs. Sam (Leah Rosen)  female   
398          399         0       2              Pain, Dr. Alfred    male   
434          435         0       1     Silvey, Mr. William Baird    male   

      Age  SibSp  Parch    Ticket     Fare Cabin Embarked  
61   38.0      0      0    113572  80.0000   B28      NaN  
270   NaN      0      0    113798  31.0000   NaN        S  
324   NaN      8      2  CA. 2343  69.5500   NaN        S  
734  23.0      0      0    233639  13.0000   NaN        S  
584   NaN      0      0      3411   8.7125   NaN        C  
855  18.0      0      1    392091   9.3500   NaN        S  
398  23.0      0      0    244278  10.5000   NaN        S  
434  50.0      1      0     13507  55.9000   E44        S  

처음에는 데이터 셋을 다 show하고 있다. cabin name 등 

 

 

 

두번째 variable_selection 함수 

1) Variable Selection

결측치가 많고 불필요한 컬럼은 제거해주세요

도메인에 따라 다르지만 결측치가 50%이상 넘어가면 변수 자체를 제거하는 것이 좋습니다.

  • 결측치가 많아 제거되는 컬럼 : Cabin
  • 불필요한 컬럼 : PanssengerId, Name, Ticket

** 결측값(결측치) in R NA(Not Available) , 결측치라고 하며 값이 표기되지 않은 값

def variable_selection(df):
    if df is None or df.empty:
        print('타이타닉 데이터를 입력해주세요')
        return None
    columns = ['PassengerId', 'Name', 'Ticket', 'Cabin']
    df.drop(columns, axis=1, inplace=True)
    print('[Variable Selection] 불필요한 컬럼을 제거하였습니다...')
[Variable Selection] 불필요한 컬럼을 제거하였습니다...


==========================
>> 데이터 처리 결과는 다음과 같습니다.
     Survived  Pclass     Sex   Age  SibSp  Parch     Fare Embarked
61          1       1  female  38.0      0      0  80.0000      NaN
270         0       1    male   NaN      0      0  31.0000        S
324         0       3    male   NaN      8      2  69.5500        S
734         0       2    male  23.0      0      0  13.0000        S
584         0       3    male   NaN      0      0   8.7125        C
855         1       3  female  18.0      0      1   9.3500        S
398         0       2    male  23.0      0      0  10.5000        S
434         0       1    male  50.0      1      0  55.9000        S

이제 여러 섹션이 사라져 간결해졌다. 아직 Age 섹션에 NaN 즉 결측치가 존재한다. 

 

 

 

세번째 handling_missing_values함수 

2) Handling Missing Values

결측치가 있으면 채워주세요

나이(Age)의 결측치를 중앙값(‘median’)으로 채웁니다.

def handling_missing_values(df):
    if df is None or df.empty:
        print('타이타닉 데이터를 입력해주세요')
        return None
    age_median = df['Age'].median()
    df['Age'].fillna(age_median, inplace=True)
    print('[Handling Missing Values] 나이(Age)의 결측치를 중앙값(median)으로 채웠습니다...')
[Variable Selection] 불필요한 컬럼을 제거하였습니다...
[Handling Missing Values] 나이(Age)의 결측치를 중앙값(median)으로 채웠습니다...


==========================
>> 데이터 처리 결과는 다음과 같습니다.
     Survived  Pclass     Sex   Age  SibSp  Parch     Fare Embarked
61          1       1  female  38.0      0      0  80.0000      NaN
270         0       1    male  28.0      0      0  31.0000        S
324         0       3    male  28.0      8      2  69.5500        S
734         0       2    male  23.0      0      0  13.0000        S
584         0       3    male  28.0      0      0   8.7125        C
855         1       3  female  18.0      0      1   9.3500        S
398         0       2    male  23.0      0      0  10.5000        S
434         0       1    male  50.0      1      0  55.9000        S

age는 28.0이라는 중앙값 median으로 채워졌다. 

 

 

 

네번째 vectorization 

3) Vectorization

이제 컴퓨터가 이해할 수 있도록 데이터를 변환해주세요

‘female’, ‘male’은 사람은 이해할 수 있지만, 컴퓨터는 여성인지 남성인지 알 수 없습니다.

컴퓨터가 이해할 수 있도록 male은 0으로, female은 1로 변환합니다

def vectorization_sex(df):
    if df is None or df.empty:
        print('타이타닉 데이터를 입력해주세요')
        return None
    try:
        sex_mapping = {'male': 0, 'female': 1}
        df['Sex'].replace(sex_mapping, inplace=True)
        print('[Vectorization] 성별(Age)을 처리하였습니다...')
    except TypeError:
        return df

def vectorization_embarked(df):
    if df is None or df.empty:
        print('타이타닉 데이터를 입력해주세요')
        return None
    try:
        embarked_mapping = {'S': 0, 'C': 1, 'Q': 2}
        df['Embarked'].replace(embarked_mapping, inplace=True)
        print('[Vectorization] 탑승한 곳(Embarked)을 처리하였습니다...')
        return df.copy()
    except TypeError:
        return df
	
[Variable Selection] 불필요한 컬럼을 제거하였습니다...
[Handling Missing Values] 나이(Age)의 결측치를 중앙값(median)으로 채웠습니다...
[Vectorization] 성별(Age)을 처리하였습니다...
[Vectorization] 탑승한 곳(Embarked)을 처리하였습니다...


==========================
>> 데이터 처리 결과는 다음과 같습니다.
     Survived  Pclass  Sex   Age  SibSp  Parch     Fare  Embarked
61          1       1    1  38.0      0      0  80.0000       NaN
270         0       1    0  28.0      0      0  31.0000       0.0
324         0       3    0  28.0      8      2  69.5500       0.0
734         0       2    0  23.0      0      0  13.0000       0.0
584         0       3    0  28.0      0      0   8.7125       1.0
855         1       3    1  18.0      0      1   9.3500       0.0
398         0       2    0  23.0      0      0  10.5000       0.0
434         0       1    0  50.0      1      0  55.9000       0.0

성과 탑승한 곳은 0/1 숫자로 표현하게 되었다. 

 

 

보너스 

결측치(Null)를 확인

데이터를 처리하는 실습 코드 이전에 실행해야 제대로 확인이 됩니다. 

코드처럼 뭘 처리하기 전에 함수를 쓴다 

>> 타이타닉 데이터의 변수별 결측치 비율은 다음과 같습니다.
PassengerId : 0.00%
Survived : 0.00%
Pclass : 0.00%
Name : 0.00%
Sex : 0.00%
Age : 19.87%
SibSp : 0.00%
Parch : 0.00%
Ticket : 0.00%
Fare : 0.00%
Cabin : 77.10%
Embarked : 0.22%

최종 

from without_domain import *

def data_preparation_without_domain():
    titanic = load_titanic_dataset()
    
    # [데이터 준비 방법]
    # - Variable Selection : 결측치가 많고 불필요한 컬럼은 제거해주세요
    # - Handling Missing Values : 결측치가 있으면 채워주세요
    # - Vectorization : 컴퓨터가 이해할 수 있도록 데이터를 변환해주세요
    check_missing_values(titanic)
    variable_selection(titanic)
    handling_missing_values(titanic)
    vectorization_sex(titanic)
    vectorization_embarked(titanic)
    
    # [실습] 
    # 아래에 실습 코드를 입력하여
    # 데이터가 어떻게 처리되는지 확인하세요
    # [Bonus] 결측치(Null)를 확인해주세요 	



	
	
    # 데이터 처리 결과를 보여줍니다
    show_result(titanic)

if __name__ == "__main__":
    data_preparation_without_domain()

 

 

도메인 지식 늘리기

깊은 도메인 지식을 가질수록 더 나은 데이터 준비(Data Preprocessing + Feature Engineering)가 가능해집니다.

어떤 현상을 설명할 수 있는 더 많은 정보를 추가하고 적절한 Feature를 구성하게 된다면,

머신러닝 프로젝트는 성공할 확률이 높아집니다

“이름”(Name)의 중요성

외국인들은 우리와 달리 이름에 많은 정보가 담겨 있습니다.

이 사실을 몰랐던 준비 과정에서는 “이름”을 불필요한 컬럼이라고 생각하고 제거했습니다.

타이타닉호 승선자들의 이름에는 Mr, Miss, Mrs, Master, Dr, Lady, Capt 등이 포함되어 있습니다.

그 사람의 사회적 지위나 결혼여부 등의 정보가 담겨있습니다.


“나이”(Age)의 중요성 (1)

이름을 통해 신분이나 결혼여부를 알게된다면,

약 20%의 사람들의 나이에 대한 결측치를 단순 ‘중앙값(median)’이 아니라

좀 더 정확하게 근삿값으로 채울 수 있게됩니다.


“나이”(Age)의 중요성 (2)

서양에서는 아이와 노인을 먼저 구출하는 성향이 있다고 합니다.

10대, 20대가 아닌 연령군의 특성을 반영한다면

단순 나이보다 나을 것 같습니다.


“가족”의 중요성

아래 타이타닉호 침몰을 분석한 인포그래픽을 보면,

가족이 있을 때 생존확률이 높은 것을 발견하실 수 있습니다.

생존자의 이름을 봤을 때 부부로 보이는 사람들이 함께 살아남는 경우도 발견할 수 있습니다.

그렇습니다! 가족이 많을수록 최고입니다….


“탑승위치”의 중요성

아래 그림을 보면 타이타닉이 어떻게 파손되고 침몰했는지 알 수 있습니다.

탑승위치를 알 수 있다면 더 좋지 않을까요?

https://static1.squarespace.com/static/5006453fe4b09ef2252ba068/t/5090b249e4b047ba54dfd258/1351660113175/TItanic-Survival-Infographic.jpg?format=1500w

이번 실습에서는 Feature Engineering을 추가로 적용해서 모델의 결과가 어떻게 변하는지 확인할 것입니다.

이번 실습에서는 아래의 내용을 다룹니다.

  • Data Preprocessing (이전 실습 참조)
  • Feature Engineering
    • Feature Transformation
    • Feature Generation

실습 순서

1) Data Preprocessing을 실행시키세요

이전 실습에서 다룬 Variable Selection, Handling Missing Value, Vectorization을 실행합니다.

2) Feature Engineering을 실행시키세요

4개의 Feature Engineering 기법에 대해서 사용 여부를 체크하는 스위치(switch)가 있습니다. 해당 Feature Engineering을 사용하고자 한다면 True를 입력해주세요.

< switch 정보 >

switch namedescription입력 가능한 값
name 탑승자의 이름에서 사회적 지위나 결혼여부 등의 feature를 추출합니다 True or False
age 다양한 맥락 정보를 활용하여 결측치를 처리합니다 True or False
age_categorization 새로운 연령군으로 feature를 추출합니다 True or False
familysize 가족구성원의 크기에 대한 feature를 생성합니다 True or False

3) 결과를 확인합니다.

각 feature engineering을 통해서 데이터가 어떻게 변환되고 생성되었는지 결과창을 통해 확인하세요!

※ Feature engineering을 하지 않았을 때의 모델의 정확도는 77.28%입니다.

from with_domain import *


def data_preparation_with_domain():
	titanic = load_titanic_dataset()

	
	'''
	[실습] 지시사항에 맞게 아래에 코드를 입력해주세요
	
	'''
	# 1) Data Preprocessing을 실행시키세요 (아래 한 줄 코드 작성)
	titanic = data_preprocessing(titanic)
	
	
	# 2) Feature Engineering을 실행시키세요 (아래 4개의 변수에 True or False 입력)
	switch = {
		'name' :  False     , # True or False
		'age' :  False     , # True or False
		'age_categorization' :   False   , #True or False
		'familysize':    False    # True or False
	}

	feature_engineering(titanic, switch)
	
	
	
	# 3) 결과를 확인하세요
	show_result(titanic)
	
	

if __name__ == "__main__":
    data_preparation_with_domain()
>>> 타이타닉 데이터셋을 불러옵니다...
==============================================
>> 최종 결과 Accuracy : 77.28%

이름, 나이, 가족 등의 요소를 고려하지 않았을 때 accuracy는 77%다. 

뭐지 더 낮아지는데 

 

 

반응형