【特征工程与实践】【特征增强:清洗数据】

识别数据中的缺失值

本章只处理定量特征,因为目前没有足够工具处理缺失的定性特征,特征构建那一章会解决这个问题。

当获得一份数据集时,首先进行探索性分析,之后本书就对皮马印第安人糖尿病预测数据集进行EDA,画了一些直方图分析属性与目标值的关系,同时绘制相关矩阵,查看相关性系数。

开始查看缺失值

  1. 使用下面代码,查看是否有空的值
data.isnull().sum()
  1. 查看shape,确定行数与列数,还有确定一下空准确率
data.shape
data['asd'].value_counts(normalize=True)
  1. 描述性统计
data.describe()

可以发现有些不合理的值,例如BMI最小值是0,这是违背事实的,可能是数据中缺失或不存在的点。

有些列如怀孕次数为0,是很正常的,可以补充为0.

  1. 必须尽可能了解数据集,以便找到更好的符号填充缺失数据

处理缺失值的方法

  1. 删除缺失值的行
  2. 填充缺失值
  • 先把0换成None,可以让fillna和dropna正常工作
data['asd']=data['asd'].map(lambda x:x if x!=0 else None)

对全部列操作
for col in columns:
	data[col].replace([0],[None],inplace=True)

通过这个方法,可以更准确地分析缺失数据,describe方法是不会对有缺失值的列进行统计

删除有害的行

data_dropped=data.dropna()
# 查看删除了多少行
num_rows_lost = round(100*(data.shape[0]-data_dropped.shape[0])/float(data.shape[0]))

print('retained {}% of rows'.format(num_rows_lost))

要留意删除了多少的行,例子中删除了整整一半的数据,这样说明我们没有尽可能的利用多点的数据,所以可以进行抛弃缺失值前后的比较。

对value_counts()的比较
对均值的比较,data.mean() , data_dropped.mean()
# 均值变化百分比
(pima_dropped.mean() - pima.mean()) / pima.mean()

# 均值变化百分比条形图
ax = ((pima_dropped.mean() - pima.mean()) / pima.mean()).plot(kind='bar', title='%
change in average column values')
ax.set_ylabel('% change')

可以看到有部门的列的均值在删除缺失值后变化比较大,即影响了数据的形状,所以应该保留尽可能多的数据

填充缺失值

采用fillna(填补值,Inplace=true)
对每个列都做有点麻烦,sklearn有个预处理类Imputer模块,我们称其为“填充器”

from sklearn.preprocessing import Imputer
imputer = Imputer(strategy='mean')   实例化对象
data_imputed = imputer.fit_transform(data) 此输出为numpy数组
'我们需要转换为dataframe'
data_imputed = pd.DataFrame(data_imputed,columns=data_column_names)

流水线上的填充缺失值(pipeline和Imputer)

from sklearn.pipeline import Pipeline
knn_params = {'classify_n_neighbors':[1,2,3,4,5,6,7]}
knn =  KNeighborsClassifier()
mean_impute = Pipeline([('imputer',Imputer(strategy='mean')),('classify',knn)])

X = data.drop('onsert_diabetes',axis=1) #这是目标值
y = data['onsert_diabetes']

grid = GridSearchCV(mean_impute,knn_params)
grid.fit(X,y)

print(grid.best_score_,grid.best_params_)

案例中,发现删除缺失值的行数的准确率比用0、均值、中位数填充还要高,但是我们希望利用所有行的数据实现类似的性能,所以引入了标准化和归一化

标准化和归一化

采用标准直方图,查看所有列的分布情况,注意到每列的均值、最小值、最大值、标准差的差别很大,我们也可以通过describe函数查看,数据尺度的差距会影响到一些机器学习模型的,例如身高在150~190,但年龄在20 ~ 80之间,算法无法达到最有状态,我们可以通过直方图的sharex和sharey参数,在同一比例下查看每个图表。

data_imputed_mean.hist(figsize=(15,15),sharex=True)

在这里插入图片描述

  • 归一化是为了将行和列对齐并转化为一致的规则,通常是将定量列转化为同一个静态范围的值,如(0,1),或者按照一些数学规则,如所有列的均值和标准差必须相同

z-score标准化

利用z分数思想,使均值为0,标准差为1,让KNN这类模型达到最优状态,而不会倾向于较大比例的特征。

z = ( x − μ ) / σ z=(x-\mu)/\sigma z=(xμ)/σ

scaler = StandardScaler()
z_score = scaler.fit_transform(data[['asd']])
#这里采用双括号,因为转换需要一个dataframe

min-max标准化

m = ( x − x m i n ) / ( x m a x − x m i n ) m=(x-x_{min}) / (x_{max}-x_{min}) m=(xxmin)/(xmaxxmin)
此公式可以把所有值都会位于0 ~ 1

from sklearn.preprocessing import MinMaxScaler
# 实例化
min_max = MinMaxScaler()
# 使用min-max 标准化
pima_min_maxed = pd.DataFrame(min_max.fit_transform(pima_imputed),
columns=pima_column_names)

这种转换的副作用是标准差会非常小,不利于个别模型,因为异常值权重降低了

行归一化

保证每行有单位范数(unit norm),即每行的向量长度相同,我们认为每行数据都在一个n维空间中,每行都有一个向量范数(长度),计算方法是:
∣ ∣ x ∣ ∣ = x 1 2 + x 1 2 + . . . + x n 2 ||x|| = \sqrt{{x_1}^2+{x_1}^2+...+{x_n}^2} x=x12+x12+...+xn2
这是L2范数,暂时不提及其他类型范数,我们关心要每行都有相同范数

np.sqrt((pima_imputed**2).sum(axis=1)).mean()
# 归一化之前的矩阵的平均范数
223.36222025823744

#归一化之后的范数
from sklearn.preprocessing import Normalizer # 行归一化
normalize = Normalizer()
pima_normalized = pd.DataFrame(normalize.fit_transform(pima_imputed),
columns=pima_column_names)

np.sqrt((pima_normalized**2).sum(axis=1)).mean()
# 行归一化后矩阵的平均范数
1.0

受尺度影响的一些算法

  • KNN,依赖于欧几里得距离
  • K-mean,依赖欧几里得距离
  • 逻辑回归、svm、神经网络,若使用梯度下降来学习权重
  • PCA,特征向量将偏向于较大的列
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值