数据分析与机器学习——收入分类

摘 要

今天,人工智能AI已经融入了人类的生活,基本上在生活中能接触到的领域,都有人工智能的身影。而说起人工智能就必定会想到机器学习ML,它以某种方式几乎影响了每个行业,而机器学习最重要的就是算法和数据。本次期末项目基于“人口普查”数据集,对居民收入是否超过50K进行了预测,用的是K临近算法,中间涉及数据填充、删除,K值的选取,‘找邻居’等步骤。完成这个项目后,对K临近算法有了更深刻的理解,也对机器学习更有兴趣了。

关键词:机器学习;Knn算法;预测收入;准确度

一、问题介绍

1.1 题目要求

基于adult数据集,利用它的age、workclass、…、native_country等13个特征属性预测收入是否超过50k,是一个二分类问题。

1.2 数据集介绍

该数据从美国1994年人口普查数据库中抽取而来,因此也称作“人口普查收入”数据集,共包含48842条记录,年收入大于50k的占比23.93%,年收入小于50k$的占比76.07%。数据集已经划分为训练数据32561条和测试数据16281条。属性变量包括年龄、工种、学历、职业等14类重要信息,其中有8类属于类别离散型变量,另外6类属于数值连续型变量

14个属性变量具体介绍如下:

图片原地址:https://blog.csdn.net/hohaizx/article/details/79084774

二、算法概述

2.1 k近邻算法简介

预测一个数据的类别的时候,通过这个数据的K个最近的邻居来判断该数据类别;也就是‘物以类聚,人以群分’,‘近朱者赤,近墨者黑’的思想。

2.2 计算距离

距离度量有很多种类型,主要包含欧式距离,曼哈顿距离,闵可夫斯基距离等。一般来说用欧式距离来计算,本次实验使用曼哈顿距离

2.3 K值选取

K值就是找待测点的K个最近邻居,统计它们的类别,然后投票计算,预测结果跟着多的那一方。可以想到,K值一般为奇数,就是为了使投票双方结果不会相同。

从上图可见k为3时,周围蓝色多,中心点为蓝色;k=5时,周围红色多,中心点为红色。故k值会影响准确度,一般来说会直接选3或5,后面步骤会遍历3,5,7,9,11…,分别查看精确度,选出最佳k值

2.4 算法优点

(1)简单易用,相比其他算法,KNN算是比较简洁明了的算法。
(2)模型训练时间快。
(3)预测效果好。
(4)对异常值不敏感

2.5 算法缺点

(1)对内存要求较高,因为该算法存储了所有训练数据
(2)预测阶段可能很慢
(3)对不相关的功能和数据规模敏感

三、实验过程和结果分析

3.1导入数据集

使用csv方式直接读取文件,并获取对应的dataFrame,因为adult.csv中的第一行是无用数据,所以需要跳过(采用skiprows),names给每一列加上属性名。此时测试数据集也用train.csv,因为有income结果,方便后面统计正确率。最后输出结果时改成test.csv

3.2 查看数据

首先查看数据信息,发现全是not-null。居然没有缺失值,但我们知道数据中有缺失值

在excel中打开文件,大致浏览一下,发现缺失值用**’ ?’空格问号**这一字符串填充,造成了没有缺失值的假象

然后使用lambda公式查看是否有’ ?’这样的缺失值

从上面的结果可以发现,居民的收入数据集中有3个变量存在数值缺失,分别是居民的工作类型workclass(离散型)缺1836、职业occupation(离散型)缺1843和国籍native-country(离散型)缺583。缺失值的存在一般都会影响分析或建模的结果,所以需要对缺失数值做相应的处理。

3.3 缺失值填充

缺失值的处理一般采用三种方法:

  1. 删除法:缺失的数据较少时适用;
  2. 替换法:用常数替换缺失变量,离散变量用众数,数值变量用均值或中位数;
  3. 插补法:用未缺失的预测该缺失变量。

这里我采用第三种插补法
而插补法又分为:填充固定值,均值,中位数,众数,上一条,下一条等等;
根据上述方法,三个缺失变量都为离散型,可用众数替换。pandas中fillna()方法,
能够使用指定的方法填充NA/NaN值。而先要将 ?字符转化为NAN,然后填充众数

3.4 查看数值型变量

首先,需要知道每个变量的基本统计值,如均值、中位数、众数等,只有了解了所需处理的数据特征,才能做到“心中有数”。
查看代码:

print(dataSet.describe())

结果:

上面的结果描述了有关数值型变量的简单统计值,包括非缺失观测的个数(count)、平均值(mean)、标准差(std)、最小值(min)、下四分位数(25%)、中位数(50%)、上四分位数(75%)和最大值(max)

3.5 查看离散型变量

查看代码:

income.describe(include= ['object'])

结果:

上面为离散变量的统计值,包含每个变量非缺失观测的数量(count)、不同离散值的个数(unique)、出现频次最高的离散值(top)和最高频次数(freq)。以教育education变量为例,一共有16种不同的教育水平;3万多居民中,高中毕业HS-grad的学历是出现最多的,一共有10 501名。

3.6 删去冗余数据

在adult数据集中,关于受教育程度的有两个变量,一个是education(教育水平),另一个是education-num(受教育时长),而且这两个变量的值都是一一对应的,只不过一个是字符型,另一个是对应的数值型。如果将这两个变量都包含在模型中的话,就会产生信息的冗余;fnlwgt变量代表的是一种序号,其对收入水平的高低并没有实际意义。同理删去capital-gain,capital-loss这两列属性。故为了避免冗余信息和无意义变量对模型的影响,共删除education,fnlwgt,capital-gain,capital-loss这四列属性。

    #删去不相关属性dataSet.drop('fnlwgt',axis=1, inplace=True)         #fnlgwtdataSet.drop('education',axis=1, inplace=True)      #EducationdataSet.drop('capital-gain',axis=1, inplace=True)   #Capital GaindataSet.drop('capital-loss',axis=1, inplace=True)   #Capital Loss

打开所有列,查看前十行数据
不加第一句话,只能显示一部分列,中间是……,加了就能看到所有列

    pd.set_option('display.max_columns', None)print(dataSet.head(10))

结果:还剩11列数据

这里有很多地方参考这篇博客 https://blog.csdn.net/qq_38249388/article/details/105211405

3.7 离散变量重编码

此时数据已经处理的差不多了,但由于数据集中有很多离散型变量,这些变量的值为字符
串,不利于建模。因此,需要先对这些变量进行重新编码。
编码的方法有很多种:
(1)将字符型的值转换为整数型的值
(2)哑变量处理(0-1变量)
(3)One-Hot热编码(类似于哑变量)
这里采用字符转数值的方法对离散型变量进行重编码

以workclass为例,查看一下workclass的几个值

结果如下:

用数字替换映射文本:


这里income也就是money属性需要特殊对待,因为train有,test没有;使用try…catch错误处理语句,i=1就是不做任何处理,防止编译器报错

这里是可以不用写那么多的,只是我当时写都写了,懒得删了,可以使用映射的方法:

for col in X.columns[1::]:  #循环修改数据类型的数组u = X[col].unique() #将当前循环的数组加上索引def convert(x):return np.argwhere(u == x)[0,0] #返回值是u中的数据等于x的索引数组,[0,0]截取索引数组的第一排第一个X[col] = X[col].map(convert) #索引替换映射数据

结果:连续化完成,现在的就是‘干净’的数据集
train训练集(前10条)

test测试集

3.8 Knn距离计算

这里使用的是曼哈顿距离,求测试数据和训练数据每个属性之差的绝对值,然后全部加起来,得到这两个数据的距离。

def findDistance(oneTest,oneTrain):#print(oneTest.shape[0])distance = 0for i in range(oneTest.shape[0]-1):distance += (abs(oneTest[i] - oneTrain[i]))return distance

3.9 实现Knn算法

首先初始化两个列表为0,用来存储最近的k+2个邻居下标和到它们的距离;
1000和-1是为了方便第一次比较

    for i in range(testNum):print('i=',i)#初始化neighbors = np.zeros(k + 2)distances = np.zeros(k + 2)for j in range(k+2):distances[j]=1000distances[0]=-1

接下来对每个距离排序,如果比当前最小的k个小,就不停往前,直到停止时,记录当前数据的距离和下标

       for j in range(trainNum):#print(testDataSet.loc[i],trainDataSet.loc[j])distance=findDistance(testDataSet.loc[i],trainDataSet.loc[j])#print(distance)index=kwhile True:if distance < distances[index] :neighbors[index+1] = neighbors[index]distances[index+1] = distances[index]index-=1else:#Insertdistances[index+1] = distanceneighbors[index+1] = jbreak

然后便是投票阶段,也就是看当前最近的k个邻居数据的收入income类型,将出现多的一方的类型当作预测值,放进predicts这个列表里面

        #投票labels=[]for j in range(k):index = int(neighbors[j+1])labels.append(int(trainDataSet.loc[index]['money']))#获得邻居的money值#print(int(trainDataSet.loc[index]['money']))counts = []for label in labels:counts.append(int(labels.count(label)))#print('counts=',counts)predicts[i]=labels[np.argmax(counts)]

最后计算正确率,这一步就是把已知的正确答案和predicts里的预测值做对比,正确数除总数得到正确率

wrong=0for i in range(testNum):#print(predicts[i],testDataSet.loc[i]['money'])if predicts[i]!=testDataSet.loc[i]['money']:wrong+=1return (testNum-wrong)/testNum

结果:

3.10 选择K值

刚刚选择的是k为5的情况,这里可以看看k为其它值时精确度怎么样
k为[1,29]内的奇数

结果:

看的出准确度随着k值变化而变化,当k=21时,精度最高为0.8422;而k在27以后准确度逐渐减小。这是符合预期的, k值的减小意味着整体模型变得复杂,容易发生过拟合;k值很大时,容易欠拟合。

3.11 写入csv文件

本题要求为预测测试集的收入income,并写入学号.csv内,而上面所说的计算准确率是基于有income属性的训练集3:1划分结果。所以为了得到最后结果,前面部分代码有修改,最后要将得到的predict列表转化为dataframe对象,然后用to_csv函数写入csv文件即可

    data = pd.DataFrame(predicts, columns=['Income'])data.to_csv('./新的文件.csv',index=False)

预测结果:

四、代码

4.1 方法一

自己写knn函数

# -*- coding: utf-8 -*-
"""
Created on Thu Jun 18 09:04:24 2020
@author: DZY"""
import pandas as pd
import numpy as npdef loadData():#读文件跳过第一行,为方便计算,可以取前450行数据trainDataSet = pd.read_csv('./train.csv', header=None, skiprows = 1, names=["age","workclass","fnlwgt","education","education_num","marital-status","occupation","relationship","race","sex","capital-gain","capital-loss","hours-per-week","native-country","money"]).head(450)testDataSet = pd.read_csv('./test.csv', header=None, skiprows = 1, names=["age","workclass","fnlwgt","education","education_num","marital-status","occupation","relationship","race","sex","capital-gain","capital-loss","hours-per-week","native-country"])return trainDataSet,testDataSetdef dataCleaning(dataSet):#删去不相关属性dataSet.drop('fnlwgt',axis=1, inplace=True)         #fnlgwtdataSet.drop('education',axis=1, inplace=True)      #EducationdataSet.drop('capital-gain',axis=1, inplace=True)   #Capital GaindataSet.drop('capital-loss',axis=1, inplace=True)   #Capital LossdataSet = dataSet.replace(' ?', np.nan)# 缺失值处理,采用众数替换法(mode()方法取众数)dataSet.fillna(value={'workclass':dataSet['workclass'].mode()[0],   #Workclass'occupation':dataSet['occupation'].mode()[0],   #Occupation  'native-country':dataSet['native-country'].mode()[0]}, #Native countryinplace = True)  #print(dataSet.describe())#print(dataSet.describe(include= ['object']))#离散数据连续化workclass = {' State-gov': 0,' Self-emp-not-inc': 1,' Private': 2,' Federal-gov': 3,' Local-gov': 4,' Self-emp-inc': 5, ' Without-pay': 6, ' Never-worked': 7}maritalStatus = {' Never-married': 0,' Married-civ-spouse': 1,' Divorced': 2,' Married-spouse-absent': 3, ' Separated': 4, ' Married-AF-spouse': 5, ' Widowed': 6}occupation = {' Adm-clerical': 0, ' Exec-managerial': 1, ' Handlers-cleaners': 2, ' Prof-specialty': 3, ' Other-service': 4, ' Sales': 5, ' Craft-repair': 6, ' Transport-moving': 7, ' Farming-fishing': 8, ' Machine-op-inspct': 9, ' Tech-support': 10, ' Protective-serv': 11,' Armed-Forces': 12, ' Priv-house-serv': 13}relationship = {' Not-in-family': 0, ' Husband': 1, ' Wife': 2, ' Own-child': 3, ' Unmarried': 4, ' Other-relative': 5}race = {' White': 0, ' Black': 1, ' Asian-Pac-Islander': 2, ' Amer-Indian-Eskimo': 3, ' Other': 4}sex = {' Male': 0, ' Female': 1}nativeCountry = {' United-States': 0, ' Cuba': 1, ' Jamaica': 2, ' India': 3, ' Mexico': 4, ' South': 5, ' Puerto-Rico': 6, ' Honduras': 7, ' England': 8, ' Canada': 9, ' Germany': 10, ' Iran': 11, ' Philippines': 12, ' Italy': 13, ' Poland': 14, ' Columbia': 15, ' Cambodia': 16, ' Thailand': 17, ' Ecuador': 18, ' Laos': 19, ' Taiwan': 20, ' Haiti': 21, ' Portugal': 22, ' Dominican-Republic': 23, ' El-Salvador': 24, ' France': 25, ' Guatemala': 26, ' China': 27, ' Japan': 28, ' Yugoslavia': 29, ' Peru': 30, ' Outlying-US(Guam-USVI-etc)': 31, ' Scotland': 32, ' Trinadad&Tobago': 33, ' Greece': 34, ' Nicaragua': 35, ' Vietnam': 36, ' Hong': 37, ' Ireland': 38, ' Hungary': 39, ' Holand-Netherlands': 40}money = {' <=50K': 0, ' >50K': 1}dataSet['workclass'] = dataSet['workclass'].map(workclass)dataSet['marital-status'] = dataSet['marital-status'].map(maritalStatus)dataSet['occupation'] = dataSet['occupation'].map(occupation)dataSet['relationship'] = dataSet['relationship'].map(relationship)dataSet['race'] = dataSet['race'].map(race)dataSet['sex'] = dataSet['sex'].map(sex)dataSet['native-country'] = dataSet['native-country'].map(nativeCountry)#训练集有money属性,测试集没有try:dataSet['money'] = dataSet['money'].map(money)except:i = 1#不做处理else:i = 1#pd.set_option('display.max_columns', None)#print(dataSet.head(10))return dataSetdef findDistance(oneTest,oneTrain):#print(oneTest.shape[0])distance = 0for i in range(oneTest.shape[0]-1):distance += (abs(oneTest[i] - oneTrain[i]))return distancedef knnTest(trainDataSet,testDataSet, k):#print(trainDataSet.loc[0])#print(testDataSet)testNum = testDataSet.shape[0]#测试数据行数trainNum = trainDataSet.shape[0]#训练数据行数predicts = np.zeros((testNum))#print(testDataSet.shape[1])for i in range(testNum):print('i=',i)#初始化neighbors = np.zeros(k + 2)distances = np.zeros(k + 2)for j in range(k+2):distances[j]=1000distances[0]=-1for j in range(trainNum):#print(testDataSet.loc[i],trainDataSet.loc[j])distance=findDistance(testDataSet.loc[i],trainDataSet.loc[j])#print(distance)index=kwhile True:if distance < distances[index] :neighbors[index+1] = neighbors[index]distances[index+1] = distances[index]index-=1else:#Insertdistances[index+1] = distanceneighbors[index+1] = jbreak#投票labels=[]for j in range(k):index = int(neighbors[j+1])labels.append(int(trainDataSet.loc[index]['money']))#获得邻居的money值#print(int(trainDataSet.loc[index]['money']))counts = []for label in labels:counts.append(int(labels.count(label)))#print('counts=',counts)predicts[i]=labels[np.argmax(counts)]#print("The prediction[{}] = {}".format(i,predicts[i]))data = pd.DataFrame(predicts, columns=['Income'])data.to_csv('./201731061220.csv',index=False)'''   #基于train的精确率wrong=0for i in range(testNum):#print(predicts[i],testDataSet.loc[i]['money'])if predicts[i]!=testDataSet.loc[i]['money']:wrong+=1return (testNum-wrong)/testNum'''
def main():trainDataSet,testDataSet = loadData()print('训练数据集加载完成,{}行{}列\n'.format(trainDataSet.shape[0],trainDataSet.shape[1]));print('测试数据集加载完成,{}行{}列\n'.format(testDataSet.shape[0],testDataSet.shape[1]));trainDataSet = dataCleaning(trainDataSet)print('训练数据集清理连续化完成,{}行{}列\n'.format(trainDataSet.shape[0],trainDataSet.shape[1]));testDataSet = dataCleaning(testDataSet)print('测试数据集清理连续化完成,{}行{}列\n'.format(testDataSet.shape[0],testDataSet.shape[1]));#print(trainDataSet)k=11knnTest(trainDataSet, testDataSet, k)#accuracy = knnTest(trainDataSet, testDataSet, k)#print("The accuracy is={:.2f}%".format(accuracy*100))main()

4.2 方法二

调用sklearn里的库函数
写的很潦草

#导入需要得包
import numpy as np
import pandas as pd
from sklearn.neighbors import KNeighborsClassifier
salary = pd.read_csv('train.csv') #读取文件
#salary.shape
#salary.head() #数据预处理
salary2 = pd.read_csv('test.csv') #读取文件
X = salary #选取所有行
X2 = salary2 #选取所有行for col in X.columns[1::]:  #循环修改数据类型的数组u = X[col].unique() #将当前循环的数组加上索引def convert(x):return np.argwhere(u == x)[0,0] #返回值是u中的数据等于x的索引数组,[0,0]截取索引数组的第一排第一个X[col] = X[col].map(convert) #索引替换映射数据for col in X2.columns[1::]:  #循环修改数据类型的数组u = X2[col].unique() #将当前循环的数组加上索引def convert(x):return np.argwhere(u == x)[0,0] #返回值是u中的数据等于x的索引数组,[0,0]截取索引数组的第一排第一个X2[col] = X2[col].map(convert) #索引替换映射数据X = salary.iloc[:,[0,1,3,5,6,8,9,-2,-3]] #选取所有行
X2 = salary2.iloc[:,[0,1,3,5,6,8,9,-2,-3]] #选取所有行
y = salary['Income']for num in range(15):k = 2*num+1Knn = KNeighborsClassifier(n_neighbors=k)Knn.fit(X,y)print("k={},score={}",format(k,Knn.score(X,y)))'''plist = np.zeros(X2.shape[0])j=0#print(Knn.predict(X2))for i in Knn.predict(X2):plist[j] = ij+=1data = pd.DataFrame(plist, columns=['Income']) data.to_csv('./目标文件.csv',index=False)
#print(result.mean())
'''

五、参考

最后加上参考的博客地址:
https://blog.csdn.net/Dorisi_H_n_q/article/details/82595188?utm_source=blogxgwz4

https://blog.csdn.net/jingyi130705008/article/details/82670011

https://blog.csdn.net/worldeert/article/details/103465303

https://blog.csdn.net/qq_38249388/article/details/105211405

https://blog.csdn.net/zhw864680355/article/details/102582788

https://blog.csdn.net/hohaizx/article/details/79084774

Python 机器学习大作业 用knn算法对adult数据集进行50w年薪收入预测相关推荐

  1. 用 Python 手写机器学习最简单的 KNN 算法

    作者 | 苏克1900 责编 | 胡巍巍 说实话,相比爬虫,掌握机器学习更实用竞争力也更强些. 目前网上大多这类教程对新手都不友好,要么直接调用 Sklearn 包,要么满篇抽象枯燥的算法公式文字,看 ...

  2. Python 手写机器学习最简单的 kNN 算法

    https://www.toutiao.com/a6698919092876739079/ Python 手写机器学习最简单的 kNN 算法 苏克1900 Python爬虫与数据挖掘 本文 3000 ...

  3. 好家伙!清华电子系大一暑假Python课程大作业上知乎热榜!竟是个CV任务

    点击下方卡片,关注"CVer"公众号 AI/CV重磅干货,第一时间送达 编辑:Amusi  |  来源:知乎 https://www.zhihu.com/question/4719 ...

  4. 机器学习与深度学习——通过knn算法分类鸢尾花数据集iris求出错误率并进行可视化

    什么是knn算法? KNN算法是一种基于实例的机器学习算法,其全称为K-最近邻算法(K-Nearest Neighbors Algorithm).它是一种简单但非常有效的分类和回归算法. 该算法的基本 ...

  5. Python机器学习笔记:异常点检测算法——Isolation Forest

    Python机器学习笔记:异常点检测算法--Isolation Forest 参考文章: (1)Python机器学习笔记:异常点检测算法--Isolation Forest (2)https://ww ...

  6. Python程序设计 大作业 简化的PS

    查看原文 Python程序设计 作业 海龟绘图 文本处理 分组游戏设计 数字照片墙 送你一首集句诗 简化的PS Python程序设计 大作业 简化的PS Python程序设计 作业 摘要 1. 项目背 ...

  7. Python数据分析大作业 4000+字 图文分析文档 销售分析

    资源地址:Python数据分析大作业 4000+字 图文分析文档 销售分析 +完整python代码 数据来自某商场,具体商业数据保密 资源地址:Python数据分析大作业 4000+字 图文分析文档 ...

  8. Python机器学习日记4:监督学习算法的一些样本数据集(持续更新)

    Python机器学习日记4:监督学习算法的一些样本数据集 一.书目与章节 二.forge数据集(二分类) 三.blobs数据集(三/多分类) 四.moons数据集 五.wave数据集(回归) 六.威斯 ...

  9. (运动会模拟射靶)Python期末大作业(附完整文档)

    python期末大作业,因为是数据分析与可视化,所以我在网上搜索的时候,找到了一篇关于大作业射靶的题目,原文写的很好,也提供了下载,本篇在其基础上增加了数据可视化-图表,并且增加了,方差,个人平均分在 ...

最新文章

  1. 常见的CSS属性和值CascadingStyleSheets
  2. 基于Spring AOP的JDK动态代理和CGLIB代理
  3. python 数值的整数次方
  4. 单元格变色和图片透明
  5. [react] 说说你对reader的context的理解
  6. 信息学奥赛一本通 1067:整数的个数 | OpenJudge NOI 1.5 11
  7. log4j的使用 20210719091111861
  8. [zz]很详细,涵盖了多数场景!推荐 - python 的日志logging模块学习
  9. 韩顺平php视频笔记44 php小练习表单提交
  10. python和.net的区别_c#教程之.net和C#的区别
  11. oracle 添加默认值列,Oracle 11g增加列,并带默认值的新特性
  12. .Net Core控制台应用加载读取Json配置文件
  13. 浅析 JNDI / DataSource / ConnectionPool 三者
  14. Python 格式化输出 —— 小数转化为百分数
  15. 使用计时器setInterval实现倒计时
  16. cass小插件集合_CASS插件合集 - 下载 - 搜珍网
  17. 符号Symbol介绍及应用
  18. 计算与背景反差较大显示明显的前景色
  19. 编程题:核桃的数量(求最小公倍数的问题)
  20. 计算机之间通信原理---CSDN观后感

热门文章

  1. 计算机科学数电吗,“不插电的计算机科学”, 你试过吗?
  2. Arduino温湿度监测与股票涨跌提醒
  3. 21.炫酷的CSS数字j时钟
  4. Spring的init-method和destory-method
  5. Python 中文分词 NLPIR 快速搭建
  6. python中的.nc文件处理 | 02 CMIP及MACA v2气候数据介绍
  7. 算法【二叉树】学习笔记 - 已知结点数计算可构建出多少种二叉树
  8. 三维实现广州的行政区划
  9. 百度地图-绘制工具以及覆盖物的简单使用
  10. 股票分时成交明细接口的数据怎么看?