特征工程-数据预处理

1探索性数据分析

数据使用的是:皮马印第安人糖尿病预测数据集
链接:https://pan.baidu.com/s/17M7UfnqGYTkpLmCXUOyTkw
提取码:y4fz

import pandas as pd
pima_column_names = ['times_pregnant', 'plasma_glucose_concentration',
                     'diastolic_blood_pressure', 'triceps_thickness',
                     'serum_insulin', 'bmi', 'pedigree_function',
                     'age', 'onset_diabetes']
pima = pd.read_csv('./data/pima.data', names=pima_column_names)
  1. times_pregnant:怀孕次数;
  2. plasma_glucose_concentration:口服葡萄糖耐量试验中的2小时血浆葡萄糖浓度;
  3. diastolic_blood_pressure:舒张压(mmHg);
  4. triceps_thickness:三头肌皮褶厚度(mm);
  5. serum_insulin:2小时血清胰岛素浓度(μU/ml);
  6. bmi:体重指数(BMI,c);
  7. pedigree_function:糖尿病家族函数;
  8. age:年龄(岁);
  9. onset_diabetes:标签(0或1,代表无或有糖尿病)。
pima['onset_diabetes'].value_counts(normalize=True)

00.65104210.34895

65%的人没有糖尿病

空准确率是指当模型总是预测频率较高的类别时达到的正确率

空准确率是不经过训练模型,直接把所有的数据预测成类别数量最多的那个类(此列中即是0:不患糖尿病)
如果我们训练出的模型准确率不到65%也就是空准确率,那么可以说我们的模型是几乎没有价值的。

2 探究不同类别样本的血糖浓度

我们可以查看不同类别样本的各项特征对比
口服葡萄糖耐量试验中的2小时血浆葡萄糖浓度
在这里插入图片描述

import matplotlib.pyplot as plt
col = 'plasma_glucose_concentration'
plt.hist(pima[pima['onset_diabetes'] == 0][col], 10, alpha=0.5, label='non-diabetes')
plt.hist(pima[pima['onset_diabetes'] == 1][col], 10, alpha=0.5, label='diabetes')
plt.legend(loc='upper right')
plt.xlabel(col)
plt.ylabel('Frequency')
plt.title('Histogram of {}'.format(col))
plt.grid()

几种异常的直方图分布(除1外)
在这里插入图片描述可以看出画出的图属于7孤岛型存在数据异常,而且也能看出正常人的血糖浓度在75-125,而糖尿病患者在100-175.说明根据血糖浓度是可以在一定程度上鉴别是否患糖尿病。
类似可以画出体重指数(bmi)舒张压( diastolic_blood_pressure )
在这里插入图片描述

3.缺失值探索

缺失值所带来的问题
1大部分机器学习算法不能处理缺失值
2信息缺失

pima.isnull().sum()

在这里插入图片描述看起来好像是没有缺失值,但也有可能是缺失值已经用0进行填充过了,所以接下来进行进一步的探索

# 真的没有缺失值吗
pima.describe()

在这里插入图片描述
根据常识bmi和血糖浓度不可能为0
以下列的最小值都是0:

  1. times_pregnant:怀孕次数;
  2. plasma_glucose_concentration:口服葡萄糖耐量试验中的2小时血浆葡萄糖浓度;
  3. diastolic_blood_pressure:舒张压(mmHg);
  4. triceps_thickness:三头肌皮褶厚度(mm);
  5. serum_insulin:2小时血清胰岛素浓度(μU/ml);
  6. bmi:体重指数(BMI,即体重(kg)除以身高(m)的平方);
  7. onset_diabetes:标签(0或1,代表无或有糖尿病)

也许原始数据集中缺失或不存在的值都用0填充了!

标签列和怀孕次数有可能为0,其他列则不可能出现取值为0的情况,故下列字段原本是存在缺失值的!

  1. plasma_glucose_concentration:口服葡萄糖耐量试验中的2小时血浆葡萄糖浓度;
  2. diastolic_blood_pressure:舒张压(mmHg);
  3. triceps_thickness:三头肌皮褶厚度(mm);
  4. serum_insulin:2小时血清胰岛素浓度(μU/ml);
  5. bmi:体重指数(BMI,即体重(kg)除以身高(m)的平方)。

所以对以上列中的0进行替换,替换成缺失值

# 用None对上述列中的0进行替换,以达到数据原本状态的效果
columns = ['serum_insulin', 'bmi', 'plasma_glucose_concentration', 'diastolic_blood_pressure', 'triceps_thickness']
for colu in columns:
    pima[colu].replace([0], [None], inplace=True)
pima.isnull().sum()

在这里插入图片描述

4.删除缺失值

处理缺失值

1.删除缺失值
2 对缺失值进行填充

可以看看在不同的处理下模型的性能()
首先是删除缺失值

pima_dropped = pima.dropna()
pima_dropped.shape

在这里插入图片描述原始数据是(768, 9),直接删除丢失了不少样本
然后看一下删除前后样本数据分布的变化

(pima_dropped.mean() - pima.mean())/pima.mean()

在这里插入图片描述在这里插入图片描述times_pregnant(怀孕次数)的均值下降了14% pedigree_function(糖尿病血系功能)上升了11%
删除样本会严重影响数据的形状,所以应该保留尽可能多的数据。

我们如何知道直接删除效果怎样,可以通过模型的性能进行评估

5构建基线模型

from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import cross_val_score
X_dropped = pima_dropped.drop('onset_diabetes', axis=1)
y_dropped = pima_dropped['onset_diabetes']
knn=KNeighborsClassifier(n_neighbors=3)
cross_val_score(knn,X_dropped,y_dropped,cv=5).mean()

在这里插入图片描述

6.网格优化

我们在设置参数时并不知道参数设为多少为最合适,比如刚才的n_neighbors,cv,我们可能很容易想到循环

for k in range(1, 8):
    for cv in range(2,5):
        knn = KNeighborsClassifier(n_neighbors=k)
        accuracy = cross_val_score(knn, X_dropped, y_dropped, cv=5).mean()
        print(accuracy)

但是当参数多于三个呢?其实sklearn中有网格搜索的接口可以调用,网格搜索(顾名思义枚举每一种组合就像网格一样)
在这种比较简单的模型中可以使用网格搜索,但是建模比赛,XGboost和lightGBM这些不推荐网格搜索,可以试试随机搜索和贝叶斯搜索,下面是sklearn中网格搜索接口调用

from sklearn.model_selection import GridSearchCV
knn_params = {'n_neighbors': [1, 2, 3, 4, 5, 6, 7]}
grid = GridSearchCV(KNeighborsClassifier(), knn_params)
grid.fit(X_dropped, y_dropped)
grid.best_estimator_   # 模型参数
grid.best_score_    # 模型性能基线

在这里插入图片描述

7.用0/均值填充缺失值

用0填充缺失值其实就是最开始获得的那份公开数据集

pima_fill_zero = pima.fillna(0)
X_fill_zero = pima_fill_zero.drop('onset_diabetes', axis=1)
y_fill_zero = pima_fill_zero['onset_diabetes']
grid_zero = GridSearchCV(KNeighborsClassifier(), knn_params)
grid_zero.fit(X_fill_zero, y_fill_zero)
grid_zero.best_score_

在这里插入图片描述除了用0填充还可以用均值填充或者插补填充

from sklearn.impute import SimpleImputer
pima_fill_mean = SimpleImputer(strategy='mean').fit_transform(pima)
X_fill_mean = pima_fill_mean[:, :-1]
y_fill_mean = pima_fill_mean[:, -1]
grid_mean = GridSearchCV(KNeighborsClassifier(), knn_params)
grid_mean.fit(X_fill_mean, y_fill_mean)
grid_mean.best_score_

在这里插入图片描述除了对数据缺失值进行填充还可以进行数据标注化提升模型

8.标准化和归一化介绍

 数据标准化是而在多指标评价体系中,由于各评价指标的性质不同,通常具有不同的量纲和数量级。当各指标间的水平相差很大时,如果直接用原始指标值进行分析,就会突出数值较高的指标在综合分析中的作用,相对削弱数值水平较低指标的作用。因此,为了保证结果的可靠性,需要对原始指标数据进行标准化处理
标准化的作用
提升模型性能;加速学习效率
常用标准化方法
1 Z分数标准化/特征标准化/方差缩放; 标准差标准化
2 min-max标准化/min-max缩放 (映射到[0,1]区间之间)
3 行归一化。
前两种是对列,最后一种是对行
1.Z分数标准化
通过缩放特征、统一化均值和方差(标准差的平方) Ø Z分数标准化的输出会被重新缩放,使均值为0、标准差为1。 标准化和归一化 Z分数标准化
z=(x-u)/σ

2min-max标准化和Z分数标准化类似,因为它也用一个公式替换列中的每个值。
这两种方法的使用介绍
3.行归一化
这个标准化方法是关于行的。行归一化不是计算每列的统计值(均值、最小值、最大值等),而是会保证每 行有单位范数(unit norm),意味着每行的向量长度相同。
x = ( x 1 , x 2 , x 3 . . . . . x n ) x=(x_1,x_2,x_3.....x_n) x=(x1,x2,x3.....xn)
||x|| = ( x 1 2 + x 2 2 + . . . . . x n 2 ) 2 =\sqrt[2]{(x_1^2+x_2^2+.....x_n^2)} =2(x12+x22+.....xn2)
X_new=x/||x||

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()# 行归一化后矩阵的平均范数

当然不是所有的模型都受量纲的影响
受尺度影响的算法
1KNN:因为依赖欧几里得距离;
2均值聚类:和KNN的原因一样;
3逻辑回归、支持向量机、神经网络:如果使用梯度下降来学习权重;
4主成分分析:特征向量将偏向较大的列。

9.结合机器学习流水线进一步优化

随着后续工作的推进模型要做的处理越来越多,我们可以把这些过程都放到管道里。

from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler, MinMaxScaler
X = pima.drop('onset_diabetes', axis=1)
y = pima['onset_diabetes']
pipeline = Pipeline(steps=[('imputer', SimpleImputer()), ('standardize', MinMaxScaler()), ('classify', KNeighborsClassifier())])  # 填充使用SimpleImputer,标准化使用MinMaxScaler,模型分类使用KNN
pipeline_params = {'imputer__strategy': ['mean', 'median'], 'classify__n_neighbors': [1, 2, 3, 4, 5, 6, 7]}   # 参数表
grid_pipeline = GridSearchCV(pipeline, pipeline_params)
grid_pipeline.fit(X, y)
grid_pipeline.best_estimator_, grid_pipeline.best_score_

在这里插入图片描述注意放到Pipeline里的对象必须要有fit,fit_transform方法
注意参数表中参数格式,步骤名__参数,比如imputer中的strategy参数设置imputer__strategy

10小结

识别缺失值
处理缺失值(删除、0填充、统计值填充)
数据标准化
机器学习流水线
在这里插入图片描述
具体使用什么方式处理缺失值,要经过尝试才知道

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

开始King

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值