Spec-Zone.ru › scikit-learn

Примечание

Перейти в конец, чтобы скачать полный код примера или запустить этот пример в браузере с помощью JupyterLite или Binder.

Заполнение пропущенных значений перед построением оценщика

Пропущенные значения можно заменить средним, медианой или наиболее часто встречающимся значением с помощью базового SimpleImputer.

В этом примере мы рассмотрим различные методы заполнения пропущенных значений:

  • заполнение постоянным значением 0
  • заполнение средним значением каждого признака
  • заполнение методом k ближайших соседей
  • итеративное заполнение

Во всех случаях для каждого признака мы добавляем новый признак, указывающий на наличие пропущенных значений.

Мы будем использовать два набора данных: набор данных Diabetes, состоящий из 10 признаков, собранных у пациентов с диабетом для прогнозирования прогрессирования заболевания, и набор данных California housing, целевым значением которого является медианная стоимость домов в округах Калифорнии.

Поскольку в этих наборах данных нет пропущенных значений, мы удалим некоторые значения, чтобы создать новые версии с искусственно внесенными пропусками. Затем сравним качество работы RandomForestRegressor на исходном наборе данных и на измененных наборах данных, в которых искусственно внесенные пропущенные значения заполнены разными методами.

# Authors: The scikit-learn developers
# SPDX-License-Identifier: BSD-3-Clause

Загрузка данных и создание наборов с пропущенными значениями

Сначала загрузим два набора данных. Набор данных Diabetes входит в состав scikit-learn. Он содержит 442 записи, в каждой из которых 10 признаков. Набор данных California housing значительно больше: 20640 записей и 8 признаков. Его необходимо скачать. Для ускорения вычислений мы будем использовать только первые 300 записей, но вы можете использовать весь набор данных.

import numpy as np

from sklearn.datasets import fetch_california_housing, load_diabetes

X_diabetes, y_diabetes = load_diabetes(return_X_y=True)
X_california, y_california = fetch_california_housing(return_X_y=True)

X_diabetes = X_diabetes[:300]
y_diabetes = y_diabetes[:300]
X_california = X_california[:300]
y_california = y_california[:300]


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

    # Add missing values in 75% of the lines
    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


rng = np.random.RandomState(42)
X_miss_diabetes, y_miss_diabetes = add_missing_values(X_diabetes, y_diabetes, rng)
X_miss_california, y_miss_california = add_missing_values(
    X_california, y_california, rng
)

Заполнение пропущенных данных и оценка качества

Теперь напишем функцию для оценки результатов на данных, заполненных разными методами, а также на полном наборе данных без заполнения пропусков. Для регрессии целевого значения мы будем использовать RandomForestRegressor.

from sklearn.ensemble import RandomForestRegressor

# To use the experimental IterativeImputer, we need to explicitly ask for it:
from sklearn.experimental import enable_iterative_imputer  # noqa: F401
from sklearn.impute import IterativeImputer, KNNImputer, SimpleImputer
from sklearn.model_selection import cross_val_score
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import RobustScaler

N_SPLITS = 4


def get_score(X, y, imputer=None):
    regressor = RandomForestRegressor(random_state=0)
    if imputer is not None:
        estimator = make_pipeline(imputer, regressor)
    else:
        estimator = regressor
    scores = cross_val_score(
        estimator, X, y, scoring="neg_mean_squared_error", cv=N_SPLITS
    )
    return scores.mean(), scores.std()


x_labels = []

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

Оценка качества

Сначала оценим качество на исходных данных:

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

Замена пропущенных значений на 0

Теперь оценим качество на данных, в которых пропущенные значения заменены на 0:

imputer = SimpleImputer(strategy="constant", fill_value=0, add_indicator=True)
mses_diabetes[1], stds_diabetes[1] = get_score(
    X_miss_diabetes, y_miss_diabetes, imputer
)
mses_california[1], stds_california[1] = get_score(
    X_miss_california, y_miss_california, imputer
)
x_labels.append("Zero Imputation")

Заполнение пропущенных значений средним

imputer = SimpleImputer(strategy="mean", add_indicator=True)
mses_diabetes[2], stds_diabetes[2] = get_score(
    X_miss_diabetes, y_miss_diabetes, imputer
)
mses_california[2], stds_california[2] = get_score(
    X_miss_california, y_miss_california, imputer
)
x_labels.append("Mean Imputation")

Заполнение пропущенных значений методом k ближайших соседей

KNNImputer заполняет пропущенные значения взвешенным или невзвешенным средним заданного числа ближайших соседей. Если признаки имеют сильно различающиеся масштабы (как в наборе данных California housing), рассмотрите возможность их масштабирования, чтобы потенциально улучшить качество.

imputer = KNNImputer(add_indicator=True)
mses_diabetes[3], stds_diabetes[3] = get_score(
    X_miss_diabetes, y_miss_diabetes, imputer
)
mses_california[3], stds_california[3] = get_score(
    X_miss_california, y_miss_california, make_pipeline(RobustScaler(), imputer)
)
x_labels.append("KNN Imputation")

Итеративное заполнение пропущенных значений

Еще один вариант — IterativeImputer. Этот метод использует циклическую регрессию, по очереди моделируя каждый признак с пропущенными значениями как функцию других признаков. Для прогнозирования пропущенных значений признаков мы используем регрессионную модель, выбранную по умолчанию в классе (BayesianRidge). Сильно различающиеся масштабы признаков могут отрицательно сказаться на качестве прогнозирования, поэтому мы масштабируем признаки в наборе данных California housing.

imputer = IterativeImputer(add_indicator=True)

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

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

Визуализация результатов

Наконец, визуализируем качество:

import matplotlib.pyplot as plt

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

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

# plot diabetes results
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("Imputation Techniques with Diabetes Data")
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)

# plot california dataset results
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("Imputation Techniques with California Data")
ax2.set_yticks(xval)
ax2.set_xlabel("MSE")
ax2.invert_yaxis()
ax2.set_yticklabels([""] * n_bars)

plt.show()
Imputation Techniques with Diabetes Data, Imputation Techniques with California Data

Вы также можете попробовать другие методы. Например, медиана — более устойчивый оценщик для данных с переменными большой величины, которые могут доминировать в результатах (это также называют «тяжелым хвостом»).

Общее время выполнения скрипта: (0 минут 8.572 секунды)

Launch binder
Launch JupyterLite

Download Jupyter notebook: plot_missing_values.ipynb

Download Python source code: plot_missing_values.py

Download zipped: plot_missing_values.zip

Связанные примеры

Заполнение пропущенных значений с помощью вариантов IterativeImputer

Основные нововведения scikit-learn 0.22

Анализ влияния типа априорного распределения концентрации на вариационную гауссову смесь Байеса

Основные нововведения scikit-learn 1.5

© 2007–2026 The scikit-learn developers
Licensed under the 3-clause BSD License.
https://scikit-learn.org/1.9/auto_examples/impute/plot_missing_values.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API