누락 데이터 대체

Beginner

This tutorial is from open-source community. Access the source code

소개

이 실습에서는 scikit-learn 의 다양한 기법을 사용하여 데이터 세트에서 누락된 데이터를 대체하는 방법을 보여줍니다. 여기서 사용된 데이터 세트는 10 개의 특징을 가진 당뇨병 데이터 세트와 8 개의 특징을 가진 캘리포니아 주택 데이터 세트입니다. 누락된 값은 SimpleImputer 를 사용하여 평균, 중앙값 또는 가장 빈번한 값으로 대체될 수 있습니다. 이 실습에서는 상수 값으로 대체하는 방법, 각 특징의 평균 값으로 대체하고 누락 여부를 나타내는 보조 변수를 결합하는 방법, k-최근접 이웃 대체, 반복 대체와 같은 다양한 대체 기법을 조사할 것입니다.

VM 팁

VM 시작이 완료되면 왼쪽 상단 모서리를 클릭하여 Notebook 탭으로 전환하여 연습을 위한 Jupyter Notebook에 접근할 수 있습니다.

때때로 Jupyter Notebook 이 완전히 로드되기까지 몇 초 정도 기다려야 할 수 있습니다. Jupyter Notebook 의 제한으로 인해 작업의 유효성 검사는 자동화될 수 없습니다.

학습 중 문제가 발생하면 Labby 에 문의하십시오. 세션 후 피드백을 제공하면 문제를 신속하게 해결해 드리겠습니다.

데이터 다운로드 및 누락 값 세트 생성

먼저 두 데이터 세트를 다운로드합니다. 계산 속도를 높이기 위해 캘리포니아 주택 데이터 세트의 처음 400 개 항목만 사용할 것입니다. 그런 다음 일부 값을 제거하여 인위적으로 누락된 데이터가 있는 새로운 버전을 생성합니다.

import numpy as np
from sklearn.datasets import fetch_california_housing, load_diabetes

rng = np.random.RandomState(42)

X_diabetes, y_diabetes = load_diabetes(return_X_y=True)
X_california, y_california = fetch_california_housing(return_X_y=True)
X_california = X_california[:400]
y_california = y_california[:400]
X_diabetes = X_diabetes[:400]
y_diabetes = y_diabetes[:400]

def add_missing_values(X_full, y_full):
    n_samples, n_features = X_full.shape

    ## 75% 의 행에 누락 값 추가
    missing_rate = 0.75
    n_missing_samples = int(n_samples * missing_rate)

    missing_samples = np.zeros(n_samples, dtype=bool)
    missing_samples[:n_missing_samples] = True

    rng.shuffle(missing_samples)
    missing_features = rng.randint(0, n_features, n_missing_samples)
    X_missing = X_full.copy()
    X_missing[missing_samples, missing_features] = np.nan
    y_missing = y_full.copy()

    return X_missing, y_missing

X_miss_california, y_miss_california = add_missing_values(X_california, y_california)
X_miss_diabetes, y_miss_diabetes = add_missing_values(X_diabetes, y_diabetes)

누락 데이터 임퓨테이션 및 점수 계산

이제 다르게 임퓨테이션된 데이터에 대한 결과를 평가하는 함수를 작성할 것입니다. 각 임퓨테이션 방법을 개별적으로 살펴보겠습니다.

from sklearn.ensemble import RandomForestRegressor
from sklearn.experimental import enable_iterative_imputer
from sklearn.impute import SimpleImputer, KNNImputer, IterativeImputer
from sklearn.model_selection import cross_val_score
from sklearn.pipeline import make_pipeline

N_SPLITS = 4
regressor = RandomForestRegressor(random_state=0)

def get_scores_for_imputer(imputer, X_missing, y_missing):
    estimator = make_pipeline(imputer, regressor)
    impute_scores = cross_val_score(
        estimator, X_missing, y_missing, scoring="neg_mean_squared_error", cv=N_SPLITS
    )
    return impute_scores

x_labels = []

mses_california = np.zeros(5)
stds_california = np.zeros(5)
mses_diabetes = np.zeros(5)
stds_diabetes = np.zeros(5)

점수 추정

먼저, 원본 데이터에 대한 점수를 추정합니다.

def get_full_score(X_full, y_full):
    full_scores = cross_val_score(
        regressor, X_full, y_full, scoring="neg_mean_squared_error", cv=N_SPLITS
    )
    return full_scores.mean(), full_scores.std()

mses_california[0], stds_california[0] = get_full_score(X_california, y_california)
mses_diabetes[0], stds_diabetes[0] = get_full_score(X_diabetes, y_diabetes)
x_labels.append("Full data")

누락 값을 0 으로 대체

이제 누락된 값을 0 으로 대체한 데이터에 대한 점수를 추정합니다.

def get_impute_zero_score(X_missing, y_missing):
    imputer = SimpleImputer(
        missing_values=np.nan, add_indicator=True, strategy="constant", fill_value=0
    )
    zero_impute_scores = get_scores_for_imputer(imputer, X_missing, y_missing)
    return zero_impute_scores.mean(), zero_impute_scores.std()

mses_california[1], stds_california[1] = get_impute_zero_score(
    X_miss_california, y_miss_california
)
mses_diabetes[1], stds_diabetes[1] = get_impute_zero_score(
    X_miss_diabetes, y_miss_diabetes
)
x_labels.append("Zero imputation")

누락 값의 KNN-대체

KNNImputer 는 원하는 수의 가장 가까운 이웃의 가중 또는 비가중 평균을 사용하여 누락된 값을 대체합니다.

def get_impute_knn_score(X_missing, y_missing):
    imputer = KNNImputer(missing_values=np.nan, add_indicator=True)
    knn_impute_scores = get_scores_for_imputer(imputer, X_missing, y_missing)
    return knn_impute_scores.mean(), knn_impute_scores.std()

mses_california[2], stds_california[2] = get_impute_knn_score(
    X_miss_california, y_miss_california
)
mses_diabetes[2], stds_diabetes[2] = get_impute_knn_score(
    X_miss_diabetes, y_miss_diabetes
)
x_labels.append("KNN Imputation")

평균으로 누락 값 채우기

def get_impute_mean(X_missing, y_missing):
    imputer = SimpleImputer(missing_values=np.nan, strategy="mean", add_indicator=True)
    mean_impute_scores = get_scores_for_imputer(imputer, X_missing, y_missing)
    return mean_impute_scores.mean(), mean_impute_scores.std()

mses_california[3], stds_california[3] = get_impute_mean(
    X_miss_california, y_miss_california
)
mses_diabetes[3], stds_diabetes[3] = get_impute_mean(X_miss_diabetes, y_miss_diabetes)
x_labels.append("Mean Imputation")

누락 값의 반복적 대체

다른 옵션으로는 IterativeImputer 가 있습니다. 이 방법은 순환 선형 회귀를 사용하여 누락된 값이 있는 각 특징을 다른 특징의 함수로 차례로 모델링합니다. 구현된 버전은 가우시안 (출력) 변수를 가정합니다. 특징이 명백하게 비정규 분포인 경우 성능을 개선하기 위해 정규 분포에 가깝도록 변환하는 것을 고려하십시오.

def get_impute_iterative(X_missing, y_missing):
    imputer = IterativeImputer(
        missing_values=np.nan,
        add_indicator=True,
        random_state=0,
        n_nearest_features=3,
        max_iter=1,
        sample_posterior=True,
    )
    iterative_impute_scores = get_scores_for_imputer(imputer, X_missing, y_missing)
    return iterative_impute_scores.mean(), iterative_impute_scores.std()

mses_california[4], stds_california[4] = get_impute_iterative(
    X_miss_california, y_miss_california
)
mses_diabetes[4], stds_diabetes[4] = get_impute_iterative(
    X_miss_diabetes, y_miss_diabetes
)
x_labels.append("Iterative Imputation")

mses_diabetes = mses_diabetes * -1
mses_california = mses_california * -1

결과 플롯

마지막으로, 점수를 시각화할 것입니다.

n_bars = len(mses_diabetes)
xval = np.arange(n_bars)

colors = ["r", "g", "b", "orange", "black"]

## diabetes 데이터 결과 플롯
plt.figure(figsize=(12, 6))
ax1 = plt.subplot(121)
for j in xval:
    ax1.barh(
        j,
        mses_diabetes[j],
        xerr=stds_diabetes[j],
        color=colors[j],
        alpha=0.6,
        align="center",
    )

ax1.set_title("Diabetes 데이터의 누락값 대체 기법")
ax1.set_xlim(left=np.min(mses_diabetes) * 0.9, right=np.max(mses_diabetes) * 1.1)
ax1.set_yticks(xval)
ax1.set_xlabel("MSE")
ax1.invert_yaxis()
ax1.set_yticklabels(x_labels)

## california 데이터셋 결과 플롯
ax2 = plt.subplot(122)
for j in xval:
    ax2.barh(
        j,
        mses_california[j],
        xerr=stds_california[j],
        color=colors[j],
        alpha=0.6,
        align="center",
    )

ax2.set_title("California 데이터의 누락값 대체 기법")
ax2.set_yticks(xval)
ax2.set_xlabel("MSE")
ax2.invert_yaxis()
ax2.set_yticklabels([""] * n_bars)

plt.show()

요약

이 실습에서는 scikit-learn 의 다양한 기법을 사용하여 데이터셋에서 누락된 데이터를 대체하는 방법을 보여줍니다. 캘리포니아 주택 데이터셋과 당뇨병 데이터셋을 사용하여 상수 값으로 대체, 각 특징의 평균값으로 대체하고 누락 여부를 나타내는 보조 변수를 결합한 방법, k-최근접 이웃 대체, 반복적 대체와 같은 다양한 기법을 구현했습니다. 또한 막대 그래프를 사용하여 점수를 시각화했습니다.