目录
如果我们知道对收入高低起决定性的因素,或者哪些因素组合在一起有着能够增大收入 的可能性,那么这样可以帮助很多人少走弯路,朝着正确的方向努力,早日达到目标。 就像许多传授给我们人生智慧的书籍一样,我们的目标是探寻一种影响人收入的条件体系并在以后的日子里继续对这套体系做出完善,以求能找到富裕的秘诀。
Adult数据集(即“人口普查收入”数据集),由美国人口普查数据集库 抽取而来,其中共包含48842条记录,年收入大于50k美元的占比23.93%,年收入小于50k美元的占比76.07%,并且已经划分为训练数据32561条和测试数据16281条。 该数据集类变量为年收入是否超过50k美元,属性变量包括年龄、工种、学历、职业等 14类重要信息,其中有8类属于类别离散型变量,另外6类属于数值连续型变量。该数据集是一个分类数据集,用来预测年收入是否超过50k美元。

通过对“Adult”数据集的观察,发现在一些属性上的缺失值较多,并且14个样本属性中既有连续型变量也有离散型变量,又因为“Adult”数据集属于分类数据集,综合考虑下, 选取决策树算法与贝叶斯算法作为主要预测方式。
补充说明:决策树算法计算比较简单,解释性强,比较适合处理有缺失属性值的数据样本。贝叶斯算法源于古典数学理论,有着坚实的数学基础,分类效率稳定,同样算法比较简单,对缺失数据不太敏感。
#将下载的数据集adult.data和adult.test存在data文件夹中
train_data = 'data/adult.data'
test_data = 'data/adult.test'
#通过pandas包中read_csv方法,给每一列加上属性名
columns = ['Age','Workclass','fnlgwt','Education','EdNum','MaritalStatus',
'Occupation','Relationship','Race','Sex','CapitalGain',
'CapitalLoss','HoursPerWeek','Country','Income']
df_train_set = pd.read_csv(train_data, names=columns)
#因为第一行是无用数据,所以跳过
df_test_set = pd.read_csv(test_data, names=columns, skiprows=1)
# 因为fnlgwt属性记录的是人口普查员的ID,对预测结果无影响,故删除该列
df_train_set.drop('fnlgwt', axis=1, inplace=True)
df_test_set.drop('fnlgwt', axis=1, inplace=True)
#进行数据清洗,将数据集中‘?’字符替换为‘Unknown’
for i in df_train_set.columns:
df_train_set[i].replace('?', 'Unknown', inplace=True)
df_test_set[i].replace('?', 'Unknown', inplace=True)
#去掉非int64类型数据中的点和空格,以提高算法精度
for col in df_train_set.columns:
if df_train_set[col].dtype != 'int64':
df_train_set[col] = df_train_set[col].apply(lambda val: val.replace(" ", ""))
df_train_set[col] = df_train_set[col].apply(lambda val: val.replace(".", ""))
df_test_set[col] = df_test_set[col].apply(lambda val: val.replace(" ", ""))
df_test_set[col] = df_test_set[col].apply(lambda val: val.replace(".", ""))
#Education(受教育程度)和Ednum(受教育时间)特征相似,为减少干扰因素, 删除Education属性;除此之外,Country对年收入的影响也不大,故同样删除
df_train_set.drop(["Country", "Education"], axis=1, inplace=True)
df_test_set.drop(["Country", "Education"], axis=1, inplace=True)
#将数据的表头转换为列表形式并储存在colnames变量中,移除原有的Age和EdNum属性,同时添加新的AgeGroup和EduGroup属性
colnames = list(df_train_set.columns)
colnames.remove('Age')
colnames.remove('EdNum')
colnames = ['AgeGroup', 'EduGroup']+colnames
# 转化Age(年龄)和EdNum(受教育时间)列,将连续数值型转换为更高效的方式,
此处将年龄转换为10的整数倍,受教育时间转换为5的整数倍
# 这里利用了format方式快速创建字符型列表
labels = ["{0}-{1}".format(i, i+9) for i in range(0,100,10)]
# 调用pandas包中的pd方法将数据切分为离散的区间并打上标签
df_train_set['AgeGroup'] = pd.cut(df_train_set.Age, range(0,101,10), right = False, labels = labels)
df_test_set['AgeGroup'] = pd.cut(df_test_set.Age, range(0,101,10), right = False, labels = labels)
#下面的方法同上,转化EdNum属性为5的整数倍
labels = ["{0}-{1}".format(i,i+4) for i in range(0,20,5)]
df_train_set['EduGroup'] = pd.cut(df_train_set.EdNum, range(0,21,5), right = False, labels = labels)
df_test_set['EduGroup'] = pd.cut(df_test_set.EdNum, range(0,21,5), right = False, labels = labels)
# 这里只提取colnames中的列,并按照colnames排序
df_train_set = df_train_set[colnames]
df_test_set = df_test_set[colnames]
#将非数值型数据转换为数值型数据
#调用pandas包中的DataFrameMapper类对AgeGroup、AgeGroup、Workclass、Occupation等列进行标签编码,转化为连续的数值型变量,大大提高了代码的简洁性,一步到位
mapper = DataFrameMapper([('AgeGroup', LabelEncoder()),('EduGroup', LabelEncoder()),
('Workclass', LabelEncoder()),('MaritalStatus', LabelEncoder()),
('Occupation', LabelEncoder()),('Relationship', LabelEncoder()),
('Race', LabelEncoder()),('Sex', LabelEncoder()),
('Income', LabelEncoder())], df_out=True, default=None)
#和(4)中方法类似,将Income列转移到中间
cols = list(df_train_set.columns)
cols.remove('Income')
cols = cols[:-3]+['Income']+cols[-3:]
#调用fit_transform()方法拟合数据,并标准化
#替换表头,移除样本标记income
df_train = mapper.fit_transform(df_train_set.copy())
df_train.columns = cols
df_test = mapper.transform(df_test_set.copy())
df_test.columns = cols
cols.remove('Income')
x_train, y_train = df_train[cols].values, df_train['Income'].values
x_test, y_test = df_test[cols].values, df_test['Income'].values
至此数据预处理操作完毕
#引入相应包
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import LabelEncoder
from sklearn_pandas import DataFrameMapper
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
#数据导入
train_data = 'data/adult.data'
test_data = 'data/adult.test'
columns = ['Age','Workclass','fnlgwt','Education','EdNum','MaritalStatus',
'Occupation','Relationship','Race','Sex','CapitalGain',
'CapitalLoss','HoursPerWeek','Country','Income']
df_train_set = pd.read_csv(train_data, names=columns)
df_test_set = pd.read_csv(test_data, names=columns, skiprows=1)
#数据预处理
df_train_set.drop('fnlgwt', axis=1, inplace=True)
df_test_set.drop('fnlgwt', axis=1, inplace=True)
for i in df_train_set.columns:
df_train_set[i].replace('?', 'Unknown', inplace=True)
df_test_set[i].replace('?', 'Unknown', inplace=True)
for col in df_train_set.columns:
if df_train_set[col].dtype != 'int64':
df_train_set[col] = df_train_set[col].apply(lambda val: val.replace(" ", ""))
df_train_set[col] = df_train_set[col].apply(lambda val: val.replace(".", ""))
df_test_set[col] = df_test_set[col].apply(lambda val: val.replace(" ", ""))
df_test_set[col] = df_test_set[col].apply(lambda val: val.replace(".", ""))
df_train_set.drop(["Country", "Education"], axis=1, inplace=True)
df_test_set.drop(["Country", "Education"], axis=1, inplace=True)
colnames = list(df_train_set.columns)
colnames.remove('Age')
colnames.remove('EdNum')
colnames = ['AgeGroup', 'EduGroup']+colnames
labels = ["{0}-{1}".format(i, i+9) for i in range(0,100,10)]
df_train_set['AgeGroup'] = pd.cut(df_train_set.Age, range(0,101,10), right = False, labels = labels)
df_test_set['AgeGroup'] = pd.cut(df_test_set.Age, range(0,101,10), right = False, labels = labels)
labels = ["{0}-{1}".format(i,i+4) for i in range(0,20,5)]
df_train_set['EduGroup'] = pd.cut(df_train_set.EdNum, range(0,21,5), right = False, labels = labels)
df_test_set['EduGroup'] = pd.cut(df_test_set.EdNum, range(0,21,5), right = False, labels = labels)
df_train_set = df_train_set[colnames]
df_test_set = df_test_set[colnames]
#数据转换
mapper = DataFrameMapper([('AgeGroup', LabelEncoder()),('EduGroup', LabelEncoder()),
('Workclass', LabelEncoder()),('MaritalStatus', LabelEncoder()),
('Occupation', LabelEncoder()),('Relationship', LabelEncoder()),
('Race', LabelEncoder()),('Sex', LabelEncoder()),
('Income', LabelEncoder())], df_out=True, default=None)
cols = list(df_train_set.columns)
cols.remove('Income')
cols = cols[:-3]+['Income']+cols[-3:]
df_train = mapper.fit_transform(df_train_set.copy())
df_train.columns = cols
df_test = mapper.transform(df_test_set.copy())
df_test.columns = cols
cols.remove('Income')
# 训练数据与测试数据划分
x_train, y_train = df_train[cols].values, df_train['Income'].values
x_test, y_test = df_test[cols].values, df_test['Income'].values
# 模型初步训练与评分
treeClassifier = DecisionTreeClassifier()
treeClassifier.fit(x_train, y_train)
score = treeClassifier.score(x_test, y_test)
print('决策树网格搜索前评分:', score)
#绘制混淆矩阵
from sklearn.metrics import plot_confusion_matrix
np.set_printoptions(precision=4)
titles_options = [('不规范混淆矩阵',None),
('规范化混淆矩阵', 'true')]
class_names = [df_test_set['Income'][1],df_test_set['Income'][2]]
for title, normalize in titles_options:
disp = plot_confusion_matrix(treeClassifier, x_test, y_test,
display_labels = class_names,
cmap = plt.cm.Oranges,
normalize = normalize)
disp.ax_.set_title(title)
print(title)
print(disp.confusion_matrix)
# 参数优化
from sklearn.model_selection import GridSearchCV
paras = {'max_features':(None, 9, 6),
'max_depth':(None, 24, 16),
'min_samples_split':(2, 4, 8),
'min_samples_leaf':(16, 4, 12)
}
clf = GridSearchCV(treeClassifier, paras, cv = 5)
clf.fit(x_train, y_train)
clf.best_score_, clf.score(x_test, y_test), clf.best_params_
print('决策树网格搜索后最好评分:', clf.best_score_)
print('决策树网格搜索后评分:', clf.score(x_test, y_test))
print('最好参数:', clf.best_params_)
disp2 = plot_confusion_matrix(clf, x_test, y_test,
display_labels = class_names,
cmap = plt.cm.Blues,
normalize = 'true')
disp2.ax_.set_title('Confusion matrix after GridSearch')
print(title)
print(disp2.confusion_matrix)
参数调优前截图:

参数调优后截图:

#朴素贝叶斯算法的数据预处理过程与(1)中相同
#建立朴素贝叶斯分类模型
from sklearn.naive_bayes import GaussianNB
gaussianNB = GaussianNB()
gaussianNB.fit(x_train, y_train)
score = gaussianNB.score(x_test, y_test)
print('贝叶斯模型评分:', score)
#用交叉验证的方法来检验模型的准确性
from sklearn.model_selection import cross_val_score
num_validations=5
accuracy=cross_val_score(gaussianNB,x_test, y_test,
scoring='accuracy',cv=num_validations)
print('准确率:{:.2f}%'.format(accuracy.mean()*100))
precision=cross_val_score(gaussianNB,x_test, y_test,
scoring='precision_weighted',cv=num_validations)
print('精确度:{:.2f}%'.format(precision.mean()*100))
recall=cross_val_score(gaussianNB,x_test, y_test,
scoring='recall_weighted',cv=num_validations)
print('召回率:{:.2f}%'.format(recall.mean()*100))
f1=cross_val_score(gaussianNB,x_test, y_test,
scoring='f1_weighted',cv=num_validations)
print('F1 值:{:.2f}%'.format(f1.mean()*100))
朴素贝叶斯截图:

在判断年收入是否超过50K的问题中,两种算法均采用相同的数据处理方式,并通过scroce()方法对模型进行了评估。其中决策树算法附加使用了网格搜索的方法进行参数调优,对模型做出了更好的改进。朴素贝叶斯算法附加使用了交叉验证的方法来进一步验证模型的性能。综合上述实验结果可以观察得出:决策树模型在参数调优前后评分均高于贝叶斯模型,并且参数调优后模型精度得到了进一步的提高;而贝叶斯模型在经过交叉验证后,精度反而出现了下降。
究其原因,可能在于数据预处理时选择了对决策树算法更有利的清洗方式,并且决策树算法利用网格搜索进行了模型参数调优,而朴素贝叶斯算法没有重新再对数据进行更加细致的预处理,没有做到减少数据冗余的特征以及归并类似的特征取值,并且最重要的一点在于没有利用拉普拉斯平滑对数据进行处理,这些原因都可能导致决策树算法的性能优于朴素贝叶斯算法的性能。
通过对相关资料的查询,朴素贝叶斯算法与其他分类方法相比,具有最小的误差率。但是实际上并非总是如此,这是因为朴素贝叶斯模型假设属性之间相互独立,这个假设在实际应用中往往是不成立的,在属性个数比较多或者属性之间相关性较大时,分类效果不好,而在属性相关性较小时,朴素贝叶斯算法的性能最为良好,并且朴素贝叶斯算法对于输入数据的准备方式较为敏感,通常不适用于连续性数据,只能用于离散数据。而“Adult”数据集恰是属于属性个数和连续性数据量多,属性之间的相关性较大的数据集。因此在对判断年收入是否超过50K这一问题解决方案的选择中应更偏向决策树算法。
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳
我正在尝试使用Curbgem执行以下POST以解析云curl-XPOST\-H"X-Parse-Application-Id:PARSE_APP_ID"\-H"X-Parse-REST-API-Key:PARSE_API_KEY"\-H"Content-Type:image/jpeg"\--data-binary'@myPicture.jpg'\https://api.parse.com/1/files/pic.jpg用这个:curl=Curl::Easy.new("https://api.parse.com/1/files/lion.jpg")curl.multipart_form_
无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD
本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01 客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02 数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit
文章目录一、概述简介原理模块二、配置Mysql使用版本环境要求1.操作系统2.mysql要求三、配置canal-server离线下载在线下载上传解压修改配置单机配置集群配置分库分表配置1.修改全局配置2.实例配置垂直分库水平分库3.修改group-instance.xml4.启动监听四、配置canal-adapter1修改启动配置2配置映射文件3启动ES数据同步查询所有订阅同步数据同步开关启动4.验证五、配置canal-admin一、概述简介canal是Alibaba旗下的一款开源项目,Java开发。基于数据库增量日志解析,提供增量数据订阅&消费。Git地址:https://github.co
我正在尝试在Rails上安装ruby,到目前为止一切都已安装,但是当我尝试使用rakedb:create创建数据库时,我收到一个奇怪的错误:dyld:lazysymbolbindingfailed:Symbolnotfound:_mysql_get_client_infoReferencedfrom:/Library/Ruby/Gems/1.8/gems/mysql2-0.3.11/lib/mysql2/mysql2.bundleExpectedin:flatnamespacedyld:Symbolnotfound:_mysql_get_client_infoReferencedf
文章目录1.开发板选择*用到的资源2.串口通信(个人理解)3.代码分析(注释比较详细)1.主函数2.串口1配置3.串口2配置以及中断函数4.注意问题5.源码链接1.开发板选择我用的是STM32F103RCT6的板子,不过代码大概在F103系列的板子上都可以运行,我试过在野火103的霸道板上也可以,主要看一下串口对应的引脚一不一样就行了,不一样的就更改一下。*用到的资源keil5软件这里用到了两个串口资源,采集数据一个,串口通信一个,板子对应引脚如下:串口1,TX:PA9,RX:PA10串口2,TX:PA2,RX:PA32.串口通信(个人理解)我就从串口采集传感器数据这个过程说一下我自己的理解,
SPI接收数据左移一位问题目录SPI接收数据左移一位问题一、问题描述二、问题分析三、探究原理四、经验总结最近在工作在学习调试SPI的过程中遇到一个问题——接收数据整体向左移了一位(1bit)。SPI数据收发是数据交换,因此接收数据时从第二个字节开始才是有效数据,也就是数据整体向右移一个字节(1byte)。请教前辈之后也没有得到解决,通过在网上查阅前人经验终于解决问题,所以写一个避坑经验总结。实际背景:MCU与一款芯片使用spi通信,MCU作为主机,芯片作为从机。这款芯片采用的是它规定的六线SPI,多了两根线:RDY和INT,这样从机就可以主动请求主机给主机发送数据了。一、问题描述根据从机芯片手
前言一般来说,前端根据后台返回code码展示对应内容只需要在前台判断code值展示对应的内容即可,但要是匹配的code码比较多或者多个页面用到时,为了便于后期维护,后台就会使用字典表让前端匹配,下面我将在微信小程序中通过wxs的方法实现这个操作。为什么要使用wxs?{{method(a,b)}}可以看到,上述代码是一个调用方法传值的操作,在vue中很常见,多用于数据之间的转换,但由于微信小程序诸多限制的原因,你并不能优雅的这样操作,可能有人会说,为什么不用if判断实现呢?但是if判断的局限性在于如果存在数据量过大时,大量重复性操作和if判断会让你的代码显得异常冗余。wxswxs相当于是一个独立