用随机森林填补缺失值

这里呢,首先将波士顿数据进行填空,然后在对含有空值的数据进行,0、均值、随机森林回归填充,并比较其好坏,并以图像视之。

首先导入所需要的库

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import load_boston#数据集
from sklearn.impute import SimpleImputer#填补缺失的类
from sklearn.ensemble import RandomForestRegressor

获取数据,并查看数据

dataset = load_boston()#数据
dataset.data.shape#查看数据结构

随机森林预测缺失值 随机森林 缺失值_随机森林预测缺失值


确定样本和标签数量

n_samples = x_full.shape[0]#样本数量
n_features = x_full.shape[1]#标签数量

确定缺失值

#首先确定我们希望放入的缺失值数据的比例,在这里我们假设是50%,那就要有3289个数据缺失

rng = np.random.RandomState(0)
missing_rate = 0.5
n_missing_samples = int(np.floor(n_samples * n_features *missing_rate))

取出将赋值为空值的索引

#np.floor  向下取整 
#所有数据要随机遍布在数据集的各行各列当中,而一个确实的数据会需要一盒行索引和一个列索引
#如果能够创造一个数组,就可以利用索引来赋空值

#用0,均值,随机森林来填写这些缺失值,然后查看这些回归结果
missing_features = rng.randint(0,n_features,n_missing_samples)
missing_samples =rng.randint(0,n_samples,n_missing_samples)

#randint(上限,下限,n) 请在下限和上限之间取出n个整数

#我们现在采样了3289个数据,远远超过了我们的样本量,所以可以使用随机抽取的函数randint

将数据赋值为nan

#但是如果我们的数据量小于我们的样本量506,那我们可以采用np.random.choice,choice会随机抽取不重复的随机数
##因此可以帮助我们让数据更加分散,确保数据不会集中在一些行中

x_missing = x_full.copy()
y_missing = y_full.copy()
x_missing[missing_samples,missing_features] = np.nan
x_missing = pd.DataFrame(x_missing)

#转换成DataFrame时为了后面方便操作,索引方便

随机森林预测缺失值 随机森林 缺失值_numpy_02


使用均值填补缺失值

#均值
from sklearn.impute import SimpleImputer
imp_mean = SimpleImputer(missing_values=np.nan,strategy='mean')
x_missing_mean = imp_mean.fit_transform(x_missing)
#训练fit+导出predict >>> 特殊的接口fit_transform

pd.DataFrame(x_missing_mean).isnull().sum()#查看缺失值

随机森林预测缺失值 随机森林 缺失值_python_03


使用 0 填补缺失值

#使用0进行填补
imp_0 = SimpleImputer(missing_values=np.nan,strategy="constant",fill_value=0)#censtant 常数
x_missing_0 = imp_0.fit_transform(x_missing)

pd.DataFrame(x_missing_0).isnull().sum()#查看缺失值

随机森林预测缺失值 随机森林 缺失值_机器学习_04


#使用随机森林填充

x_missing_reg = x_missing.copy()
sortindex = np.argsort(x_missing_reg.isnull().sum(axis=0)).values
#用argsort 排序可以返回索引位置


for i in sortindex:
    #构建我们的新特征矩阵(没有被选中去填充的特征+原始的标签)和新标签(被选中去填充的特征)
    df = x_missing_reg
    fillc = df.iloc[:,i]
    df = pd.concat([df[df != fillc],pd.DataFrame(y_full)])
    
    #在新特征矩阵中,对含有缺失值的列,进行0的填补
    df_0 = SimpleImputer(missing_values=np.nan
                        ,strategy = "constant"
                        ,fill_value = 0
                        ).fit_transform(df)
    
    #找出我们的训练集和测试集
    y_train = fillc[fillc.notnull()]#是被选中要填充的值,存在的那些值,非空值
    y_test = fillc[fillc.isnull()]#是被选中 的要填充给的值,不存在的那些值,是空值
    x_train = df_0[y_train.index,:]#在新特征矩阵中,我们需要非空值所对应的的索引
    x_test = df_0[y_test.index,:]#空值所对应的记录
    
    #用随机森林回归来填补缺失值
    rfc = RandomForestRegressor(n_estimators=100)#实例化
    rfc = rfc.fit(x_train,y_train)  #导入训练集去进行训练
    Ypredict = rfc.predict(x_test)#用oredicr接口将x_TEST,就是我们要填补空值的这些值
    
    #将填补号的特征返回到我们的原始的特征矩阵中
    x_missing_reg.loc[x_missing_reg.iloc[:,i].isnull(),i] = Ypredict

随机森林预测缺失值 随机森林 缺失值_过拟合_05


随机森林预测缺失值 随机森林 缺失值_过拟合_06


对填充好的数据进行建模

from sklearn.model_selection import cross_val_score
x = [x_full,X_missing_mean,x_missing_0,x_missing_reg]
 
mse = []
std = []
for x in x:
    estimator = RandomForestRegressor(random_state=0, n_estimators=100)#实例化
    scores = cross_val_score(estimator,x,y_full,scoring='neg_mean_squared_error', cv=5).mean()
    mse.append(scores * -1)
[*zip(['Full data','Zero Imputation','Mean Imputation','Regressor Imputation'],mse)]

随机森林预测缺失值 随机森林 缺失值_numpy_07

将结果用图的形式展现出来

#画图
x_labels = ['Full data',
            'Zero Imputation',
            'Mean Imputation',
            'Regressor Imputation']
colors = ['r', 'g', 'b', 'orange']
 
plt.figure(figsize=(12, 6))#画出画布
ax = plt.subplot(111)#添加子图
for i in np.arange(len(mse)):
    ax.barh(i, mse[i],color=colors[i], alpha=0.6, align='center')#bar为条形图,barh为横向条形图,alpha表示条的粗度
ax.set_title('Imputation Techniques with Boston Data')
ax.set_xlim(left=np.min(mse) * 0.9,
             right=np.max(mse) * 1.1)#设置x轴取值范围
ax.set_yticks(np.arange(len(mse)))
ax.set_xlabel('MSE')
ax.set_yticklabels(x_labels)
plt.show()

随机森林预测缺失值 随机森林 缺失值_随机森林预测缺失值_08

由此可见随机森林最小,说明效果好,比源数据拟合程度逗号,但是最小不一定是最好的,容易过拟合。