机器学习:05. 随机森林之RandomForestRegression填补缺失值

1. RandomForestRegression

所有的参数,属性与接口,全部和随机森林分类器一致。仅有的不同就是回归树与分类树的不同,不纯度的指标,参数Criterion不一致(回归是MSE,分类树是accuracy)

重要参数和接口

参数:criterion

回归树衡量分枝质量的指标:均方误差mean squared error(MSE)。。在回归树中,MSE不只是我们的分枝质量衡量指标,也是我们最常用的衡量回归树回归质量的指标。均方误差作为我们的评估指标(在分类树中这个指标是score代表的预测准确率)。虽然均方误差永远为正,但是sklearn当中使用均方误差作为评判标准时,却是计算”负均方误差“(neg_mean_squared_error)。示。真正的均方误差MSE的数值,其实就是neg_mean_squared_error去掉负号的数字。

重要属性和接口

重要属性和接口随机森林的分类器相一致。因为对于回归来说,并不存在一个样本要被分到某个类别的概率问题,因此没有predict_proba这个接口。

2 用随机森林回归填补缺失值

使用sklearn.impute.SimpleImputer来将均值,中值,或者其他最常用的数值填补到数据中。这个案例中,我们将使用均值,0,和随机森林回归来填补缺
失值,并验证四种状况下的拟合状况,找出对使用的数据集来说最佳的缺失值填补方法。
1. 导入包

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import load_boston
from sklearn.impute import SimpleImputer #impute模块中的SimpleImputer用来填补缺失值
from sklearn.ensemble import RandomForestRegressor

2. 以波士顿数据集为例,导入完整的数据集并探索

dataset = load_boston() #标签是连续性变量
dataset.data.shape
#总共506*13=6578个数据
#(506, 13)

X_full, y_full = dataset.data, dataset.target #没有缺失值
n_samples = X_full.shape[0] #样本数量506
n_features = X_full.shape[1] #特征数量13

3. 为完整数据集放入缺失值

#首先确定我们希望放入的缺失数据的比例,在这里我们假设是50%,那总共就要有3289个数据缺失
rng = np.random.RandomState(0) #确认一种随机模式,后面需要随机都用rng代替
missing_rate = 0.5
n_missing_samples = int(np.floor(n_samples * n_features * missing_rate))
#np.floor向下取整,返回.0格式的浮点数


#所有数据要随机遍布在数据集的各行各列当中,而一个缺失的数据会需要一个行索引和一个列索引
#如果能够创造一个数组,包含3289个分布在0~506中间的行索引,和3289个分布在0~13之间的列索引,那我们就可
#以利用索引来为数据中的任意3289个位置赋空值
#然后我们用0,均值和随机森林来填写这些缺失值,然后查看回归的结果如何
missing_features = rng.randint(0,n_features,n_missing_samples) #在rng的随机模式下,在0-13之间取出3289个整数
#randint(下限,上限,n) 在下限和上限之间取出n个整数
missing_samples = rng.randint(0,n_samples,n_missing_samples)


missing_features #是array的一维数组
#array([12,  5,  0, ..., 11,  0,  2])
missing_samples


X_missing = X_full.copy() #copy就是复制下
y_missing = y_full.copy() #标签不能空,要不然就是无监督学习了


X_missing[missing_samples,missing_features] = np.nan #将数据中3289个位置用空值代替
X_missing = pd.DataFrame(X_missing)
#转换成DataFrame是为了后续方便各种操作,numpy对矩阵的运算速度快到拯救人生,但是在索引等功能上却不如pandas来得好用
X_missing

4. 使用0和均值填补缺失值

#使用均值进行填补
from sklearn.impute import SimpleImputer #SimpleImputer也是一个类,所以先实例化
imp_mean = SimpleImputer(missing_values=np.nan, strategy='mean') #实例化, missing_values缺失值是nan,strategy用mean填补
X_missing_mean = imp_mean.fit_transform(X_missing) #训练fit+导出predict >>> 特殊接口 fit_transform
#fit_transform就是将X_missing代入实例化的模型训练,然后再导出
#观察是否还存在缺失值 
pd.DataFrame(X_missing_mean).isnull().sum() #isnull返回是否布尔值,在对布尔值进行加和。布尔值False =0,True=1


#使用0进行填补
imp_0 = SimpleImputer(missing_values=np.nan, strategy="constant",fill_value=0) #constant用常数0填补
X_missing_0 = imp_0.fit_transform(X_missing)
pd.DataFrame(X_missing_0).isnull().sum()

5. 使用随机森林填补缺失值

使用随机森林回归填补缺失值思想
任何回归都是从特征矩阵中学习,然后求解连续型标签y的过程,可以认为特征矩阵和标签之前存在着某种联系。实际上,标签和特征是可以相互转换的而回归填补缺失值,正是利用了这种思想。

对于一个有n个特征的数据来说,其中特征T有缺失值,我们就把特征T当作标签,其他的n-1个特征和原本的标签组成新的特征矩阵。那对于T来说,它没有缺失的部分,就是我们的Y_test,这部分数据既有标签也有特征,而它缺失的部分,只有特征没有标签,就是我们需要预测的部分。
特征T不缺失的值对应的其他n-1个特征 + 本来的标签:X_train
特征T不缺失的值:Y_train
特征T缺失的值对应的其他n-1个特征 + 本来的标签:X_test
特征T缺失的值:未知,我们需要预测的Y_test

这种做法,对于某一个特征大量缺失,其他特征却很完整的情况,非常适用。那如果数据中除了特征T之外,其他特征也有缺失值怎么办?
答案是遍历所有的特征,从缺失最少的开始进行填补(因为填补缺失最少的特征所需要的准确信息最少)。
填补一个特征时,先将其他特征的缺失值用0代替,每完成一次回归预测,就将预测值放到原本的特征矩阵中,再继续填补下一个特征。每一次填补完毕,有缺失值的特征会减少一个,所以每次循环后,需要用0来填补的特征就越来越少。当进行到最后一个特征时(这个特征应该是所有特征中缺失值最多的),已经没有任何的其他特征需要用0来进行填补了,而我们已经使用回归为其他特征填补了大量有效信息,可以用来填补缺失最多的特征。遍历所有的特征后,数据就完整,不再有缺失值了。

X_missing_reg = X_missing.copy()

#找出数据集中,缺失值从小到大排列的特征们的顺序,并且有了索引
#np.argsort返回的是从小到大排序的顺序所对应的索引
#.values将对应的索引取出来,变成一维的数组
sortindex = np.argsort(X_missing_reg.isnull().sum(axis=0)).values #axis=0按列进行加和
sortindex
#array([ 6, 12,  8,  7,  9,  0,  2,  1,  5,  4,  3, 10, 11], dtype=int64)
for i in sortindex:
    #构建我们的新特征矩阵(没有被选中去填充的特征+原始的标签)和新标签(被选中的去填充的特征)
    df = X_missing_reg #防止刚开始就把没有选中的特征的nan全部用0填充了
    fillc = df.iloc[:,i] #新标签,通过切片将选中的特征提取出来
    #新特征矩阵
    #df.iloc[:,df.columns != 6] #取出了没有6列的数据
    #y_full之前得到的是array,所以先转为dataframe,然后用pd.concat连起来
    df = pd.concat([df.iloc[:,df.columns != i],pd.DataFrame(y_full)],axis=1) #axis=1用行进行操作,连在最右边
    
    #在新特征矩阵中,对含有缺失值的列,进行0的填补
    #实例化和接口同时进行,对其补上0
    df_0 =SimpleImputer(missing_values=np.nan,strategy='constant',fill_value=0).fit_transform(df)
    
    #找出训练集和测试集
    #Y_train是被选中的特征中(现在是标签)存在的那些值,非空值
    Ytrain = fillc[fillc.notnull()] 
    #被选中的要填充的特征中不存在的那些值,是空值,虽然Ytest全部是空值,但是我们需要它的索引
    Ytest = fillc[fillc.isnull()]
    #在新特征矩阵上,被选出来的要填充的特征的非空值所对应的记录
    Xtrain = df_0[Ytrain.index,:] #就是以Ytrain的所有索引为行的列全部提取出来
    #新特征矩阵上,被选出来的要填充的特征的空值所对应的索引
    Xtest = df_0[Ytest.index,:]
    
    #用随机森林回归来填补缺失值
    rfc = RandomForestRegressor(n_estimators=100) #实例化
    rfc = rfc.fit(Xtrain, Ytrain) #导入训练集训练
    Ypredict = rfc.predict(Xtest) #用predict接口导入Xtest,得到预测结果(回归结果),就是要用来填补空值的这些值
    
    #将填补好的特征返回到我们的原始的特征矩阵中
    #loc是取出行,X_missing_reg.iloc[:,i].isnull()得到空值的索引,然后取出loc取出第6列这些索引行的值
    #X_missing_reg.loc[X_missing_reg.iloc[:,6].isnull(),6] #就是将nan全部取出来
    X_missing_reg.loc[X_missing_reg.iloc[:,i].isnull(),i] = Ypredict

X_missing_reg

6. 对填补好的数据进行建模

#对所有数据进行建模,取得MSE结果
from sklearn.model_selection import cross_val_score
X = [X_full,X_missing_mean,X_missing_0,X_missing_reg]
mse = [] #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) #*-1得到MSE

[*zip(["X_full","X_missing_mean","X_missing_0","X_missing_reg"],mse)] #用*zip将数据和mse值连接起来
回归填写后,mse的最小,说明回归填写缺失值效果很好

7. 用所得结果画出条形图

x_labels = ['Full data',
            'Zero Imputation',
            'Mean Imputation',
            'Regressor Imputation']
colors = ['r', 'g', 'b', 'orange']
plt.figure(figsize=(12, 6)) #画出画布
ax = plt.subplot(111) #添加子图:111是第一行第一列第一个表
for i in np.arange(len(mse)): #其实就是range(len(mse))
    ax.barh(i, mse[i],color=colors[i], alpha=0.6, align='center') #barh:h就是将柱状图横过来,align将条放在中间
ax.set_title('Imputation Techniques with Boston Data')
ax.set_xlim(left=np.min(mse) * 0.9,
            right=np.max(mse) * 1.1) #set_xlim:x的区间
ax.set_yticks(np.arange(len(mse))) #set_yticks :y的刻度
ax.set_xlabel('MSE')
ax.set_yticklabels(x_labels) #y轴的命名用x_labels里面的进行命名
plt.show()

Imputation Techniques with Boston Data

参考菜菜的sklearn

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342