赞
踩
数据使用的是:皮马印第安人糖尿病预测数据集
链接: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)
pima['onset_diabetes'].value_counts(normalize=True)
65%的人没有糖尿病
空准确率是指当模型总是预测频率较高的类别时达到的正确率
空准确率是不经过训练模型,直接把所有的数据预测成类别数量最多的那个类(此列中即是0:不患糖尿病)
如果我们训练出的模型准确率不到65%也就是空准确率,那么可以说我们的模型是几乎没有价值的。
我们可以查看不同类别样本的各项特征对比
口服葡萄糖耐量试验中的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 )
缺失值所带来的问题
1大部分机器学习算法不能处理缺失值
2信息缺失
pima.isnull().sum()
看起来好像是没有缺失值,但也有可能是缺失值已经用0进行填充过了,所以接下来进行进一步的探索
# 真的没有缺失值吗
pima.describe()
根据常识bmi和血糖浓度不可能为0
以下列的最小值都是0:
也许原始数据集中缺失或不存在的值都用0填充了!
标签列和怀孕次数有可能为0,其他列则不可能出现取值为0的情况,故下列字段原本是存在缺失值的!
所以对以上列中的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()
处理缺失值
1.删除缺失值
2 对缺失值进行填充
可以看看在不同的处理下模型的性能()
首先是删除缺失值
pima_dropped = pima.dropna()
pima_dropped.shape
原始数据是(768, 9),直接删除丢失了不少样本
然后看一下删除前后样本数据分布的变化
(pima_dropped.mean() - pima.mean())/pima.mean()
times_pregnant(怀孕次数)的均值下降了14% pedigree_function(糖尿病血系功能)上升了11%
删除样本会严重影响数据的形状,所以应该保留尽可能多的数据。
我们如何知道直接删除效果怎样,可以通过模型的性能进行评估
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()
我们在设置参数时并不知道参数设为多少为最合适,比如刚才的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_ # 模型性能基线
用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_
除了对数据缺失值进行填充还可以进行数据标注化提升模型
数据标准化是而在多指标评价体系中,由于各评价指标的性质不同,通常具有不同的量纲和数量级。当各指标间的水平相差很大时,如果直接用原始指标值进行分析,就会突出数值较高的指标在综合分析中的作用,相对削弱数值水平较低指标的作用。因此,为了保证结果的可靠性,需要对原始指标数据进行标准化处理
标准化的作用
提升模型性能;加速学习效率
常用标准化方法
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主成分分析:特征向量将偏向较大的列。
随着后续工作的推进模型要做的处理越来越多,我们可以把这些过程都放到管道里。
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
识别缺失值
处理缺失值(删除、0填充、统计值填充)
数据标准化
机器学习流水线
具体使用什么方式处理缺失值,要经过尝试才知道
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。