从零开始学python数据分析与挖掘第2章学习笔记

2.2 基于python的案例实战

2.2.1 数据预处理

    案例是对某地区一次人口普查数据进行分析,数据共计32561条,其中变量包括年龄、受教育程度、职业等因素。需要通过已知的数据预测居民的年收入是否会超过5万。

 

#导入需要的包
import pandas as pd
import numpy as np
import seaborn as sns
#导入数据,数据放在D盘python_code文件夹下
income=pd.read_excel(r'D:\python_code\income.xlsx')
#查看数据
income

执行结果为:

读出的数据集大小为32561\times15。代表数据集中有32561个用户的数据,每个用户包含的属性为15个,整理成表格如下:

从表中数据可以看出,数据类型为数值型和离散型,需要对数据进行清洗,包括检查数据是否重复、缺失、异常等,还需要对离散型进行重编码。

读出数据后,首先统计数据集是否有缺失值

#查看数据集是否存在缺失值
income.apply(lambda x:np.sum(x.isnull()))

从结果可以看出,workclass、ouucupation和native-country包含缺失值。

缺失值的处理一般分为三种方法:

(1)删除法

一般针对缺失值占比非常小的,可以使用这种方法。

(2)替换法

用一个常数来替换缺失值。如果变量为离散型,则可以考虑用众数替换缺失值;如果变量为数值型,则使用均值或中位数替换缺失值。

(3)插补法

运用模型方法,对缺失值进行预测,常用回归插补法、多重插补法、拉格朗日插补法等。

由于3个有缺失值的变量都为离散型,可以采用替换法,用众数来替换缺失值。

#缺失值处理
income.fillna(value={'workclass':income.workclass.mode()[0],
                    'occupation':income.occupation.mode()[0],
                    'native-country':income['native-country'].mode()[0]},
             inplace=True)

执行以上命令后,在检查缺失值,所有缺失值都被替换,不存在缺失值。

2.2.2 数据的探索性分析

1、数值型变量的统计描述

#数值型变量的统计描述
income.describe()

输出:

个数(count)、均值(mean)、标准差(std)、最小值(min)、下四分位数(25%)、中位数(50%)、下四分位数(75%)、最大值(max)。

以年龄为例,32561个被调查居民中,平均年龄38.6岁,最小年龄17岁,最大年龄90岁;四分之一的居民年龄不超过28岁,一半的居民年龄为37岁,四分之三的居民年龄不超过48岁,年龄的标准差为13.6岁。

2、离散型变量的统计描述

#离散型变量的统计描述
income.describe(include=['object'])

输出:

个数(count)、不同离散值的个数(unique)、出现频次最高的离散值(top)、最高频次数(freq)。

以受教育水平为例,共16种不同的教育水平,高中毕业学历最多,有10501个。

为了直观查看数据变化,对数据可视化。以年龄和周工作小时数为例,绘制各自的分布形状图。

#导入绘图模块
import matplotlib.pyplot as plt
#设置绘图风格
plt.style.use('ggplot')
#设置多图形的组合
fig,axes=plt.subplots(2,1)
#绘制不同收入水平下的年龄核密度图
income.age[income.income==' <=50K'].plot(kind='kde',label='<=50K',ax=axes[0],legend=True,linestyle='-')
income.age[income.income==' >50K'].plot(kind='kde',label='>50K',ax=axes[0],legend=True,linestyle='--')
#绘制不同收入水平下的周工作小时数核密度图
income['hours-per-week'][income.income==' <=50K'].plot(kind='kde',label='<=50K',ax=axes[1],legend=True,linestyle='-')
income['hours-per-week'][income.income==' >50K'].plot(kind='kde',label='>50K',ax=axes[1],legend=True,linestyle='--')
#显示图形
plt.show()

输出:

从第一张核密度图可以看出,对于年收入超过5万美元的人,年龄符合正态分布,即年龄偏大的居民比年龄小的人数多;

从第二张核密度图可以看出,周工作小时数对年收入影响不大。不同周工作小时数的收入近似。

对于离散型变量采用同样的办法绘图。以性别、种族状态、家庭关系等方面作比较。

#构造不同收入水平下各种族人数的数据
race=pd.DataFrame(income.groupby(by=['race','income']).aggregate(np.size).loc[:,'age'])
#重设行索引
race=race.reset_index()
#变量重命名
race.rename(columns={'age':'counts'},inplace=True)
#排序
race.sort_values(by=['race','counts'],ascending=False,inplace=True)
#构造不同收入水平下各家庭关系人数的数据
relationship=pd.DataFrame(income.groupby(by=['relationship','income']).aggregate(np.size).loc[:,'age'])
relationship=relationship.reset_index()
relationship.rename(columns={'age':'counts'},inplace=True)
relationship.sort_values(by=['relationship','counts'],ascending=False,inplace=True)
#设置图框比例,并绘图
plt.figure(figsize=(9,5))
sns.barplot(x="race",y="counts",hue='income',data=race)
plt.show()
plt.figure(figsize=(9,5))
sns.barplot(x="relationship",y="counts",hue='income',data=relationship)
plt.show()

输出:

第一张图反应相同种族下,居民年收入水平高低的人数差异;第二张图反应的是相同的家庭成员关系下,居民年收入水平高低的人数差异。

2.2.3 数据建模

1、对离散型变量重编码

重编码方法有多种,如将字符型转换为整数型、哑变量(0-1变量)、one-hot热编码(类似哑变量)等。

采用第一种办法。

#离散变量重编码
for feature in income.columns:
    if income[feature].dtype=='object':
        income[feature]=pd.Categorical(income[feature]).codes
income.head()#查看前五项

输出结果:

从结果可以看出,所有值都变成了数值。

观察数据集,有两个属性:education(教育水平)和education-num(教育时长),两个表征同一个属性,可以删除一个。

序号(fnlwgt)与收入无关,也可以删除。

#删除变量
income.drop(['education','fnlwgt'],axis=1,inplace=True)
income.head()

输出结果:

属性只剩下13个,数据集预处理完成。

2、拆分数据集

将数据分为测试集合训练集,训练集:测试集=75%:25%。

#导入sklearn包中的函数
from sklearn.model_selection import train_test_split
#数据拆分
X_train,X_test,y_train,y_test=train_test_split(income.loc[:,'age':'native-country'],
                                              income['income'],train_size=0.75,
                                              random_state=1234)
print('训练集有%d数据'%X_train.shape[0])
print('测试集有%d数据'%X_test.shape[0])

输出:

数据集拆分完成。

3、默认参数的模型构建

利用K近邻合GBDT模型对数据进行预测,对比结果。

K近邻程序:

#导入K近邻模型
from sklearn.neighbors import KNeighborsClassifier
#构建K近邻模型
kn=KNeighborsClassifier()
#对训练集进行训练
kn.fit(X_train,y_train)
#在测试集上的预测
kn_pred=kn.predict(X_test)
#输出混淆矩阵
print(pd.crosstab(kn_pred,y_test))
#打印得分
print('默认模型在训练集上的准确率%f'%kn.score(X_train,y_train))
print('默认模型在测试集上的准确率%f'%kn.score(X_test,y_test))

输出:

混淆矩阵对角线为预测正确的数量,其他数据为错误数量。

模型的准确率在训练集上89%,测试集上准确率83.88%。

gbdt模型的程序

#导入GBDT模型的类
from sklearn.ensemble import GradientBoostingClassifier
#构建GBDT模型
gbdt=GradientBoostingClassifier()
gbdt.fit(X_train,y_train)
#预测测试集
gbdt_pred=gbdt.predict(X_test)
print(pd.crosstab(gbdt_pred,y_test))
#模型得分
print('默认模型在训练集上的准确率%f'%kn.score(X_train,y_train))
print('默认模型在测试集上的准确率%f'%kn.score(X_test,y_test))

输出:

默认情况下,两种算法得到的成绩都差不多。

4、模型网格搜索

默认模型的得分太低,现对两个模型进行优化。利用网络搜索方法对K近邻中的n_neighbors参数优化,选出最合适的。

#k近邻网格搜索法
#导入函数
from sklearn.model_selection import GridSearchCV
#选择不同的参数
k_options=list(range(1,12))
parameters={'n_neighbors':k_options}
#搜索不同的K值
grid_kn=GridSearchCV(estimator=KNeighborsClassifier(),param_grid=parameters,cv=10,scoring='accuracy')
grid_kn.fit(X_train,y_train)
#输出结果
grid_kn.cv_results_

输出结果:

{'mean_fit_time': array([0.53203638, 0.5401998 , 0.54426515, 0.54082947, 0.53198488,
        0.54064717, 0.5367497 , 0.53685031, 0.54187129, 0.54155195,
        0.54196649]),
 'std_fit_time': array([0.01158694, 0.0166025 , 0.00771529, 0.0095051 , 0.00890927,
        0.00949594, 0.00769622, 0.00629885, 0.01243542, 0.00904132,
        0.01049021]),
 'mean_score_time': array([0.23999326, 0.2523963 , 0.25548747, 0.25999699, 0.26750793,
        0.26845031, 0.27248833, 0.27395649, 0.27948327, 0.28333008,
        0.2906534 ]),
 'std_score_time': array([0.00410672, 0.00613088, 0.00206619, 0.00519574, 0.00458668,
        0.00345504, 0.00271323, 0.00405733, 0.0038667 , 0.00656394,
        0.00913412]),
 'param_n_neighbors': masked_array(data=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
              mask=[False, False, False, False, False, False, False, False,
                    False, False, False],
        fill_value='?',
             dtype=object),
 'params': [{'n_neighbors': 1},
  {'n_neighbors': 2},
  {'n_neighbors': 3},
  {'n_neighbors': 4},
  {'n_neighbors': 5},
  {'n_neighbors': 6},
  {'n_neighbors': 7},
  {'n_neighbors': 8},
  {'n_neighbors': 9},
  {'n_neighbors': 10},
  {'n_neighbors': 11}],
 'split0_test_score': array([0.7985258 , 0.82391482, 0.82350532, 0.82882883, 0.82964783,
        0.83497133, 0.83660934, 0.83701884, 0.84029484, 0.83906634,
        0.84398034]),
 'split1_test_score': array([0.81613432, 0.83701884, 0.83579034, 0.84643735, 0.84193284,
        0.85012285, 0.84725635, 0.84848485, 0.84193284, 0.84684685,
        0.84152334]),
 'split2_test_score': array([0.82022932, 0.83742834, 0.84029484, 0.85217035, 0.84725635,
        0.85339885, 0.84807535, 0.85217035, 0.84725635, 0.84971335,
        0.84684685]),
 'split3_test_score': array([0.81367731, 0.84930385, 0.84971335, 0.84930385, 0.84275184,
        0.84971335, 0.84316134, 0.84684685, 0.84234234, 0.84520885,
        0.85094185]),
 'split4_test_score': array([0.80917281, 0.83497133, 0.83619984, 0.84234234, 0.83660934,
        0.84111384, 0.83783784, 0.83783784, 0.83456183, 0.83783784,
        0.83538084]),
 'split5_test_score': array([0.82268632, 0.83824734, 0.83742834, 0.84275184, 0.83333333,
        0.84111384, 0.83497133, 0.84070434, 0.84275184, 0.84438984,
        0.84316134]),
 'split6_test_score': array([0.81695332, 0.84561835, 0.83947584, 0.85872236, 0.85176085,
        0.85954136, 0.85053235, 0.85503686, 0.85298935, 0.85053235,
        0.84807535]),
 'split7_test_score': array([0.82473382, 0.84520885, 0.84971335, 0.85503686, 0.85708436,
        0.86036036, 0.85913186, 0.85667486, 0.86117936, 0.85954136,
        0.85544636]),
 'split8_test_score': array([0.80917281, 0.83456183, 0.82760033, 0.83497133, 0.83906634,
        0.84316134, 0.83988534, 0.84070434, 0.84111384, 0.84438984,
        0.84357084]),
 'split9_test_score': array([0.81531532, 0.83947584, 0.83087633, 0.83824734, 0.83906634,
        0.84561835, 0.84398034, 0.84561835, 0.84357084, 0.84684685,
        0.84438984]),
 'mean_test_score': array([0.81466011, 0.83857494, 0.83705979, 0.84488124, 0.84185094,
        0.84791155, 0.84414414, 0.84610975, 0.84479934, 0.84643735,
        0.8453317 ]),
 'std_test_score': array([0.00725452, 0.00676308, 0.00806508, 0.00883572, 0.0079041 ,
        0.0078496 , 0.00700282, 0.00666316, 0.00707144, 0.00581144,
        0.0051735 ]),
 'rank_test_score': array([11,  9, 10,  5,  8,  1,  7,  3,  6,  2,  4])}
#输出最好的参数和成绩
grid_kn.best_params_,grid_kn.best_score_
输出结果:
({'n_neighbors': 6}, 0.847911547911548)
当n_eighbors选为6时,得分84.79%。

可以看出模型经过优化后,在测试集上得分有所提高,从83.88%上升到84.79%。

对GBDT模型参数进行网格搜索,搜索三个参数,模型的学习速率、生成的基础决策数个数和每个基础决策树的最大深度。

#GBDT模型的网格搜索法
#选择不同的参数
learning_rate_options=[0.01,0.05,0.1]
max_depth_options=[3,5,7,9]
n_estimators_options=[100,300,500]
parameters={'learning_rate':learning_rate_options,
            'max_depth':max_depth_options,
            'n_estimators':n_estimators_options}
grid_gbdt=GridSearchCV(estimator=GradientBoostingClassifier(),
                      param_grid=parameters,
                      cv=10,
                      scoring='accuracy')
grid_gbdt.fit(X_train,y_train)

输出结果:

GridSearchCV(cv=10, estimator=GradientBoostingClassifier(),
             param_grid={'learning_rate': [0.01, 0.05, 0.1],
                         'max_depth': [3, 5, 7],
                         'n_estimators': [100, 300, 500]},
             scoring='accuracy')
#输出结果
grid_gbdt.cv_results_
{'mean_fit_time': array([ 1.3958554 ,  4.04388216,  6.68881943,  2.09518399,  6.50424566,
        10.98832171,  3.14928858,  9.33427184, 15.63615055,  1.33766334,
         3.99769986,  6.94284654,  2.52989802,  7.05922241, 11.68120179,
         3.2000422 , 10.13484142, 16.36020839,  1.40012238,  4.10331552,
         7.2050549 ,  2.28643219,  6.7324204 , 10.7338553 ,  3.22583969,
         9.80430114, 16.47719848]),
 'std_fit_time': array([0.09376492, 0.06855079, 0.07611737, 0.02303831, 0.18850963,
        0.29871895, 0.14512734, 0.08656884, 0.03332805, 0.00710748,
        0.02772576, 0.22887098, 0.09304981, 0.03149704, 0.10735627,
        0.06711602, 0.33308105, 0.38994114, 0.05947049, 0.14465777,
        0.25577146, 0.07008751, 0.13199415, 0.20016754, 0.13193352,
        0.12359806, 0.21836207]),
 'mean_score_time': array([0.00562954, 0.01175189, 0.01740434, 0.00767102, 0.01915598,
        0.02955492, 0.01225917, 0.03140805, 0.04751823, 0.00518537,
        0.01007619, 0.01480801, 0.00877385, 0.01686001, 0.02503104,
        0.01136703, 0.02473061, 0.03928909, 0.00517757, 0.00917804,
        0.0143487 , 0.0074759 , 0.01498547, 0.02412941, 0.01037493,
        0.02457972, 0.04108407]),
 'std_score_time': array([0.00044694, 0.00039251, 0.00046374, 0.00063932, 0.00039624,
        0.00070037, 0.00148993, 0.00067128, 0.00077939, 0.00039834,
        0.00053727, 0.00084112, 0.00097682, 0.00053772, 0.00082907,
        0.00079325, 0.00059335, 0.00194742, 0.00107564, 0.0003908 ,
        0.00111974, 0.0005014 , 0.00041451, 0.00108529, 0.00049222,
        0.00062819, 0.00145772]),
 'param_learning_rate': masked_array(data=[0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01,
                    0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05,
                    0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1],
              mask=[False, False, False, False, False, False, False, False,
                    False, False, False, False, False, False, False, False,
                    False, False, False, False, False, False, False, False,
                    False, False, False],
        fill_value='?',
             dtype=object),
 'param_max_depth': masked_array(data=[3, 3, 3, 5, 5, 5, 7, 7, 7, 3, 3, 3, 5, 5, 5, 7, 7, 7,
                    3, 3, 3, 5, 5, 5, 7, 7, 7],
              mask=[False, False, False, False, False, False, False, False,
                    False, False, False, False, False, False, False, False,
                    False, False, False, False, False, False, False, False,
                    False, False, False],
        fill_value='?',
             dtype=object),
 'param_n_estimators': masked_array(data=[100, 300, 500, 100, 300, 500, 100, 300, 500, 100, 300,
                    500, 100, 300, 500, 100, 300, 500, 100, 300, 500, 100,
                    300, 500, 100, 300, 500],
              mask=[False, False, False, False, False, False, False, False,
                    False, False, False, False, False, False, False, False,
                    False, False, False, False, False, False, False, False,
                    False, False, False],
        fill_value='?',
             dtype=object),
 'params': [{'learning_rate': 0.01, 'max_depth': 3, 'n_estimators': 100},
  {'learning_rate': 0.01, 'max_depth': 3, 'n_estimators': 300},
  {'learning_rate': 0.01, 'max_depth': 3, 'n_estimators': 500},
  {'learning_rate': 0.01, 'max_depth': 5, 'n_estimators': 100},
  {'learning_rate': 0.01, 'max_depth': 5, 'n_estimators': 300},
  {'learning_rate': 0.01, 'max_depth': 5, 'n_estimators': 500},
  {'learning_rate': 0.01, 'max_depth': 7, 'n_estimators': 100},
  {'learning_rate': 0.01, 'max_depth': 7, 'n_estimators': 300},
  {'learning_rate': 0.01, 'max_depth': 7, 'n_estimators': 500},
  {'learning_rate': 0.05, 'max_depth': 3, 'n_estimators': 100},
  {'learning_rate': 0.05, 'max_depth': 3, 'n_estimators': 300},
  {'learning_rate': 0.05, 'max_depth': 3, 'n_estimators': 500},
  {'learning_rate': 0.05, 'max_depth': 5, 'n_estimators': 100},
  {'learning_rate': 0.05, 'max_depth': 5, 'n_estimators': 300},
  {'learning_rate': 0.05, 'max_depth': 5, 'n_estimators': 500},
  {'learning_rate': 0.05, 'max_depth': 7, 'n_estimators': 100},
  {'learning_rate': 0.05, 'max_depth': 7, 'n_estimators': 300},
  {'learning_rate': 0.05, 'max_depth': 7, 'n_estimators': 500},
  {'learning_rate': 0.1, 'max_depth': 3, 'n_estimators': 100},
  {'learning_rate': 0.1, 'max_depth': 3, 'n_estimators': 300},
  {'learning_rate': 0.1, 'max_depth': 3, 'n_estimators': 500},
  {'learning_rate': 0.1, 'max_depth': 5, 'n_estimators': 100},
  {'learning_rate': 0.1, 'max_depth': 5, 'n_estimators': 300},
  {'learning_rate': 0.1, 'max_depth': 5, 'n_estimators': 500},
  {'learning_rate': 0.1, 'max_depth': 7, 'n_estimators': 100},
  {'learning_rate': 0.1, 'max_depth': 7, 'n_estimators': 300},
  {'learning_rate': 0.1, 'max_depth': 7, 'n_estimators': 500}],
 'split0_test_score': array([0.82719083, 0.83456183, 0.84479934, 0.83415233, 0.84561835,
        0.85217035, 0.83701884, 0.84766585, 0.84766585, 0.84316134,
        0.85217035, 0.85503686, 0.84971335, 0.85257985, 0.85217035,
        0.84930385, 0.85339885, 0.85217035, 0.84889435, 0.85380835,
        0.85339885, 0.85339885, 0.85421785, 0.84766585, 0.84930385,
        0.84398034, 0.84357084]),
 'split1_test_score': array([0.85298935, 0.86527437, 0.86895987, 0.86404586, 0.87182637,
        0.87510238, 0.86445536, 0.87755938, 0.88042588, 0.86855037,
        0.87264537, 0.87714988, 0.87796888, 0.87960688, 0.87960688,
        0.87714988, 0.88042588, 0.87755938, 0.86732187, 0.87755938,
        0.88247338, 0.87796888, 0.87878788, 0.87796888, 0.87919738,
        0.87510238, 0.87059787]),
 'split2_test_score': array([0.84520885, 0.85749386, 0.86363636, 0.84889435, 0.86855037,
        0.87264537, 0.85544636, 0.87551188, 0.87674038, 0.86486486,
        0.87346437, 0.87633088, 0.87223587, 0.87919738, 0.87633088,
        0.87796888, 0.87592138, 0.87592138, 0.87059787, 0.87714988,
        0.87674038, 0.87469287, 0.87428337, 0.87100737, 0.87551188,
        0.86977887, 0.86650287]),
 'split3_test_score': array([0.83865684, 0.85667486, 0.86281736, 0.84684685, 0.87059787,
        0.87755938, 0.85462735, 0.88001638, 0.88452088, 0.86322686,
        0.87100737, 0.87592138, 0.87755938, 0.88329238, 0.88533989,
        0.88493038, 0.88329238, 0.87837838, 0.86895987, 0.87674038,
        0.88124488, 0.88370188, 0.88370188, 0.88165438, 0.88452088,
        0.87837838, 0.86855037]),
 'split4_test_score': array([0.85135135, 0.86322686, 0.86773137, 0.86036036, 0.86855037,
        0.87592138, 0.85913186, 0.86977887, 0.87551188, 0.86732187,
        0.87510238, 0.87551188, 0.87510238, 0.87387387, 0.87469287,
        0.87428337, 0.87059787, 0.87223587, 0.87346437, 0.87346437,
        0.87182637, 0.87633088, 0.87592138, 0.87346437, 0.87100737,
        0.86977887, 0.86240786]),
 'split5_test_score': array([0.83824734, 0.84971335, 0.85585586, 0.84807535, 0.85708436,
        0.87141687, 0.85094185, 0.86650287, 0.87387387, 0.85503686,
        0.87223587, 0.87510238, 0.87223587, 0.87878788, 0.87878788,
        0.87387387, 0.87428337, 0.87387387, 0.86568387, 0.87592138,
        0.87551188, 0.87469287, 0.87428337, 0.87592138, 0.87755938,
        0.87182637, 0.86855037]),
 'split6_test_score': array([0.84684685, 0.85667486, 0.86404586, 0.85626536, 0.86609337,
        0.87387387, 0.85995086, 0.87837838, 0.88574939, 0.86568387,
        0.87346437, 0.88329238, 0.87633088, 0.88574939, 0.88493038,
        0.88206388, 0.88615889, 0.88656839, 0.86977887, 0.88411138,
        0.88820639, 0.88411138, 0.88697789, 0.88533989, 0.88697789,
        0.88329238, 0.86855037]),
 'split7_test_score': array([0.84520885, 0.85421785, 0.85667486, 0.85585586, 0.86076986,
        0.86404586, 0.85667486, 0.87059787, 0.87223587, 0.85544636,
        0.86527437, 0.86936937, 0.86650287, 0.87141687, 0.87428337,
        0.87510238, 0.87633088, 0.87387387, 0.86158886, 0.86895987,
        0.87182637, 0.87059787, 0.87633088, 0.87387387, 0.87264537,
        0.86895987, 0.86076986]),
 'split8_test_score': array([0.84070434, 0.85012285, 0.85298935, 0.84848485, 0.85544636,
        0.85995086, 0.84889435, 0.85995086, 0.86650287, 0.85421785,
        0.86240786, 0.86895987, 0.85749386, 0.86732187, 0.86568387,
        0.86732187, 0.86527437, 0.86568387, 0.85790336, 0.86650287,
        0.86732187, 0.86895987, 0.86486486, 0.86855037, 0.86568387,
        0.86117936, 0.85380835]),
 'split9_test_score': array([0.84070434, 0.85298935, 0.85790336, 0.84930385, 0.86036036,
        0.86855037, 0.85176085, 0.87100737, 0.87346437, 0.85831286,
        0.86977887, 0.87633088, 0.86936937, 0.87796888, 0.88247338,
        0.87428337, 0.87796888, 0.87141687, 0.86691237, 0.87714988,
        0.87755938, 0.87674038, 0.87837838, 0.87510238, 0.87796888,
        0.87182637, 0.86445536]),
 'mean_test_score': array([0.84271089, 0.854095  , 0.85954136, 0.8512285 , 0.86248976,
        0.86912367, 0.85389025, 0.86969697, 0.87366912, 0.85958231,
        0.86875512, 0.87330057, 0.86945127, 0.87497952, 0.87542998,
        0.87362817, 0.87436527, 0.87276822, 0.86511057, 0.87313677,
        0.87461097, 0.87411957, 0.87477477, 0.87305487, 0.87403767,
        0.86941032, 0.86277641]),
 'std_test_score': array([0.00703686, 0.00806841, 0.00698795, 0.00794906, 0.00781234,
        0.00768771, 0.00713706, 0.0093305 , 0.01025592, 0.00746022,
        0.00667435, 0.0071825 , 0.00879959, 0.00906662, 0.00951558,
        0.00929882, 0.00900678, 0.00856639, 0.00687229, 0.00792529,
        0.00907355, 0.00829013, 0.0088471 , 0.00965067, 0.01013247,
        0.01015932, 0.00794568]),
 'rank_test_score': array([27, 24, 23, 26, 21, 17, 25, 14,  8, 22, 18, 10, 15,  2,  1,  9,  5,
        13, 19, 11,  4,  6,  3, 12,  7, 16, 20])}
grid_gbdt.best_params_,grid_gbdt.best_score_

输出结果:

({'learning_rate': 0.05, 'max_depth': 5, 'n_estimators': 500},
 0.8754299754299755)
即最佳模型学习率为0.05,生成基础决策树个数为500棵,最大深度为5.模型平均准确率为87.54%。

5、模型预测与评估

验证模型好坏的方法有很多。对于预测的连续变量来说,常用的衡量指标有均方误差(MSE)和均方根误差(RMSE);对于预测的分类变量来说,常用的衡量指标有混淆矩阵中的准确率、ROC曲线下的面积AUC、K-S值等。

现以常用的计算ROC曲线和AUC值为例。分四种情况:

(1)默认K近邻模型

#导入模型评估模型
from sklearn import metrics
#计算ROC曲线的x轴和y轴数据
fpr,tpr,_=metrics.roc_curve(y_test,kn.predict_proba(X_test)[:,1])
#绘制ROC曲线
plt.plot(fpr,tpr,linestyle='solid',color='red')
#添加阴影
plt.stackplot(fpr,tpr,color='steelblue')
#绘制参考线
plt.plot([0,1],[0,1],linestyle='dashed',color='black')
#往图中添加文本
plt.text(0.6,0.4,'ADU=%.3f' %metrics.auc(fpr,tpr),fontdict=dict(size=18))
plt.show()

输出结果:

绘制出ROC曲线,AUC面积为0.865.模型的好坏,以AUC为准,越大越好。一般认为,当AUC的值超过0.8时,基本上认为模型比较合理。从结果可以看出,默认参数K近邻模型在居民收入数据集上表现还算理想。

(2)网格搜索的K近邻模型

#预测测试集
grid_kn_pred=grid_kn.predict(X_test)
print(pd.crosstab(grid_kn_pred,y_test))
#模型得分
print('模型在训练集上的准确率%f'%grid_kn.score(X_train,y_train))
print('模型在测试集上的准确率%f'%grid_kn.score(X_test,y_test))
#绘制ROC曲线
fpr,tpr,_=metrics.roc_curve(y_test,grid_kn.predict_proba(X_test)[:,1])
plt.plot(fpr,tpr,linestyle='solid',color='red')
plt.stackplot(fpr,tpr,color='steelblue')
plt.plot([0,1],[0,1],linestyle='dashed',color='black')
plt.text(0.6,0.4,'AUC=%.3f'%metrics.auc(fpr,tpr),fontdict=dict(size=18))
plt.show()

输出结果:

经过网格搜索后模型在训练集上的准确率下降了,但是在测试集上准确率提高了。AUC为0.87.比默认提高了一点。说明网格搜索后的模型比原始模型更优秀。

(3)默认GBDT模型

#预测测试集
gbdt_pred=gbdt.predict(X_test)
print(pd.crosstab(gbdt_pred,y_test))
#模型得分
print('模型在训练集上的准确率%f'%grid_kn.score(X_train,y_train))
print('模型在测试集上的准确率%f'%grid_kn.score(X_test,y_test))
#绘制ROC曲线
fpr,tpr,_=metrics.roc_curve(y_test,gbdt.predict_proba(X_test)[:,1])
plt.plot(fpr,tpr,linestyle='solid',color='red')
plt.stackplot(fpr,tpr,color='steelblue')
plt.plot([0,1],[0,1],linestyle='dashed',color='black')
plt.text(0.6,0.4,'AUC=%.3f'%metrics.auc(fpr,tpr),fontdict=dict(size=18))
plt.show()

结果:

集成算法GBDT在测试集上表现优于K近邻算法。准确率超过85%,AUC达到了0.913.

(4)网格搜索的GBDT模型

#预测测试集
grid_gbdt_pred=grid_gbdt.predict(X_test)
print(pd.crosstab(grid_gbdt_pred,y_test))
#模型得分
print('模型在训练集上的准确率%f'%grid_gbdt.score(X_train,y_train))
print('模型在测试集上的准确率%f'%grid_gbdt.score(X_test,y_test))
#绘制ROC曲线
fpr,tpr,_=metrics.roc_curve(y_test,grid_gbdt.predict_proba(X_test)[:,1])
plt.plot(fpr,tpr,linestyle='solid',color='red')
plt.stackplot(fpr,tpr,color='steelblue')
plt.plot([0,1],[0,1],linestyle='dashed',color='black')
plt.text(0.6,0.4,'AUC=%.3f'%metrics.auc(fpr,tpr),fontdict=dict(size=18))
plt.show()

gbdt网格搜索后的结果明显得到提升。

Guess you like

Origin blog.csdn.net/xfsong2012/article/details/112692200