Feature Engineering with Housing Price Prediction - Missing Values

Page content

강의 홍보

개요

  • Feature Engineering를 이해하고 실습한다.
    • 결측치를 처리한다.

I. 사전 준비작업

  • Kaggle API 설치 후 데이터를 Kaggle에서 직접 가져오는 것을 구현한다.

(1) Kaggle API 설치

  • 구글 코랩에서 API를 불러오려면 다음 소스코드를 실행한다.
!pip install kaggle
Requirement already satisfied: kaggle in /usr/local/lib/python3.6/dist-packages (1.5.6)
Requirement already satisfied: certifi in /usr/local/lib/python3.6/dist-packages (from kaggle) (2020.6.20)
Requirement already satisfied: six>=1.10 in /usr/local/lib/python3.6/dist-packages (from kaggle) (1.15.0)
Requirement already satisfied: python-dateutil in /usr/local/lib/python3.6/dist-packages (from kaggle) (2.8.1)
Requirement already satisfied: urllib3<1.25,>=1.21.1 in /usr/local/lib/python3.6/dist-packages (from kaggle) (1.24.3)
Requirement already satisfied: python-slugify in /usr/local/lib/python3.6/dist-packages (from kaggle) (4.0.1)
Requirement already satisfied: tqdm in /usr/local/lib/python3.6/dist-packages (from kaggle) (4.41.1)
Requirement already satisfied: requests in /usr/local/lib/python3.6/dist-packages (from kaggle) (2.23.0)
Requirement already satisfied: text-unidecode>=1.3 in /usr/local/lib/python3.6/dist-packages (from python-slugify->kaggle) (1.3)
Requirement already satisfied: idna<3,>=2.5 in /usr/local/lib/python3.6/dist-packages (from requests->kaggle) (2.10)
Requirement already satisfied: chardet<4,>=3.0.2 in /usr/local/lib/python3.6/dist-packages (from requests->kaggle) (3.0.4)

(2) Kaggle Token 다운로드

  • Kaggle에서 API Token을 다운로드 받는다.
  • [Kaggle]-[My Account]-[API]-[Create New API Token]을 누르면 kaggle.json 파일이 다운로드 된다.
  • 이 파일을 바탕화면에 옮긴 뒤, 아래 코드를 실행 시킨다.
from google.colab import files
uploaded = files.upload()
for fn in uploaded.keys():
  print('uploaded file "{name}" with length {length} bytes'.format(
      name=fn, length=len(uploaded[fn])))
  
# kaggle.json을 아래 폴더로 옮긴 뒤, file을 사용할 수 있도록 권한을 부여한다. 
!mkdir -p ~/.kaggle/ && mv kaggle.json ~/.kaggle/ && chmod 600 ~/.kaggle/kaggle.json

Upload widget is only available when the cell has been executed in the current browser session. Please rerun this cell to enable.

Saving kaggle.json to kaggle.json
uploaded file "kaggle.json" with length 64 bytes
  • 실제 kaggle.json 파일이 업로드 되었다는 뜻이다.
ls -1ha ~/.kaggle/kaggle.json
/root/.kaggle/kaggle.json

(3) Kaggle 데이터 불러오기

  • Kaggle 대회 리스트를 불러온다.
!kaggle competitions list
Warning: Looks like you're using an outdated API Version, please consider updating (server 1.5.6 / client 1.5.4)
ref                                            deadline             category            reward  teamCount  userHasEntered  
---------------------------------------------  -------------------  ---------------  ---------  ---------  --------------  
contradictory-my-dear-watson                   2030-07-01 23:59:00  Getting Started     Prizes        253           False  
gan-getting-started                            2030-07-01 23:59:00  Getting Started     Prizes         88           False  
tpu-getting-started                            2030-06-03 23:59:00  Getting Started  Knowledge        369           False  
digit-recognizer                               2030-01-01 00:00:00  Getting Started  Knowledge       2556           False  
titanic                                        2030-01-01 00:00:00  Getting Started  Knowledge      19017            True  
house-prices-advanced-regression-techniques    2030-01-01 00:00:00  Getting Started  Knowledge       4933            True  
connectx                                       2030-01-01 00:00:00  Getting Started  Knowledge        609           False  
nlp-getting-started                            2030-01-01 00:00:00  Getting Started  Knowledge       1451            True  
competitive-data-science-predict-future-sales  2020-12-31 23:59:00  Playground           Kudos       8621            True  
hashcode-drone-delivery                        2020-12-14 23:59:00  Playground       Knowledge          6           False  
lish-moa                                       2020-11-30 23:59:00  Research           $30,000        826           False  
conways-reverse-game-of-life-2020              2020-11-30 23:59:00  Playground            Swag         49           False  
lyft-motion-prediction-autonomous-vehicles     2020-11-25 23:59:00  Featured           $30,000        341           False  
rsna-str-pulmonary-embolism-detection          2020-10-26 23:59:00  Featured           $30,000          2           False  
osic-pulmonary-fibrosis-progression            2020-10-06 23:59:00  Featured           $55,000       1577           False  
landmark-recognition-2020                      2020-09-29 23:59:00  Research           $25,000        582           False  
halite                                         2020-09-15 23:59:00  Featured              Swag       1128           False  
birdsong-recognition                           2020-09-15 23:59:00  Research           $25,000       1318           False  
global-wheat-detection                         2020-08-19 01:59:00  Research           $15,000       2245           False  
landmark-retrieval-2020                        2020-08-17 23:59:00  Research           $25,000        541           False  
  • 여기에서 참여하기 원하는 대회의 데이터셋을 불러오면 된다.
  • 이번 basic강의에서는 house-prices-advanced-regression-techniques 데이터를 활용한 데이터 가공과 시각화를 연습할 것이기 때문에 아래와 같이 코드를 실행하여 데이터를 불러온다.
!kaggle competitions download -c house-prices-advanced-regression-techniques
Warning: Looks like you're using an outdated API Version, please consider updating (server 1.5.6 / client 1.5.4)
Downloading sample_submission.csv to /content
  0% 0.00/31.2k [00:00<?, ?B/s]
100% 31.2k/31.2k [00:00<00:00, 12.4MB/s]
Downloading test.csv to /content
  0% 0.00/441k [00:00<?, ?B/s]
100% 441k/441k [00:00<00:00, 58.0MB/s]
Downloading data_description.txt to /content
  0% 0.00/13.1k [00:00<?, ?B/s]
100% 13.1k/13.1k [00:00<00:00, 11.6MB/s]
Downloading train.csv to /content
  0% 0.00/450k [00:00<?, ?B/s]
100% 450k/450k [00:00<00:00, 61.3MB/s]
  • 실제 데이터가 잘 다운로드 받게 되었는지 확인한다.
!ls
data_description.txt  sample_data  sample_submission.csv  test.csv  train.csv

(4) 데이터 불러오기

  • pandas 모듈을 활용해서 데이터를 확인해본다.
import pandas as pd
train = pd.read_csv('train.csv')
test = pd.read_csv('test.csv')

# Id Column 저장
train_ID = train['Id']
test_ID = test['Id']

print("Id 컬럼 삭제 전 Train 데이터 size : {} ".format(train.shape))
print("Id 컬럼 삭제 전 Test 데이터 size : {} ".format(test.shape))

# Id 삭제
train.drop("Id", axis = 1, inplace = True)
test.drop("Id", axis = 1, inplace = True)

print("Id 컬럼 삭제 후 Train 데이터 size : {} ".format(train.shape))
print("Id 컬럼 삭제 후 Test 데이터 size : {} ".format(test.shape))
Id 컬럼 삭제 전 Train 데이터 size : (1460, 81) 
Id 컬럼 삭제 전 Test 데이터 size : (1459, 80) 
Id 컬럼 삭제 후 Train 데이터 size : (1460, 80) 
Id 컬럼 삭제 후 Test 데이터 size : (1459, 79) 
  • 변수명이 삭제된 것을 확인한다.

II. 데이터 싸이언스의 전반적인 흐름 리뷰

III. Feature Engineering

  • 도메인 지식을 활용하여 특징(Feature)을 만들어내는 과정
  • 머신러닝 모델을 위한 Column 생성하거나 또는 선택하는 작업 의미
  • Feature Engineering은 모델 성능에 즉각적으로 영향을 미치기 때문에 ML응용에 있어서 굉장히 중요한 단계이며, 전문성과 시간과 비용이 많이 듬
  • 리뷰하는 차원에서 말하면, Feature Preprocessing관한 일반적인 내용은 다음과 같다.
    • 수치형: Scaling, Outliers, Rank, np.log(1+x) and np.sqrt(1+x)
    • 범주형: Label Encoding for tree based models, One-hot encoding for non-tree-based models
    • 날짜: 주기성(=Periodicity), Time Since, 날짜간의 차이
    • 위도 & 경도: places, centers, statistics
  • Feature Engineering은 결국 Feature를 컨트롤 및 추출하는 것으로 정의할 수 있다.
    • 수치형 데이터: Binarization, Log Transformation, Scaling, Normalization, Regularization
    • 텍스트 데이터: Bag of X, Stopwords, Tokenization, Tf-IDF Transformation, Regularization
    • 범주형 데이터: One-hot encoding, Dummy Encoding, Effect Coding
    • 차원축소(PCA)
  • 그러나, 결측치를 채우는 것도 Feature Engineering에 포함되며, 이 때 Target에 따른 mean encoding도 포함하게 된다. 특히, mean encoding은 분류모형을 다룰 때 다시 설명하도록 한다.

(1) 데이터 합치기

  • 데이터를 합치는데, target 데이터를 별도 변수로 저장한다.
ntrain = train.shape[0] # 행 개수 저장
ntest = test.shape[0] # 행 개수 저장

y_train = train.SalePrice.values # y_train 추출

house_df = pd.concat((train, test)).reset_index(drop = True)
house_df.drop(['SalePrice'], axis=1, inplace=True)
print("전체 데이터 Size : {}".format(house_df.shape))
전체 데이터 Size : (2919, 79)

(2) 결측치 데이터 확인

  • 결측치 check 함수를 만든다.
def check_na(data):
  isnull_na = (data.isnull().sum() / len(data)) * 100
  data_na = isnull_na.drop(isnull_na[isnull_na == 0].index).sort_values(ascending=False)
  missing_data = pd.DataFrame({'Missing Ratio' :data_na, 
                               'Data Type': data.dtypes[data_na.index]})
  print("결측치 데이터 컬럼과 건수:\n", missing_data)
check_na(house_df)
결측치 데이터 컬럼과 건수:
               Missing Ratio Data Type
PoolQC            99.657417    object
MiscFeature       96.402878    object
Alley             93.216855    object
Fence             80.438506    object
FireplaceQu       48.646797    object
LotFrontage       16.649538   float64
GarageFinish       5.447071    object
GarageYrBlt        5.447071   float64
GarageQual         5.447071    object
GarageCond         5.447071    object
GarageType         5.378554    object
BsmtExposure       2.809181    object
BsmtCond           2.809181    object
BsmtQual           2.774923    object
BsmtFinType2       2.740665    object
BsmtFinType1       2.706406    object
MasVnrType         0.822199    object
MasVnrArea         0.787941   float64
MSZoning           0.137033    object
BsmtFullBath       0.068517   float64
BsmtHalfBath       0.068517   float64
Utilities          0.068517    object
Functional         0.068517    object
Exterior2nd        0.034258    object
Exterior1st        0.034258    object
SaleType           0.034258    object
BsmtFinSF1         0.034258   float64
BsmtFinSF2         0.034258   float64
BsmtUnfSF          0.034258   float64
Electrical         0.034258    object
KitchenQual        0.034258    object
GarageCars         0.034258   float64
GarageArea         0.034258   float64
TotalBsmtSF        0.034258   float64

(3) 결측치 데이터 보간

  • 위 데이터에 순차적으로 처리하도록 한다.
  • 몇몇 분들은 PoolQC, MiscFeature와 같은 Feature는 삭제하기도 한다.
var_lists = ['PoolQC', 'MiscFeature', 'Alley', 'Fence', 'FireplaceQu']
for fea in var_lists:
  house_df[fea] = house_df[fea].fillna('None')

check_na(house_df)
결측치 데이터 컬럼과 건수:
               Missing Ratio Data Type
LotFrontage       16.649538   float64
GarageQual         5.447071    object
GarageFinish       5.447071    object
GarageYrBlt        5.447071   float64
GarageCond         5.447071    object
GarageType         5.378554    object
BsmtExposure       2.809181    object
BsmtCond           2.809181    object
BsmtQual           2.774923    object
BsmtFinType2       2.740665    object
BsmtFinType1       2.706406    object
MasVnrType         0.822199    object
MasVnrArea         0.787941   float64
MSZoning           0.137033    object
BsmtFullBath       0.068517   float64
Functional         0.068517    object
Utilities          0.068517    object
BsmtHalfBath       0.068517   float64
Exterior2nd        0.034258    object
Exterior1st        0.034258    object
SaleType           0.034258    object
BsmtFinSF1         0.034258   float64
BsmtFinSF2         0.034258   float64
TotalBsmtSF        0.034258   float64
Electrical         0.034258    object
KitchenQual        0.034258    object
GarageCars         0.034258   float64
GarageArea         0.034258   float64
BsmtUnfSF          0.034258   float64
  • LotFrontage의 데이터 typefloat64이기 때문에 median으로 처리하도록 한다.
  • 이 때 Neighborhood에 따른 median으로 지정하는 코드를 작성한다.
house_df['LotFrontage'] = house_df.groupby('Neighborhood')['LotFrontage'].transform(lambda x: x.fillna(x.median()))
check_na(house_df)
결측치 데이터 컬럼과 건수:
               Missing Ratio Data Type
GarageQual         5.447071    object
GarageFinish       5.447071    object
GarageYrBlt        5.447071   float64
GarageCond         5.447071    object
GarageType         5.378554    object
BsmtCond           2.809181    object
BsmtExposure       2.809181    object
BsmtQual           2.774923    object
BsmtFinType2       2.740665    object
BsmtFinType1       2.706406    object
MasVnrType         0.822199    object
MasVnrArea         0.787941   float64
MSZoning           0.137033    object
BsmtFullBath       0.068517   float64
BsmtHalfBath       0.068517   float64
Functional         0.068517    object
Utilities          0.068517    object
Exterior1st        0.034258    object
Exterior2nd        0.034258    object
SaleType           0.034258    object
BsmtFinSF1         0.034258   float64
BsmtFinSF2         0.034258   float64
TotalBsmtSF        0.034258   float64
Electrical         0.034258    object
KitchenQual        0.034258    object
GarageCars         0.034258   float64
GarageArea         0.034258   float64
BsmtUnfSF          0.034258   float64
  • GarageQual, GarageFinish, GarageCond, GarageType의 데이터는 object이므로 모두 None으로 처리한다.
for fea in ('GarageQual', 'GarageFinish', 'GarageCond', 'GarageType'):
  house_df[fea] = house_df[fea].fillna('None')

check_na(house_df)
결측치 데이터 컬럼과 건수:
               Missing Ratio Data Type
GarageYrBlt        5.447071   float64
BsmtCond           2.809181    object
BsmtExposure       2.809181    object
BsmtQual           2.774923    object
BsmtFinType2       2.740665    object
BsmtFinType1       2.706406    object
MasVnrType         0.822199    object
MasVnrArea         0.787941   float64
MSZoning           0.137033    object
BsmtFullBath       0.068517   float64
BsmtHalfBath       0.068517   float64
Functional         0.068517    object
Utilities          0.068517    object
TotalBsmtSF        0.034258   float64
BsmtUnfSF          0.034258   float64
BsmtFinSF2         0.034258   float64
GarageArea         0.034258   float64
BsmtFinSF1         0.034258   float64
Electrical         0.034258    object
KitchenQual        0.034258    object
GarageCars         0.034258   float64
Exterior2nd        0.034258    object
Exterior1st        0.034258    object
SaleType           0.034258    object
  • BsmtCond, BsmtExposure, BsmtQual, BsmtFinType2, BsmtFinType1, MasVnrType는 범주형 데이터이므로 모두 None으로 처리한다.
  • GarageYrBlt, MasVnrArea, BsmtFullBath, BsmtHalfBath, TotalBsmtSF, BsmtUnfSF, BsmtFinSF2, GarageArea, BsmtFinSF1는 모두 숫자형 데이터이므로 모두 0으로 처리한다.
for fea in ('BsmtCond', 'BsmtExposure', 'BsmtQual', 'BsmtFinType2', 'BsmtFinType1', 'MasVnrType'):
  house_df[fea] = house_df[fea].fillna('None')

for fea in ('GarageYrBlt', 'MasVnrArea', 'BsmtFullBath', 'BsmtHalfBath', 'TotalBsmtSF', 'BsmtUnfSF', 'BsmtFinSF2', 'GarageArea', 'BsmtFinSF1', 'GarageCars'):
  house_df[fea] = house_df[fea].fillna(0)

check_na(house_df)
결측치 데이터 컬럼과 건수:
              Missing Ratio Data Type
MSZoning          0.137033    object
Functional        0.068517    object
Utilities         0.068517    object
SaleType          0.034258    object
KitchenQual       0.034258    object
Electrical        0.034258    object
Exterior2nd       0.034258    object
Exterior1st       0.034258    object
  • 우선 Utilities 데이터는 AllPub 한개의 값만 있기 때문에 삭제한다.
house_df = house_df.drop(['Utilities'], axis = 1)
check_na(house_df)
결측치 데이터 컬럼과 건수:
              Missing Ratio Data Type
MSZoning          0.137033    object
Functional        0.068517    object
SaleType          0.034258    object
KitchenQual       0.034258    object
Electrical        0.034258    object
Exterior2nd       0.034258    object
Exterior1st       0.034258    object
  • MSZoning 내 각 데이터의 빈도수를 확인해본다.
house_df['MSZoning'].value_counts()
RL         2265
RM          460
FV          139
RH           26
C (all)      25
Name: MSZoning, dtype: int64
  • 위와 같이 RL의 빈도수가 매우 많기 때문에 RL, 즉 최빈값을 대체해서 넣도록 한다.
  • 나머지 결측치의 데이터를 위와 같이 대체해서 넣도록 한다.
for fea in ('MSZoning', 'Functional', 'SaleType', 'KitchenQual', 'Electrical', 'Exterior2nd', 'Exterior1st'):
  house_df[fea] = house_df[fea].fillna(house_df[fea].mode()[0])

check_na(house_df)
결측치 데이터 컬럼과 건수:
 Empty DataFrame
Columns: [Missing Ratio, Data Type]
Index: []

IV. 결론

  • Feature Engineering의 이론적인 개념을 배웠다.
    • 실제 각각에 대해서 깊이 배우고자 한다면, Feature Engineering 교재를 읽으시는 것을 추천한다.
  • 결측치를 채우는 방법에 대해서 배웠다
  • 그러나, 아직 여정이 더 남아 있다.