特征工程-使用随机森林进行缺失值填补

一、前言

特征工程在传统的机器学习中是非常重要的一个步骤,我们对机器学习算法的优化通常是有限的。如果在完成任务时发现不管怎么优化算法得到的结果都不满意,这个时候就可以考虑回头在做一下特征工程。

二、缺失值填补

在特征工程中,对缺失值的处理是很常见的一个问题。处理方法通常如下:

  1. 删除有缺省值的数据
  2. 使用数据中该特征的均值填充缺失值
  3. 使用数据中该特征的中位数填充缺失值
  4. 使用数据中该特征的众数填充缺失值
  5. 使用机器学习模型对缺失值进行填充

上面的方法各有有点,我们可以根据自己的需求来选择策略。在数据集比较大时,最后一种方式是综合表现比较好的。今天我们就来讲讲使用随机森林来进行缺失值的填补。

三、数据预处理

3.1、处理思路

在外面开始填充数据前,我们还需要对原本的数据进行一些简单的处理。假如我们现在要对下面的数据进行填充:

name sex age target
zack male 20 1
rudy male 30 1
alice female 20 0
atom male 31 0
alex female 32 1
kerry female 0
king 20 1
nyx male 20 1
petty female 0

在使用scikit-learn创建随机森林时,不允许我们训练数据的特征值为字符串,因此我们要对name、gender、city这几列进行处理,这里采取one-hot编码的策略。

注意:上面是我捏造的一些数据,至于target是什么含义我也不知道。

首先name特征在很多情况下都不会影响最后的结果,因此我们直接选择删除name特征。然后是gender和city特征,他们都是类型特征,对于gender我们可以用0代表male、用1代表female。而city是多分类的特征,我们也可以采取和gender一样的方法,0代表city_01、1代表city_02、2代表city_03。不过这样会导致city特征权重不一样,如果类别太多对结果会有很大影响。

这个时候我们就可以换一个策略,我们可以把原本的city特征拆分成三个特征,分别是city=city_01、city=city_02、city=city_03,然后特征值只有0或一,这样就可以解决上面的问题了。

比如我们原始数据如下:

name gender age city target
zack male 21 city_01 1
alice female 22 city_02 0

进行转换后数据如下(忽略name特征):

name gender=male gender=female age city=city_01 city=city_02 city=city_03 target
zack 1 0 21 1 0 0 1
alice 0 1 22 0 1 0 0

在上面我们还有个city=city_03特征,这是因为我们要考虑整个数据集进行拆分。

这里还需要注意一点,就是gender特征可以不这样拆分,这里为了方便就不另外对gender用另外的策略了。

3.2、代码实现

根据上面的思路,我们知道了如何处理多分类的特征。而对于数字特征,我们不需要进行额外处理,因此我们需要遍历特征的列,然后判断是否是我们要处理的列。具体代码如下:

import numpy as np
import pandas as pd
from sklearn.feature_extraction import DictVectorizer# 创建DictVectorizer
dv = DictVectorizer(sparse=False)
# 读取数据
df = pd.read_csv("test.csv")
# 删除name列
df = df.drop(['name'], axis=1)
# 裁剪出特征值
X = df.iloc[:, 0:-1]# 遍历特征值的列
for colum in X.iteritems():# 对非数值型列进行处理(多类别数据)if colum[1].dtype == np.object_:# 拆分出列名和数据feature_name, data = colum# ①、将该列转换成字典colum = data.map(lambda x: {feature_name: x})colum = dv.fit_transform(colum)# 多分类特征名转换后的特征名,如gender->[gender=male, gender=female]features = dv.get_feature_names_out()# 将新创建的列添加进去X[features] = colum# 删除当前列X = X.drop([feature_name], axis=1)# ②、如果原先值是空,则吧所以新添加的列设置为nanif list(features).__contains__(feature_name):features = list(features)features.remove(feature_name)features = np.array(features)# 对于特征值是null的数据,转换后的各个特征也应为null# 如:gender为null,那gender=male为null,gender=female为nullmask = X[features].sum(axis=1) == 0X.loc[mask, features] = np.nan

对于大部分代码,相信读者都能理解。这里来解释下代码中①、②两个部分。

3.3、代码解析

(1)问题①

在①处我们将当前列的数据转换成了字典,然后再调用DictVectorizer对象的fit_transform方法,我们直接看DictVectorizer的作用。来看下面这段代码:

from sklearn.feature_extraction import DictVectorizer
# 待处理字典列表
data = [{"gender": "male"},{"gender": "female"},{"gender": "unknow"},{"gender": "male"},{"gender": "male"}
]
dv = DictVectorizer(sparse=False)
# 转换数据
data = dv.fit_transform(data)
print(dv.get_feature_names_out())
print(data)

上面代码输出如下:

['gender=female' 'gender=male' 'gender=unknow']
[[0. 1. 0.][1. 0. 0.][0. 0. 1.][0. 1. 0.][0. 1. 0.]]

可以看到,这个和我们上面思路提到的转换是一样的。因为dv接收的是字典序列,因此我们需要先使用下面代码:

colum = data.map(lambda x: {feature_name: x})

这样就可以将当前列转换成字典序列类型。然后调用dv.fit_transform就可以实现转换。

(2)问题②

这部分代码是为了让原本gender为nan的数据转换后gender=female和gender=male也应为nan。但是对于存在缺失值的数据,转换过程中会出现下面的问题:

from sklearn.feature_extraction import DictVectorizer
data = [{"gender": "male"},{"gender": "female"},{"gender": "unknow"},{"gender": "male"},{"gender": None}
]
dv = DictVectorizer(sparse=False)
data = dv.fit_transform(data)
print(dv.get_feature_names_out())
print(data)

上面我们添加了一个带有缺失值的数据,输出结果如下:

['gender' 'gender=female' 'gender=male' 'gender=unknow']
[[ 0.  0.  1.  0.][ 0.  1.  0.  0.][ 0.  0.  0.  1.][ 0.  0.  1.  0.][nan  0.  0.  0.]]

可以发现,我们原本只期望有三列,但是却出现了四列。因此我们需要将dv.get_feature_names_out()中的多余列删除。

到处,我们的数据就处理完了。下面我们可以使用随机森林来填补缺失值。

四、使用随机森林填补缺失值

4.1、实现思路

填补缺失值的过程就是不断建立模型预测的过程。我们还是来看一组简单的数据:

height weight age
181 70 20
178 18
160 50
170 60 19

上面的数据有两个特征存在缺失值,我们都需要进行填充。当我们要填充weight时,我们可以考虑选取weight不为空的数据。然后将其余列作为特征值,而weight作为目标值。这样我们就可以训练出一个可以预测weight的模型。

但是上面的方法有个问题,就是我们选取的是weight不为空的数据,但是这些数据的其它特征可能为空。这个时候我们就可以考虑用其它简单方法先对其余缺失值进行填充,然后训练模型填充weight的缺失值。

在填补weight的缺失值后,再用同样的方法来填补其余有缺失值的特征。

为了效果好,我们会有限选择填补缺失值数量少的列,因为这样我们就可以拿到较多的数据,可以更好地填充该列地数据。然后依次类推。

4.2、代码实现

这部分是在实现上面对多分类的处理后进行的,完整代码如下:

y = df.iloc[:, [-1]]# 按照当前列缺失值的数量进行升序排列
sortindex = np.argsort(X.isnull().sum(axis=0)).values #axis=0按列进行加和
for i in sortindex:# 将当前列作为目标值feature_i = X.iloc[:, i]# 将其余列作为特征值(包括目标值)tmp_df = pd.concat([X.iloc[:, X.columns != i], y], axis=1)# 使用众数填充其余列缺失值imp_mf = SimpleImputer(missing_values=np.nan, strategy='most_frequent')tmp_df_mf = imp_mf.fit_transform(tmp_df)# 将feature_i中非空的样本作为训练数据y_notnull = feature_i[feature_i.notnull()]y_null = feature_i[feature_i.isnull()]   X_notnull = tmp_df_mf[y_notnull.index, :]X_null = tmp_df_mf[y_null.index, :] # 如果没有缺失值则填充下一列if y_null.shape[0] == 0:continue# 建立随机森林回归树进行训练rfc = RandomForestRegressor(n_estimators=100)rfc = rfc.fit(X_notnull, y_notnull)# 对缺失值进行预测y_predict = rfc.predict(X_null)# 填充缺失值X.loc[X.iloc[:, i].isnull(), X.columns[i]] = y_predict

这样我们就实现了随机森林填充缺失值的操作。完整代码如下:

import numpy as np
import pandas as pd
from sklearn.ensemble import RandomForestRegressor
from sklearn.feature_extraction import DictVectorizer
from sklearn.impute import SimpleImputerdv = DictVectorizer(sparse=False)
df = pd.read_csv("test.csv")
name = df['name']
df = df.drop(['name'], axis=1)
X = df.iloc[:, 0:-1]# 遍历数据的列
for colum in X.iteritems():# 对非数值型列进行处理if colum[1].dtype == np.object_:# 拆分出列名和数据feature_name, data = colum# 将该列转换成字典colum = data.map(lambda x: {feature_name: x})colum = dv.fit_transform(colum)features = dv.get_feature_names_out()# 将新创建的列添加进去X[features] = colum# 删除当前列X = X.drop([feature_name], axis=1)# 如果原先值是空,则吧所以新添加的列设置为nanif list(features).__contains__(feature_name):features = list(features)features.remove(feature_name)features = np.array(features)mask = X[features].sum(axis=1) == 0X.loc[mask, features] = np.nany = df.iloc[:, [-1]]# 按照当前列缺失值的数量进行升序排列
sortindex = np.argsort(X.isnull().sum(axis=0)).values
for i in sortindex:# 将当前列作为目标值feature_i = X.iloc[:, i]# 将其余列作为特征值(包括目标值)tmp_df = pd.concat([X.iloc[:, X.columns != i], y], axis=1)# 使用众数填充其余列缺失值imp_mf = SimpleImputer(missing_values=np.nan, strategy='most_frequent')  tmp_df_mf = imp_mf.fit_transform(tmp_df)# 将feature_i中非空的样本作为训练数据y_notnull = feature_i[feature_i.notnull()]  y_null = feature_i[feature_i.isnull()]   X_notnull = tmp_df_mf[y_notnull.index, :]  X_null = tmp_df_mf[y_null.index, :] # 如果没有缺失值则下一列if y_null.shape[0] == 0:continue# 建立随机森林回归树进行训练rfc = RandomForestRegressor(n_estimators=100)rfc = rfc.fit(X_notnull, y_notnull)# 对缺失值进行预测y_predict = rfc.predict(X_null)# 填充缺失值X.loc[X.iloc[:, i].isnull(), X.columns[i]] = y_predict

今天的内容就是这些,更多内容可以关注“新建文件夹X”。

特征工程-使用随机森林进行缺失值填补相关推荐

  1. 随机森林计算特征重要性_随机森林中计算特征重要性的3种方法

    随机森林计算特征重要性 The feature importance describes which features are relevant. It can help with a better ...

  2. 各维度 特征 重要程度 随机森林_机器学习算法——随机森林

    随机森林简介 随机森林是一种通用的机器学习方法,能够处理回归和分类问题.它还负责数据降维.缺失值处理.离群值处理以及数据分析的其他步骤.它是一种集成学习方法,将一组一般的模型组合成一个强大的模型 工作 ...

  3. 特征筛选(随机森林)

    参考:http://blog.csdn.net/zjuPeco/article/details/77371645?locationNum=7&fps=1 一般情况下,数据集的特征成百上千,因此 ...

  4. 机器学习第20篇 - 基于Boruta选择的特征变量构建随机森林

    前面机器学习第18篇 - Boruta特征变量筛选(2)已经完成了特征变量筛选,下面看下基于筛选的特征变量构建的模型准确性怎样? 定义一个函数生成一些列用来测试的mtry (一系列不大于总变量数的数值 ...

  5. 随机森林筛选特征Matlab,特征筛选(随机森林)

    随机森林能够度量每个特征的重要性,我们可以依据这个重要性指标进而选择最重要的特征.sklearn中已经实现了用随机森林评估特征重要性,在训练好随机森林模型后,直接调用feature_importanc ...

  6. 如何筛选特征?用随机森林(RF)

    向AI转型的程序员都关注了这个号

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

    使用随机森林进行缺失值填补的思想: X和y之间是有联系的,所以才能用X预测y;那么反过来,y也可以在一定程度上预测X. 当X中的某个特征x有缺失值时,我们将该特征看为target,y看作一个新特征(即 ...

  8. 五、实例:在波士顿房价数据集上用随机森林回归填补缺失值

    在波士顿房价数据集上用随机森林回归填补缺失值 点击标题即可获取源代码和笔记 一.引入 我们从现实中收集的数据,几乎不可能是完美无缺的,往往都会有一些缺失值.面对缺失值,很多人选择的方式是直接将含有缺失 ...

  9. 利用随机森林填补缺失值

    利用随机森林填补缺失值 介绍 利用随机森林填补缺失值 介绍 说到缺失值,我想各位在进行数据分析之前或多或少都是会遇到的.在做有关机器学习的项目的时候,出题人都是会给你一个好几万好几十万的数据,可能会出 ...

最新文章

  1. java log4j mysql_java – log4j:MySQL的JDBCAppender错误
  2. 谷歌新智能体Dreamer将亮相NeurIPS 2019,数据效率比前身PlaNet快8个小时
  3. 有关 AI 人才的 6 个真相
  4. Rails用DELETE method提交表单讲解
  5. IGNN图卷积超分网络:挖掘隐藏在低分辨率图像中的高清纹理
  6. mysql5.7复制集_技术分享 | 克隆:更优雅的创建 MySQL 实例副本
  7. CCF201512试题
  8. form表单会跨域_我的Vue不小心跨域了o()o 干它
  9. 最近公共祖先 解题报告
  10. Linux中在终端启动anaconda
  11. 研究学习时用到的软件
  12. 【软考软件评测师】2011年下案例分析历年真题
  13. easyui模版html,EasyUI 模板(Template)_Vue EasyUI Demo
  14. DB2 改变日期格式
  15. 小游戏学习--获取已发布微信小游戏源码 creator cocos 编译出微信平台代码 喵喵切水果 跑酷
  16. 用友NC单据模板公式
  17. 深度学习理论——特征提取算法
  18. iPhone 开发常用工具
  19. “高定美学”品牌矩阵:「莲玉芳华」「琢我」「佐我」佐我气运系列之进击
  20. WeUI+移动端照片上传、显示、预览、下载功能

热门文章

  1. md5sum命令的灵活运用
  2. Excel受保护的工作表怎么操作?
  3. Redis的集群配置
  4. 数据清洗的一般方法和步骤
  5. 推荐一个好用的OKR工具
  6. 自动驾驶落地,究竟被什么「绑」住了脚?
  7. Java实现TCP的长短链接
  8. 定点数一位乘法之Booth(布斯)算法
  9. 【opencv】Camshift目标跟踪
  10. 强化学习 (Reinforcement Learning)