Imputação de Dados Ausentes

Beginner

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

Introdução

Este laboratório demonstra como imputar dados ausentes em um conjunto de dados usando diferentes técnicas no scikit-learn. Os conjuntos de dados usados aqui são o conjunto de dados de diabetes com 10 recursos e o conjunto de dados de habitação da Califórnia com 8 recursos. Os valores ausentes podem ser substituídos pela média, mediana ou valor mais frequente usando SimpleImputer. Este laboratório investigará diferentes técnicas de imputação, como imputação por valor constante, imputação pelo valor médio de cada recurso combinado com uma variável auxiliar de indicador de ausência, imputação pelo k vizinho mais próximo e imputação iterativa.

Dicas da Máquina Virtual

Após o término da inicialização da máquina virtual, clique no canto superior esquerdo para mudar para a aba Notebook para acessar o Jupyter Notebook para praticar.

Às vezes, pode ser necessário aguardar alguns segundos para que o Jupyter Notebook termine de carregar. A validação das operações não pode ser automatizada devido a limitações no Jupyter Notebook.

Se você enfrentar problemas durante o aprendizado, sinta-se à vontade para perguntar ao Labby. Forneça feedback após a sessão e resolveremos prontamente o problema para você.

Baixar Dados e Criar Conjuntos com Valores Ausentes

Primeiro, os dois conjuntos de dados são baixados. Usaremos apenas as primeiras 400 entradas do conjunto de dados de habitação da Califórnia para acelerar os cálculos. Em seguida, removeremos alguns valores para criar novas versões com dados artificialmente ausentes.

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

    ## Adicionar valores ausentes em 75% das linhas
    taxa_ausencia = 0.75
    n_amostras_ausentes = int(n_samples * taxa_ausencia)

    amostras_ausentes = np.zeros(n_samples, dtype=bool)
    amostras_ausentes[:n_amostras_ausentes] = True

    rng.shuffle(amostras_ausentes)
    recursos_ausentes = rng.randint(0, n_features, n_amostras_ausentes)
    X_missing = X_full.copy()
    X_missing[amostras_ausentes, recursos_ausentes] = 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)

Imputar Dados Ausentes e Avaliar Desempenho

Agora, escreveremos uma função que avaliará os resultados em dados imputados de forma diferente. Vamos analisar cada imputador separadamente:

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)

Estimar a Pontuação

Primeiro, queremos estimar a pontuação nos dados originais:

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("Dados completos")

Substituir Valores Ausentes por 0

Agora, vamos estimar a pontuação nos dados onde os valores ausentes foram substituídos por 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("Imputação por zero")

Imputação KNN dos Valores Ausentes

A imputação KNN preenche valores ausentes usando a média ponderada ou não ponderada do número desejado de vizinhos mais próximos.

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("Imputação KNN")

Imputar Valores Ausentes com a Média

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("Imputação pela Média")

Imputação Iterativa dos Valores Ausentes

Outra opção é o IterativeImputer. Este método utiliza regressão linear em rodízio, modelando cada característica com valores ausentes como uma função de outras características, por sua vez. A versão implementada assume variáveis gaussianas (de saída). Se as suas características forem obviamente não normais, considere transformá-las para parecerem mais normais, para potencialmente melhorar o desempenho.

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("Imputação Iterativa")

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

Plotar os Resultados

Finalmente, vamos visualizar a pontuação:

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

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

## plotar resultados de 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("Técnicas de Imputação com Dados de 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)

## plotar resultados do conjunto de dados da Califórnia
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("Técnicas de Imputação com Dados da Califórnia")
ax2.set_yticks(xval)
ax2.set_xlabel("MSE")
ax2.invert_yaxis()
ax2.set_yticklabels([""] * n_bars)

plt.show()

Resumo

Este laboratório demonstra como imputar dados ausentes em um conjunto de dados usando diferentes técnicas no scikit-learn. Usamos o conjunto de dados de habitação da Califórnia e o conjunto de dados de diabetes para implementar diferentes técnicas, como imputação por valor constante, imputação pela média de cada característica combinada com uma variável auxiliar indicadora de ausência de dados, imputação por k vizinhos mais próximos e imputação iterativa. Também visualizamos as pontuações usando gráficos de barras.