2013-07-09 17:12:17 +08:00
|
|
|
"""
|
2018-04-16 16:18:29 +08:00
|
|
|
====================================================
|
2013-07-09 17:12:17 +08:00
|
|
|
Imputing missing values before building an estimator
|
2018-04-16 16:18:29 +08:00
|
|
|
====================================================
|
2013-07-09 17:12:17 +08:00
|
|
|
|
2018-07-18 03:45:36 +08:00
|
|
|
This example shows that imputing the missing values can give better
|
|
|
|
|
results than discarding the samples containing any missing value.
|
|
|
|
|
Imputing does not always improve the predictions, so please check via
|
|
|
|
|
cross-validation. Sometimes dropping rows or using marker values is
|
|
|
|
|
more effective.
|
|
|
|
|
|
2013-07-28 15:03:56 +08:00
|
|
|
Missing values can be replaced by the mean, the median or the most frequent
|
2018-07-17 03:22:13 +08:00
|
|
|
value using the basic :func:`sklearn.impute.SimpleImputer`.
|
2014-11-30 22:31:22 +08:00
|
|
|
The median is a more robust estimator for data with high magnitude variables
|
|
|
|
|
which could dominate results (otherwise known as a 'long tail').
|
2013-07-09 17:12:17 +08:00
|
|
|
|
2018-07-17 03:22:13 +08:00
|
|
|
In addition of using an imputing method, we can also keep an indication of the
|
|
|
|
|
missing information using :func:`sklearn.impute.MissingIndicator` which might
|
|
|
|
|
carry some information.
|
2013-07-09 17:12:17 +08:00
|
|
|
"""
|
|
|
|
|
import numpy as np
|
2018-04-16 16:18:29 +08:00
|
|
|
import matplotlib.pyplot as plt
|
2013-07-09 17:12:17 +08:00
|
|
|
|
2018-04-16 16:18:29 +08:00
|
|
|
from sklearn.datasets import load_diabetes
|
2013-07-09 17:12:17 +08:00
|
|
|
from sklearn.datasets import load_boston
|
|
|
|
|
from sklearn.ensemble import RandomForestRegressor
|
2018-07-17 03:22:13 +08:00
|
|
|
from sklearn.pipeline import make_pipeline, make_union
|
2018-07-18 03:45:36 +08:00
|
|
|
from sklearn.impute import SimpleImputer, MissingIndicator
|
2015-09-11 02:26:39 +08:00
|
|
|
from sklearn.model_selection import cross_val_score
|
2013-07-09 17:12:17 +08:00
|
|
|
|
|
|
|
|
rng = np.random.RandomState(0)
|
|
|
|
|
|
2018-04-16 16:18:29 +08:00
|
|
|
|
|
|
|
|
def get_results(dataset):
|
|
|
|
|
X_full, y_full = dataset.data, dataset.target
|
|
|
|
|
n_samples = X_full.shape[0]
|
|
|
|
|
n_features = X_full.shape[1]
|
|
|
|
|
|
|
|
|
|
# Estimate the score on the entire dataset, with no missing values
|
|
|
|
|
estimator = RandomForestRegressor(random_state=0, n_estimators=100)
|
|
|
|
|
full_scores = cross_val_score(estimator, X_full, y_full,
|
2018-08-21 03:22:42 +08:00
|
|
|
scoring='neg_mean_squared_error', cv=5)
|
2018-04-16 16:18:29 +08:00
|
|
|
|
|
|
|
|
# Add missing values in 75% of the lines
|
|
|
|
|
missing_rate = 0.75
|
|
|
|
|
n_missing_samples = int(np.floor(n_samples * missing_rate))
|
|
|
|
|
missing_samples = np.hstack((np.zeros(n_samples - n_missing_samples,
|
|
|
|
|
dtype=np.bool),
|
|
|
|
|
np.ones(n_missing_samples,
|
|
|
|
|
dtype=np.bool)))
|
|
|
|
|
rng.shuffle(missing_samples)
|
|
|
|
|
missing_features = rng.randint(0, n_features, n_missing_samples)
|
|
|
|
|
|
|
|
|
|
# Estimate the score after replacing missing values by 0
|
|
|
|
|
X_missing = X_full.copy()
|
|
|
|
|
X_missing[np.where(missing_samples)[0], missing_features] = 0
|
|
|
|
|
y_missing = y_full.copy()
|
|
|
|
|
estimator = RandomForestRegressor(random_state=0, n_estimators=100)
|
|
|
|
|
zero_impute_scores = cross_val_score(estimator, X_missing, y_missing,
|
2018-08-21 03:22:42 +08:00
|
|
|
scoring='neg_mean_squared_error',
|
|
|
|
|
cv=5)
|
2018-04-16 16:18:29 +08:00
|
|
|
|
|
|
|
|
# Estimate the score after imputation (mean strategy) of the missing values
|
|
|
|
|
X_missing = X_full.copy()
|
|
|
|
|
X_missing[np.where(missing_samples)[0], missing_features] = 0
|
|
|
|
|
y_missing = y_full.copy()
|
2018-07-17 03:22:13 +08:00
|
|
|
estimator = make_pipeline(
|
|
|
|
|
make_union(SimpleImputer(missing_values=0, strategy="mean"),
|
|
|
|
|
MissingIndicator(missing_values=0)),
|
|
|
|
|
RandomForestRegressor(random_state=0, n_estimators=100))
|
2018-04-16 16:18:29 +08:00
|
|
|
mean_impute_scores = cross_val_score(estimator, X_missing, y_missing,
|
2018-08-21 03:22:42 +08:00
|
|
|
scoring='neg_mean_squared_error',
|
|
|
|
|
cv=5)
|
2018-04-16 16:18:29 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
return ((full_scores.mean(), full_scores.std()),
|
|
|
|
|
(zero_impute_scores.mean(), zero_impute_scores.std()),
|
2018-07-18 03:45:36 +08:00
|
|
|
(mean_impute_scores.mean(), mean_impute_scores.std()))
|
2018-04-16 16:18:29 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
results_diabetes = np.array(get_results(load_diabetes()))
|
|
|
|
|
mses_diabetes = results_diabetes[:, 0] * -1
|
|
|
|
|
stds_diabetes = results_diabetes[:, 1]
|
|
|
|
|
|
|
|
|
|
results_boston = np.array(get_results(load_boston()))
|
|
|
|
|
mses_boston = results_boston[:, 0] * -1
|
|
|
|
|
stds_boston = results_boston[:, 1]
|
|
|
|
|
|
|
|
|
|
n_bars = len(mses_diabetes)
|
|
|
|
|
xval = np.arange(n_bars)
|
|
|
|
|
|
|
|
|
|
x_labels = ['Full data',
|
|
|
|
|
'Zero imputation',
|
2018-07-18 03:45:36 +08:00
|
|
|
'Mean Imputation']
|
2018-04-16 16:18:29 +08:00
|
|
|
colors = ['r', 'g', 'b', 'orange']
|
|
|
|
|
|
|
|
|
|
# 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')
|
|
|
|
|
|
2018-06-14 14:41:38 +08:00
|
|
|
ax1.set_title('Imputation Techniques with Diabetes Data')
|
2018-04-16 16:18:29 +08:00
|
|
|
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 boston results
|
|
|
|
|
ax2 = plt.subplot(122)
|
|
|
|
|
for j in xval:
|
|
|
|
|
ax2.barh(j, mses_boston[j], xerr=stds_boston[j],
|
|
|
|
|
color=colors[j], alpha=0.6, align='center')
|
|
|
|
|
|
2018-06-14 14:41:38 +08:00
|
|
|
ax2.set_title('Imputation Techniques with Boston Data')
|
2018-04-16 16:18:29 +08:00
|
|
|
ax2.set_yticks(xval)
|
|
|
|
|
ax2.set_xlabel('MSE')
|
|
|
|
|
ax2.invert_yaxis()
|
|
|
|
|
ax2.set_yticklabels([''] * n_bars)
|
|
|
|
|
|
|
|
|
|
plt.show()
|