이전 포스트

 

 

 

 

2023.01.12 - [분류 전체보기] - 타이타닉 생존자 예측 분석 (3-2) 데이터 정리 - v.1.0.1

 

타이타닉 생존자 예측 분석 (3-2) 데이터 정리 - v.1.0.1

이전 포스트 2023.01.09 - [Kaggle/타이타닉] - 타이타닉 생존자 예측 분석 (3-1) 전처리 (나이예측) - v.1.0.1 타이타닉 생존자 예측 분석 (3-1) 전처리 (나이예측) - v.1.0.1 이전 포스트 2023.01.09 - [분류 전체

drewvvv.tistory.com


 

 

1. 데이터 인코딩

  • 모델에 학습을 하기 위해선 사실 몇가지 준비가 필요하다.
  • 모델에 학습시킬 데이터에 대한 내용인데, 
    • 1. 데이터프레임 안의 데이터는 숫자여야 하며(could not convert string to float)
      • 이때 범주형 변수를 숫자로 나타내게될 때, 사실 서로 아무 의미가 없지만 모델이 의미를 갖는 경우가 생기는 것에 주의해야 한다.  (참고링크)
      • 위의 차이를 확인해보고자, 레이블 인코딩과 원핫 인코딩으로 비교 제출해 볼 것이다.
    • 2. 원핫인코딩의 경우 값을 기준으로 분류하기 때문에, 값을 컬럼명으로 사용하는 경우가 발생한다. 
      • 이때 원핫인코딩은 컬럼명을 도출하지만, 각기 다른 컬럼에 값이 같은 경우 문제가 될 수 있으며,
      • 가장 중요한 모델의 학습의 경우 컬럼명이 숫자인 경우 워링이 발생한다. (FutureWarning: Feature names only support names that are all strings. Got feature names with dtypes: ['int64'])
        • 경우의 따라 숫자 컬럼명을 문자로 변경해주면 되긴하지만, 그것은 모델의 학습에 대해 의도한 바가 아니다. 
    • 3. scikit-learn의 onehot-encoding과 pandas의 get_dummies()
      • 겉으로 보기엔 둘은 똑같은 역할을 하는 것처럼 보이지만 둘은 공통점과 명확한 차이가 존재한다.
      • 우선 공통점을 보자면 두 메서드는 각 값에 해당하는 컬럼을 새로 생성한 후 컬럼에 해당하는 값일 경우 1 아닐 경우 0으로 둔다. (참고링크)
      •  
      • 히지만 명확한 차이는 모델 학습에서 들어난다. 
        • 판다스의 get_dummies()는 그저 위의 공통사항을 분류만 할 뿐이지만,
        • 사이킷 런의 원핫인코딩은 train 데이터 셋에 맞게 test 셋을 맞추는 것이다. 
        • 이 차이를 다시 풀자면, train 셋에는 해당하는 컬럼이 없지만 test 셋에는 컬럼이 있을 경우 모델은 학습을 할 수 없어 에러가 나게된다. 
        • 하지만 원핫인코딩의 경우 데이터 뿐만이 아니라, 컬럼명까지 참조하기 때문에 get_dummies()와 같은 문제가 발생하지 않는다. (단 encoding시 handle_unknown='ignore' 파라미터 추가 필요)
        • 하지만 get_dummies()도 위의 문제를 해결하고 사용할 수 있는 방법이 있는데, 파이프라인을 구축하여 encoding시 원핫인코딩의 handle_unknown 기능을 간접적으로 구현하는 방법이 있다. (참고링크)
        • (이외의 다른 차이도 존재하지만 생략)
  • 따라 본 v1.0.1 버전에선 다음과 같은 계획을 갖고 비교해가며 모델 학습을 진행한다. 
    • 인코딩 방법간의 차이를 살펴보기 위해 모델은 RandomForest로 고정한다.
    • 1. 앞의 (3-2) 데이터 정리 포스트에서 변수를 숫자 범주형(레이블 인코더)으로 변환한 데이터를 그대로 학습 후 제출 
    • 2. 숫자 범주형을 사용하지 않고 범주형 데이터를 원핫인코딩 후 제출 

 

위의 1번의 경우 데이터 셋을 불러온다. 

1
2
3
4
5
6
import pandas as pd
import numpy as np
 
noNaTrain = pd.read_csv("../input/noNa_train - v1.0.1.csv")
noNaTest = pd.read_csv("../input/noNa_test - v1.0.1.csv")
gender = pd.read_csv("../input/gender_submission.csv")
cs

 

1
2
3
4
5
feature_1 = ['Survived','Pclass','ca_Sex','ca_Age''SibSp''Parch','ca_designation']
 
train_data = noNaTrain[feature_1[1:]].copy()
target = noNaTrain['Survived'].copy().values
test_data = noNaTest[feature_1[1:]].copy()
cs
  • Fare 컬럼을 사용하지 않고 위와 같이 featrue_1을 구성한다.
  • 모델에 학습시킬 train_data는 Survived를 제외, target은 Survived를 사용

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
 
X_train, X_test, y_train, y_test = train_test_split(train_data, target, test_size = 0.2, random_state=42)
 
model = RandomForestClassifier()
model.fit(X_train, y_train)
accuracy = round(model.score(X_test, y_test) * 1002)
print(f"accuracy of {type(model).__name__}: {str(accuracy)}%")
 
predict = model.predict(test_data)
submission_df = pd.DataFrame({'PassengerId':noNaTest['PassengerId'],
                            'Survived':predict})
# submission_df.head()
submission_df.to_csv(f'sbn_{type(model).__name__ }_labeling.csv', index=False)
print(f"name of export submission : sbn_{type(model).__name__}_labeling.csv")
cs

 

  • 분류모델에 별다른 하이퍼 파라미터 수정하지 않고,
  • 위의 train_data는 변수들을 라벨링한 후의 결과 값으로 80.45%의 정확도를 보였다. 

  • 하지만 실제 스코어는 0.5933으로 매우 낮았다. 

 

이제 2번의 계획인 onehot encoding을 사용해 본다. 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
# test for one hot encoding
feature_2 = ['Survived''Pclass''Sex''ca_Age''SibSp''Parch''designation']
 
train_data2 = noNaTrain[feature_2[1:]].copy()
target = noNaTrain['Survived'].copy().values
test_data2 = noNaTest[feature_2[1:]].copy()
 
 
for df in [train_data2, test_data2]: 
    for col in ['Pclass', 'ca_Age', 'SibSp''Parch']:
        for index, item in enumerate(df[col]):
            df.loc[index, col] = col+ '_' + str(item)
 
cs
  • 우선 feature의 경우 기존 feature_1 = ['Survived','Pclass','ca_Sex','ca_Age''SibSp''Parch','ca_designation'] 에서
  • ca_Sex를 Sex로, ca_designation은 designation으로 사용하고 나머지 컬럼은 앞의 prefix를 붙혀 데이터를 변환한다. 
  • 데이터 변환 결과는 아래와 같다. 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# https://towardsdatascience.com/stop-using-pandas-get-dummies-for-feature-encoding-5d2cd07cb4fc 
# https://pythonsimplified.com/difference-between-onehotencoder-and-get_dummies/
 
from sklearn.preprocessing import OneHotEncoder
# one hot encoding
enc = OneHotEncoder(sparse=False, handle_unknown='ignore')
onehot = enc.fit_transform(train_data2[feature_2[1:]])
columns = list([j for i in enc.categories_ for j in i])
#to print the encoded features for train data
trainOneHotDf = pd.DataFrame(onehot, columns=columns)
train_data2 = trainOneHotDf.copy()
 
# tranform encoding for test data
test_onehot = enc.transform(test_data2[feature_2[1:]])
#to print the encoded features for train data
testOneHotDf = pd.DataFrame(test_onehot, columns=columns)
test_data2 = testOneHotDf.copy()
cs
  • 위 코드를 살펴보면 enc를 통해 train_data가 fit_transform되었고 , onehot array를 실제 columns와 매핑하여 trainOneHotDf를 생성하였다.
  • testOneHotDf의 경우는 train_data2의 컬럼을 기준으로 학습된 enc를 적용하여 transform해서 test셋에는 있지만 train 셋에는 없어서 학습할 수 없는 경우가 발생하지 않도록 unknown 컬럼은 ignore 시키도록 파라미터를 추가하였다.

  • 위를 바탕으로 feature들이 onehot-encoding된 것을 확인할 수 있다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
X_train, X_test, y_train, y_test = train_test_split(train_data2, target, test_size = 0.2, random_state=42)
 
model = RandomForestClassifier()
model.fit(X_train, y_train)
accuracy = round(model.score(X_test, y_test) * 1002)
print(f"accuracy of {type(model).__name__}: {str(accuracy)}%")
 
predict = model.predict(test_data2)
submission_df = pd.DataFrame({'PassengerId':noNaTest['PassengerId'],
                            'Survived':predict})
# submission_df.head()
submission_df.to_csv(f'sbn_{type(model).__name__ }_onehot.csv', index=False)
print(f"name of export submission : sbn_{type(model).__name__}_onehot.csv")
cs

 

  • 분류모델에 별다른 하이퍼 파라미터 수정하지 않고,
  • 위의 train_data는 변수들을 onehot-encoding한 후의 결과 값으로 82.68%의 정확도를 보였다. 

  • 단지 onehot-encoding만 실시하였지만 score가 확연히 차이나는 것을 확인할 수 있다.
  • 이는 모델이 학습시에 데이터를 올바르게 읽지 못하고 연속된 값이 연관이 있다고 판단하여 생기는 문제이다.
  • 따라 데이터 전처리의 경우 각 데이터의 특성에 따른 적절한 전처리를 할 필요가 있다.

 

 

 

 

 

다음 포스트

 

 

TBW

 
 
 
 
 
 
 
 
 

+ Recent posts