ML/Articles

7 Ways to Handle Missing Values in Machine Learning

a292run 2021. 3. 2. 08:36
반응형

원본 링크



7 Ways to Handle Missing Values in Machine Learning

데이터셋에서 손실값을 다루는 유명한 전략들

실제 데이터는 많은 손실값(missing value)를 갖는다. 손실값의 원인은 데이터 변질 또는 데이터 기록 실패가 될 수 있다. 손실값 처리는 많은 머신러닝 알고리즘이 손실값을 지원하지 않기 때문에 데이터의 전처리 동안 매우 중요하다.

이 글은 데이터셋에서 손실값을 다루는 7가지 방법에 대해 다룬다.

  1. Deleting Rows with missing values (손실값을 포함하는 열 삭제)
  2. Impute missing values for continuous variable (연속형 변수에 대한 손실값 대체)
  3. Impute missing values for categorical variable (범주형 변수에 대한 손실값 대체)
  4. Other Imputation Methods (다른 대체 방법들)
  5. Using Algorithms that support missing values (손실값을 지원하는 알고리즘 사용)
  6. Prediction of missing values (손실값 예측_
  7. Imputation using Deep Learning Library — Datawig (딥러닝 라이브러리(Datawig)를 사용한 대체)

데이터는 캐글의 타이타닉 데이터셋(titanic dataset)을 사용한다.
titanic.zip


data = pd.read_csv("train.csv")
msno.matrix(data)


(Image by Author), Visualization of Missing Values: white lines denote the presence of missing value



Delete Rows with Missing Values:

손실값은 null 값을 갖는 열(row) 또는 행(column)을 삭제하여 처리할 수 있다. 행이 열의 절반이상을 null로 가지고 있다면 전체 컬럼을 뺄 수 있다. 하나이상의 컬럼값이 null인 열 또한 뺄 수 있다.


(Image by Author) Left: Data with Null values, Right: Data after removal of Null values

Pros:

  • 모든 손실값이 제거되어 훈련된 모델은 견고한 모델을 생성한다.

Cons:

  • 많은 정보의 손실
  • 손실값의 비율이 전체 데이터셋 대비 과도하다면 제대로 동작하지 않는다.



Impute missing values with Mean/Median: (평균/중간값으로 대체)

수치형 연속 값을 갖는 데이터셋에서 컬럼은 컬럼에서 남은 값의 평균(mean), 중간값(median) 또는 최빈값(mode)으로 대체될 수 있다. 이 방법은 앞선 방법(데이터 삭제)에 비해 데이터의 손실을 막을 수 있다. 위의 두 근사치(평균, 중간값)로의 대체는 손실값을 다루기 위한 통계적인 접근 방법이다.


(Image by Author) Left: Age column before Imputation, Right: Age column after imputation by the mean value

위 예제에서 손실값은 평균값으로 대체되었다. 동일한 방법으로 중간값으로 대체될 수도 있다.


data["Age"] = data["Age"].replace(np.NaN, data["Age"].mean())
data["Age"] = data["Age"].replace(np.NaN, data["Age"].median())


Pros:

  • 열 또는 컬럼의 삭제로 이어지는 데이터 손실을 방지
  • 작은 데이터셋으로도 잘 동작하고 구현이 쉽다.

Cons:

  • 오로지 수치형 연속 변수에서만 동작
  • 데이터 누출을 일으킬 수 있음
  • 특성간 공분산을 고려하지 않음.



Imputation method for categorical columns: (범주형 대체)

손실값이 범주형 컬럼이라면 손실값은 가장 빈번한 범주로 대체될 수 있다. 만약 손실값의 수가 매우 크다면 새로운 범주로 대체될 수도 있다.


(Image by Author) Left: Data before Imputation, Right: Cabin column after imputation by ‘U’

Pros:

  • 열 또는 컬럼의 삭제로 이어지는 데이터 손실을 방지
  • 작은 데이터셋으로도 잘 동작하고 구현이 쉽다.
  • 유일한 범주를 추가하여 데이터의 손실을 무효화 한다.

Cons:

  • 오직 범주형 변수에서만 동작
  • 인코딩동안 모델에 새로운 특성의 추가는 나쁜 성능으로 이어질 수 있다.



Other Imputation Methods:

데이터의 본질 또는 데이터 형태에 따라 몇몇 다른 대체 방법이 손실값을 대체는데 더 적합할 수 있다.

예를 들면, 세로방향(경도)의 행동을 하는 데이터 변수에 대해서는 손실값을 채우기 위해 마지막 유효한 관측을 사용하는 것이 타당할 수 있다. 이 방법이 LOCF(Last Observation Carried Forward) 방법이다.


data["Age"] = data["Age"].fillna(method='ffill')

시간 연속적인 데이터셋 변수에 대해서는 손실 데이터에 대한 타임스탬프 전후에 보간법을 사용하는 것이 타당하다.


data["Age"] = data["Age"].interpolate(method='linear', limit_direction='forward', axis=0)



Using Algorithms that support missing values:

모든 머신러닝 알고리즘이 손실값을 지원하는 것은 아니지만 몇몇 ML 알고리즘은 데이터셋내 손실값에 견고하다. K-NN 알고리즘은 값이 없을 때 거리 측정에서 열을 무시할 수 있다. 나이브 베이즈(Naive Bayes) 또한 예측할 때 손실값을 지원할 수 있다. 이러한 알고리즘은 데이터셋이 null 또는 손실값을 포함할때 사용할 수 있다.

파이썬에서 나이브 베이즈와 K-NN의 sklearn 구현은 손실값의 존재를 지원하지 않는다.

여기서 사용할 수 있는 또 다른 알고리즘은 비선형과 범주형 데이터에서 잘 동작하는 랜덤포레스트(random forest)이다. 이 알고리즘은 높은 분산(high variance) 또는 편향(bias) 고려를 포함하여 데이터 구조에 적응한다. 그래서 대규모 데이터셋에서 더 나은 결과를 보인다.


Pros:

  • ML 알고리즘이 효과적으로 손실값을 처리하기 때문에 각 컬럼내 손실값을 처리할 필요가 없다.

Cons:

  • sckikit-learn 라이브러리에서 이러한 ML 알고리즘의 구현이 없다.



Prediction of missing values:

손실값을 처리하는 앞선 방법에서는 손실값과 다른 변수를 포함하는 변수의 상관관계 이점을 사용하지 않는다. null을 갖지않는 다른 특성을 사용하는 것은 손실값 예측에 사용될 수 있다.

회귀 또는 분류 모델은 손실값을 갖는 특성의 본질(범주형 또는 연속형)에 따라 손실값 예측에 사용될 수 있다.


Here 'Age' column contains missing values so for prediction of null values the spliting of data will be,

y_train: rows from data["Age"] with non null values
y_test: rows from data["Age"] with null values
X_train: Dataset except data["Age"] features with non null values
X_test: Dataset except data["Age"] features with null values


from sklearn.linear_model import LinearRegression
import pandas as pd

data = pd.read_csv("train.csv")
data = data[["Survived", "Pclass", "Sex", "SibSp", "Parch", "Fare", "Age"]]

data["Sex"] = [1 if x=="male" else 0 for x in data["Sex"]]

test_data = data[data["Age"].isnull()]
data.dropna(inplace=True)

y_train = data["Age"]
X_train = data.drop("Age", axis=1)
X_test = test_data.drop("Age", axis=1)

model = LinearRegression()
model.fit(X_train, y_train)

y_pred = model.predict(X_test)


Pros:

  • 앞선 방법보다 더 나은 결과를 보인다.
  • 손실값 컬럼과 다른 컬럼간 공분산을 고려한다.

Cons:

  • 단지 참값(true value)에 대한 대리값(proxy)로써만 고려된다.



Imputation using Deep Learning Library — Datawig

이 방법은 범주형(categorical), 연속형(continuous), 숫자가 아닌 특성(non-numerical feature)에서 매우 잘 동작한다. Datawig는 데이터그램(datagram)에서 손실값을 대체하기 위해 심층신경망(DNN)을 사용하여 ML 모델을 학습한 라이브러리이다.


# Install datawig library,
pip3 install datawig

Datawig는 dataframe을 취할 수 있고 손실값이 있는 각 컬럼을 위해 다른 모든 컬럼을 입력으로 대체 모델을 맞출 수 있다.(fit)

아래 코드는 Age 컬럼에서 손실값을 대체하는 코드이다.


import pandas as pd
pip install datawig
import datawig

data = pd.read_csv("train.csv")

df_train, df_test = datawig.utils.random_split(data)

#Initialize a SimpleImputer model
imputer = datawig.SimpleImputer(
    input_columns=['Pclass','SibSp','Parch'], # column(s) containing information about the column we want to impute
    output_column= 'Age', # the column we'd like to impute values for
    output_path = 'imputer_model' # stores model data and metrics
    )

#Fit an imputer model on the train data
imputer.fit(train_df=df_train, num_epochs=50)

#Impute missing values and return original dataframe with predictions
imputed = imputer.predict(df_test)


Pros:

  • 다른 방법 대비 꽤 정확하다.
  • CPU와 GPU를 지원한다.

Cons:

  • 대규모 데이터셋에서 꽤 느려질 수 있다.



Conclusion

모든 데이터셋은 견고한 모델을 만들기 위해 현명하게 처리되어야 하는 손실값이 있다. 이 글에서는 컬럼 모든 형태에서 손실값을 처리할 수 있는 7가지 방법을 다뤘다. 특정 방식으로 손실값을 처리하는 원칙은 없고 최고의 성능을 갖는 견고한 모델을 얻는 것이 방법이다. 누군가는 데이터가 무엇을 어떻게에 따라 다른 특성으로 다양한 방법을 사용할 수 있다. 데이터셋에 대한 도메인 지식을 갖는 것도 중요하다. 이것은 어떻게 데이터를 처리하고 손실값을 다룰지에 대한 통찰력을 줄 수 있다.



References:

[1] Datawig: https://github.com/awslabs/datawig

반응형