from pprint import pprint from sklearn.ensemble import RandomForestRegressor # 随机森林回归器 from sklearn.impute import SimpleImputer # 用来填补缺失值的 import numpy as np import pandas as pd import matplotlib.pyplot as plt from sklearn.model_selection import cross_val_score from sklearn.datasets import load_boston pd.set_option('display.max_columns', None) # 以波士顿数据集为例,导入完整的数据集并探索 dataset = load_boston() # print(dataset.data.shape) # (506, 13) x_full, y_full = dataset.data, dataset.target # todo: 首先把完美的数据改成含缺失值的 n_sample = x_full.shape[0] # 获取样本数量 行 506 n_feature = x_full.shape[1] # 获取标签数量 列 13 # 我们希望的缺失数据的比例,假设为50%,共有506*13*0.5个数据缺失 rng = np.random.RandomState(0) # 确认一个随机数种子 missing_rate = 0.5 # np.floor 向下取整 返回.0的浮点数 n_missing_samples = int(np.floor(n_sample * n_feature * missing_rate)) # 数据总量/2个 # print(n_missing_samples) missing_features = rng.randint(0, n_feature, n_missing_samples) # 取出 0到nfeature范围内的n_missing_samples个随机数 missing_samples = rng.randint(0, n_sample, n_missing_samples) # 也可以抽样来完成 # missing_samples = rng.choice(dataset.data.shape[0], n_missing_samples, replace=False) # 复制一份完整的数据集,原数据不动 X_missing = x_full.copy() Y_missing = y_full.copy() # 让它遍布空值 X_missing[missing_samples, missing_features] = np.nan X_missing = pd.DataFrame(X_missing) # todo: 使用均值进行补缺 imp_mean = SimpleImputer(missing_values=np.nan, strategy="mean") # 要补啥,用啥补 # 训练加导出 fit+predict -----》特殊的接口 fit_transform X_missing_mean = imp_mean.fit_transform(X_missing) # print(pd.DataFrame(X_missing_mean).isnull().sum()) # todo: 使用0进行补缺 imp_mean0 = SimpleImputer(missing_values=np.nan, strategy="constant", fill_value=0) # 要补啥,用啥补 # 训练加导出 fit+predict -----》特殊的接口 fit_transform X_missing_0 = imp_mean0.fit_transform(X_missing) # print(pd.DataFrame(X_missing_mean)) # todo: 以上填补实际都不是很合适 # todo:使用随机森林回归填补缺失值 # 把特征不缺失的特征+原本的标签作为新的标签 # 遍历所有的特征,从缺失值最少的开始填补(因为所需要的准确信息最少) X_missing_reg = X_missing.copy() # print(X_missing_reg) # print(X_missing_reg.isnull()) # print(X_missing_reg.isnull().sum(axis=0)) # 获取按行看每列 共有多少缺失值 # 从小到大排序 # np.sort(X_missing_reg.isnull().sum(axis=0)) # todo 从小到大排序(获取对应特征索引) sortindex = np.argsort(X_missing_reg.isnull().sum(axis=0)).values # print(sortindex) ###[ 6 12 8 7 9 0 2 1 5 4 3 10 11] ## 第几行特征缺失最少,排序 # todo 构建新特征矩阵和新标签---->逐个把排序好的特征作为标签来用,其他的用作构建成新的特征矩阵 # 新标签 for i in sortindex: # 原特征之一,目前是 新标签 df = X_missing_reg fillc = df.iloc[:, i] # 新特征矩阵 # print([*df.columns]) ###可以查看所有的列索引 # print(df.iloc[:, df.columns != 6]) # 连接俩个矩阵得到新特征矩阵 df = pd.concat([df.iloc[:, df.columns != i], pd.DataFrame(y_full)], axis=1) # 在新特征矩阵中,对含有缺失值的列,进行0的填充 df_0 = SimpleImputer(missing_values=np.nan, strategy='constant', fill_value=0).fit_transform(df) # print(pd.DataFrame(df_0)) # 找出我们的训练集和测试集 # 是被选中要填充的特征中(现在是我们的标签),存在的那些值,非nan值 # print(fillc.isnull()) Y_train = fillc[fillc.notnull()] # 是被选中要填充的特征中(现在是我们的标签),不存在的那些值,为nan的空值 # 我们需要的不是Ytest,而是ytest所带的索引 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) # 用predict接口将x_test导入 ,得到我们的预测结果(回归结果),就是我们要用来填补空缺的这些值 # print(len(Ypredict)) # 将填补好的特征返回我们的原始的特征矩阵中 X_missing_reg.loc[X_missing_reg.iloc[:, i].isnull(), i] = Ypredict # print(X_missing_reg) # 目前已经有了四组数据 : 原数据,0填充的数据,均值填充的数据,回归填充的数据 # 对填充好的数据进行建模 X = [x_full, X_missing_mean, X_missing_0, X_missing_reg] mse = [] 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) # print(mse) # mse越小越好 pprint([*zip(["x_full", "X_missing_mean", "X_missing_0", "X_missing_reg"], mse)]) # [('x_full', 21.62860460743544), # ('X_missing_mean', 40.84405476955929), # ('X_missing_0', 49.50657028893417), # ('X_missing_reg', 20.907999984896122)] #########比原始数据打分都高
day 4 随机森林 回归填补缺失值
最新推荐文章于 2024-01-16 23:51:23 发布