美文网首页
用KNN和GBDT判断美国某区域居民年收入

用KNN和GBDT判断美国某区域居民年收入

作者: apricoter | 来源:发表于2019-03-01 18:16 被阅读45次

读取数据

import numpy as np
import pandas as pd
#读取数据
data=pd.read_excel("F:\income.xlsx")
#预览数据前五行
data.head()

对某区域居民的人口普查

#查看各变量类型
data.info()

int为数值型,object为离散型
workclass为工作类型,fnlwgt为序号,relationship为家庭成员关系,race为种族,capital-gain为资本收益,native-country为国籍,因变量为需要预测居民的年收入是否超过5万美元

数据预处理

重复观测,缺失值,异常值,对字符型数据数值转换

#查看缺失值并合计个数
data.isnull().sum(axis = 0)

有三个离散型变量有缺失且数目比较多,用众数替换

#使用各个离散型变量的众数来替换缺失值
data.fillna(value = {'workclass':data.workclass.mode()[0],
                              'occupation':data.occupation.mode()[0],
                              'native-country':data['native-country'].mode()[0]}, inplace = True)
#再次查看缺失值并合计个数
data.isnull().sum(axis = 0)

探索性分析

#数值型变量统计描述
data.describe()
#离散型变量统计描述
data.describe(include=["object"])

以受教育水平为例,一共有16种不同的水平,3万多居民中,高中毕业的最多,有10501名

针对数值型变量,描述分布,以年龄为例,观测分布,确定峰度,偏度

#分布形状
#绘制不同收入水平下的年龄核密度图
import seaborn as sns
import matplotlib.pyplot as plt
#设置绘图风格
plt.style.use("ggplot")
# 中文乱码和坐标轴负号的处理
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False
# 取出收入<=50k
Age1 = data.age[data.income == ' <=50K']#<=之前要空一格
# 取出收入>50k
Age2 = data.age[data.income == " >50K"]
# 绘制收入<=50k的年龄的核密度图
sns.distplot(Age1, hist = False, kde_kws = {'color':'red', 'linestyle':'-'}, 
             norm_hist = True, label = '<=50K')
# 绘制收入>50k的年龄的核密度图
sns.distplot(Age2, hist = False, kde_kws = {'color':'black', 'linestyle':'--'}, 
             norm_hist = True, label = '>50K')
plt.title('不同收入水平下的年龄核密度图')
# 显示图例
plt.legend()
# 显示图形
plt.show()

在不同的收入水平下,年龄的核密度分布图表明,对于年收入超过5万美元的居民,几乎呈现正态分布,而收入低于5万美元的居民,年龄呈现右偏分布,即年龄偏大的居民人数比年龄偏下的人数多

同样,针对离散型变量,以对比居民的收入水平高低在种族之间的差异为例,可以发现这些离散型变量是否影响收入水平

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

在相同的种族下,居民年收入高低的人数差异,在白种人中,年收入低于5万和高于5万的居民比例大致为3;1

数据建模

对离散变量重编码,这样的字符型变量不可直接建模,需要重编码

# 离散变量的重编码
for feature in data.columns:
    if data[feature].dtype == 'object':
        data[feature] = pd.Categorical(data[feature]).codes
data.head()

所有的字符型变量都变成了整数型变量

又教育水平和教育时长产生信息冗余,且序号fnlwgt无意义,故删除变量

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

拆分数据集

# 导入第三方包
from sklearn import model_selection
predictors = data.columns[:-1]
# 将数据集拆分为训练集和测试集,且测试集的比例为25%
X_train, X_test, y_train, y_test = model_selection.train_test_split(data[predictors], data.income, 
                                                                    test_size = 0.25, random_state = 1234)
print('训练数据集共有%d条观测' %X_train.shape[0])
print('测试数据集共有%d条观测' %X_test.shape[0])

sklearn模块提供了网格搜索法完成模型的参数选择
KNN模型

# K近邻模型的网格搜索法
# 导入k近邻模型的类
from sklearn.neighbors import KNeighborsClassifier
# 导入网格搜索法的函数
from sklearn.grid_search 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', verbose=0, n_jobs=2)
grid_kn.fit(X_train, y_train)
print(grid_kn)
# 结果输出
grid_kn.grid_scores_, grid_kn.best_params_, grid_kn.best_score_  

estimator接受一个指定的模型,param_grid指定模型需要搜索的参数列表对象,cv为x重交叉验证,scoring指定模型评估的度量值


第一部分为11种K值下的平均准确率(因为是10重交叉验证),第二部分选择了最佳的K值,第三部分是当为最佳K值时,模型的最佳平均准确率

评估模型,对于预测的连续变量为MSE和RMSE;对于预测的分类变量为混淆矩阵中的准确率,ROC曲线下的面积AUC,K-S值

# 导入模型评估模块
from sklearn import metrics
# 预测测试集
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()

大于0.8,模型合理

GBDT模型

# 导入网格搜索法的函数
from sklearn.grid_search import GridSearchCV
# 导入GBDT模型的类
from sklearn.ensemble import GradientBoostingClassifier
from sklearn import ensemble
# 运用网格搜索法选择梯度提升树的合理参数组合
learning_rate = [0.01,0.05,0.1] #模型的学习速率
n_estimators = [100,300,500] #生成的基础决策树的个数
max_depth = [3,5,7,9] #每个基础决策树的最大深度
params = {'learning_rate':learning_rate,'n_estimators':n_estimators,'max_depth':max_depth}
gbdt_grid = GridSearchCV(estimator = ensemble.GradientBoostingClassifier(),
                         param_grid= params, scoring = 'roc_auc', cv = 10, n_jobs = 4)
gbdt_grid.fit(X_train,y_train)
# 返回参数的最佳组合和对应AUC值
gbdt_grid.best_params_, gbdt_grid.best_score_

最佳模型学习率为0.05,生成的基础决策树个数为300棵,并且每颗基础决策树的最大深度为5,这样的组合可以使GBDT模型的平均准确率达到93.02%

# 导入模型评估模块
from sklearn import metrics
# 预测测试集
gbdt_grid_pred = gbdt_grid.predict(X_test)
print(pd.crosstab(gbdt_grid_pred, y_test))

# 模型得分
print('模型在训练集上的准确率%f' %gbdt_grid.score(X_train,y_train))
print('模型在测试集上的准确率%f' %gbdt_grid.score(X_test,y_test))

# 绘制ROC曲线
fpr, tpr, _ = metrics.roc_curve(y_test, gbdt_grid.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()

模型在训练集上的准确率达到94%,在测试集上的准确率也达到92%,AUC的值高达0.921,远远超过0.8。

集成算法GBDT的表现比KNN要优秀,因为这是基于多棵决策树进行投票的优点。

总之,无论是KNN还是GBDT,都可以通过网格搜索法找到各自的最佳模型参数,而且这些最佳参数的组合一般都会使得模型比较优秀和健壮、

在纵向比较默认参数的模型和网格搜索后的最佳参数模型,后者一般比较好;在横向比较单一模型和集成模型,后者也一般表现更优秀。

相关文章

  • 用KNN和GBDT判断美国某区域居民年收入

    读取数据 对某区域居民的人口普查 int为数值型,object为离散型workclass为工作类型,fnlwgt为...

  • 13.2求和函数(Sumif,Sumifs)

    1.基本用法 SUMIF(判断区域,求和条件,数据区域)—— 区域用绝对引用/用名称框方法 SUMIFS(数据区域...

  • 2018-11-29

    今天学习了sumif.sumifs函数,主要包括1基本用法sum if(判断区域,求和条件,数据区域),判断区域和...

  • 第十三天—求和函数(Sumif、Sumifs)

    1.基本函数 sumif =SUMIF(判断区域,求和的条件,数据区域) 注意:判断区域和求和区域必须保持一致的长...

  • iOS - 点是否在范围内、点和坐标的转换

    判断一个 Point 是否在另一个 rect 中 判断一个rect是否在这个rect区域中 判断区域1和区域2是否...

  • 传统机器学习笔记 - GBDT(二)

    学习GBDT的原理和细节(二) 在GBDT的原理之后,拓展GBDT相关的细节,包括和Adaboost的异同,以及G...

  • 用KNN算法判断知识掌握程度高低

    KNN算法既可以解决分类问题,也可以解决预测问题。 对于离散型因变量,从k个最近的已知类别样本中挑选出频率最高的类...

  • 2.费解的国家

    中国人用好与不好来判断事件,依据的是道德。而美国人用合法和非法判断事件,依据的是法律。 美国人向往自由...

  • KNN

    一句话介绍KNN KNN是一种可用于分类和回归的方法。一般情况下用其进行分类任务。 KNN三要素 1)模型,即对特...

  • 求和函数(sumif sumifs)

    1. 基本用法 =Sumif(条件区域,求和条件,数据区域) 注意:判断区域和求和区域长度保持一致 =sumifs...

网友评论

      本文标题:用KNN和GBDT判断美国某区域居民年收入

      本文链接:https://www.haomeiwen.com/subject/ovwduqtx.html