【课程总结】Day6(下):机器学习项目实战–成人收入预测

机器学习项目实战:成人收入预测

项目目的

基于个人收入数据(包括教育程度、年龄、性别等)的数据集,通过机器学习算法,预测一个人的年收入是否超过5万美金。

数据集

  • 地址:http://idatascience.cn/dataset-detail?table_id=100368

  • 数据集字段

    字段名称字段类型字段说明
    age数值型年龄
    workclass字符型工作类型
    fnlwgt字符型序号
    education字符型教育程度
    education-num数值型受教育时长
    marital-status字符型婚姻状况
    occupation字符型职业
    relationship字符型关系
    race字符型种族
    sex字符型性别
    capital-gain数值型资本收益
    capital-loss数值型资本损失
    hours-per-week数值型每周工作小时数
    native-country字符型原籍
    salary字符型收入
  • 数据集样例:
    file

解决思路

分析输入/输出

通过分析,本次项目我们要解决的问题:给定一个人的相关信息(包括年龄、教育程度、受教育时长等),预测其收入是否超过5万。

该问题如果是预测其收入是多少,那么就属于线性回归问题;但数据集中在收入标签是>=5万或<5万,所以这应该是一个分类问题。

分析相关输入/输出如下:

  • 输入:一个人的信息(包括年龄、教育程度、受教育时长等)
  • 输出:0为<=50K,1为>50K
构建数据集
分析数据类型

首先,我们先分析一下如何将数据集向量化,通过以下代码来查看数据集每列的内容:

import csv
import numpy as np
def read_file(file_path, skip_header=True):"""读取CSV文件的内容。参数:file_path (str): CSV文件的路径。skip_header (bool): 是否跳过表头数据,默认为True。返回:list: 包含CSV文件内容的列表。"""print(f'读取原始数据集文件: {file_path}')with open(file_path, 'r', encoding='utf-8') as f:if skip_header:# 跳过表头数据f.readline()reader = csv.reader(f)return [row for row in reader]  # 读取csv文件的内容def print_unique_columns(data):"""打印表格数据中每一列去重后的数据。参数:data (list): 包含表格数据的列表。"""if not data:print("没有读取到任何数据。")return# 获取每一列的数据columns = zip(*data)# 打印每一列去重后的数据for i, column in enumerate(columns):unique_values = set(column)unique_count = len(unique_values)print(f"第{i}列去重后的数据(最多前20个):")# 如果数据大于20个,则只打印前20个if unique_count > 20:for value in list(unique_values)[:20]:print(value)print(f"共 {unique_count} 个不同的值")else:for value in unique_values:print(value)print(f"共 {unique_count} 个不同的值")print()data = read_file('./成人收入预测数据集.csv')
print_unique_columns(data)

运行结果:

对上述每一列内容进行梳理,梳理结果如下:

列的序号(第几列)原始数据表头名称表头名称中文解释对应列取值举例取值个数数据类型数据处理办法
0age年龄69, 62, 37, 80, 3473连续量保留
1workclass工作类型Without-pay, State-gov, Federal-gov9离散量保留
2fnlwgt疑似邮编编号226092, 209770, 3184021648连续量舍弃
3education教育程度Masters, Bachelors, Some-college16离散量保留
4education-num教育年限3, 4, 16, 2, 1116连续量保留
5marital-status婚姻状况Divorced, Separated, Never-married7离散量保留
6occupation职业类型Exec-managerial, Adm-clerical, Handlers-cleaners15离散量保留
7relationship家庭关系Wife, Not-in-family, Other-relative6离散量保留
8race种族Amer-Indian-Eskimo, White, Black5离散量保留
9sex性别Female, Male2离散量保留
10capital-gain投资利得3781, 2062, 401119连续量保留
11capital-loss投资损失1816, 1876, 176292连续量保留
12hours-per-week每周工作时长37, 80, 3494连续量保留
13native-country出生国家Japan, England, Guatemala42离散量保留

通过分析上述每列内容可知:

  • 数据集中,age、education-num、capital-gain、capital-loss、hours-per-week等字段的内容一般都是数字,可以视为连续量。这类数据直接使用即可,不需要做向量化处理(因为是数字,机器能够处理)。
  • 数据集中,workclass、education、marital-status、occupation、relationship、race、sex、native-country等字段内容一般都是表示状态,属于离散量;由于其内容不是数字,为了让机器能够处理,我们后续需要进行向量化处理。
  • 数据集中,fnlwgt疑似是连续量,但是查看取值个数(21648)与总样本个数(32561个)不一致,所以确定该列不是类似身份证号的唯一编号数据(如果身份证可以舍弃,因为身份证跟收入没啥关系);该列可能是类似邮编的数据,虽然邮编可能与收入有一定关系,但是因为其取值数量比较大(21648个),这会导致特征数据过去庞大,所以选择舍弃。
离散量的编码

通过与chatGPT交流,我们了解到,离散量的编码常见方式有One-Hot编码标签编码序数编码Target编码哈希编码实体嵌入

  1. One-Hot编码:
    • 编码方式:将每个离散特征转换为多个二进制特征。
    • 优点:能够很好地表示分类特征,不会引入大小关系。
    • 缺点:会增加特征维度。
    • 适用场景:适用于没有大小关系的分类特征,如性别、产品类别等。
  2. 标签编码(Label Encoding):
    • 编码方式:将每个离散特征的取值映射为一个整数值。
    • 优点:简单直观。
    • 缺点:可能会让算法认为特征之间存在大小关系。
    • 适用场景:适用于没有明确大小关系的分类特征,但要注意可能带来的影响。
  3. 序数编码(Ordinal Encoding):
    • 编码方式:将每个离散特征的取值映射为一个有序的整数值。
    • 优点:能够保留特征之间的大小关系。
    • 缺点:对于没有明确大小关系的离散特征可能不太合适。
    • 适用场景:适用于有明确大小关系的有序离散特征,如学历、星级等。
  4. Target编码:
    • 编码方式:将每个离散特征的取值映射为目标变量的平均值或中位数。
    • 优点:能够捕捉特征取值与目标变量之间的关系,通常能提高模型性能。
    • 缺点:需要提前知道目标变量,不适用于无监督学习。
    • 适用场景:适用于有监督学习问题中,当目标变量与离散特征存在相关性时。
  5. 哈希编码:
    • 编码方式:将每个离散特征的取值通过哈希函数映射为一个整数值。
    • 优点:在处理高基数特征时较为有效,能减少内存占用。
    • 缺点:可能会产生冲突,导致信息丢失。
    • 适用场景:适用于高基数离散特征,且内存受限的情况下。
  6. 实体嵌入(Entity Embedding):
    • 编码方式:将每个离散特征的取值映射为一个低维的稠密向量。
    • 优点:能够学习特征之间的潜在关系,通常能提高模型性能。
    • 缺点:需要额外的训练过程来学习嵌入向量。
    • 适用场景:适用于复杂的机器学习问题,如自然语言处理、推荐系统等,能够更好地捕捉特征之间的潜在关系。

分析上述编码内容,其中

  • Target编码哈希编码实体嵌入暂未学习到,本次暂不做考虑。

  • 标签编码序数编码由于其存在潜在的数字大小对比,让算法认为特征之间存在大小关系,所以并不适用于上述的婚姻状况、职业类型、国家等。

所以,综上所述本次练习使用One-Hot编码,其编码示意图如下:

基于上面的思想,我们通过与GPT沟通了解到,sklearn的库函数中有OneHotEncoder,使用方法如下:

import numpy as np
from sklearn.preprocessing import OneHotEncoder# 示例数据
data = np.array([['A', 'X', 'P'],['B', 'Y', 'Q'],['A', 'X', 'R'],['B', 'Z', 'Q']
])# 创建 OneHotEncoder 实例
encoder = OneHotEncoder(sparse_output=False)# 对数据进行one-hot编码
encoded_data = encoder.fit_transform(data)print("原始数据:")
print(data)
print("\n编码后的数据:")
print(encoded_data)

执行结果如下:

分离特征和标签
def split_data(data):"""将数据分割为标签和数据。参数:data (list): 数据行的列表,第一个元素是标签。返回:numpy.ndarray: 标签数组。numpy.ndarray: 连接元素后的数据数组。"""# 去除每个元素的前后空格data = [[col.strip() for col in row] for row in data]# 分离数据和标签n_label = np.array([row[-1] for row in data])n_data = np.array([row[:-1] for row in data])return n_label, n_datacsv_data = read_file('./成人收入预测数据集.csv')
label, data = split_data(csv_data)
label, data

运行结果:

处理特征列

这部分的处理较为麻烦,整体思路是这样:

1、实现一个函数,传入三个参数:分别是离散量列的序号、连续量列序号和丢弃列序号

2、函数根据传入的列序号,分别进行如下处理:

  • 如果是连续量列,取出对应的列,不用做处理;

  • 如果是离散量列,取出对应的列,使用OneHotEncoder进行编码

  • 如果是丢弃列,则在矩阵中删除对应的列

    最后,在去除丢弃列之后,将连续量列和离散量列按照列方向堆叠为一个新的矩阵

import numpy as np
from sklearn.preprocessing import OneHotEncoder, StandardScalerdef vectorize_data_with_sklearn(data, onehot_cols, continuous_cols, exclude_cols=None):"""使用scikit-learn将给定的NumPy数组中的数据进行one-hot编码和标准化处理。参数:data (np.ndarray): 输入的NumPy数组onehot_cols (list): 需要进行one-hot编码的列索引continuous_cols (list): 不需要one-hot编码的连续量列索引exclude_cols (list, optional): 需要排除的列索引返回:np.ndarray: 经过one-hot编码和标准化的向量化数据"""# 排除不需要处理的列if exclude_cols:data = np.delete(data, exclude_cols, axis=1)onehot_cols = [col - sum(col > exc for exc in exclude_cols) for col in onehot_cols if col not in exclude_cols]# 解释过程:# 1. 遍历 onehot_cols 中的每个索引 col# 2. 检查 col 是否在 exclude_cols 中#    - 如果在,计算 col 在 exclude_cols 中的位置 sum(col > exc for exc in exclude_cols)#    - 并从 col 中减去这个值,更新 col 的索引#    - 例如: col = 1, 在 exclude_cols 中的位置为 0, 则更新后 col = 1 - 0 = 1#    - ⭐ 这样可以确保 onehot_cols 中的索引能正确对应到数据的列# 3. 如果 col 不在 exclude_cols 中,则保留原始索引continuous_cols = [col - sum(col > exc for exc in exclude_cols) for col in continuous_cols if col not in exclude_cols]# 解释过程:# 1. 遍历 continuous_cols 中的每个索引 col# 2. 检查 col 是否在 exclude_cols 中#    - 如果在,计算 col 在 exclude_cols 中的位置 sum(col > exc for exc in exclude_cols)#    - 并从 col 中减去这个值,更新 col 的索引#    - 例如: col = 2, 在 exclude_cols 中的位置为 0, 则更新后 col = 2 - 0 = 2#    - ⭐ 这样可以确保 continuous_cols 中的索引能正确对应到数据的列# 3. 如果 col 不在 exclude_cols 中,则保留原始索引else:onehot_cols = onehot_cols[:]continuous_cols = continuous_cols[:]# 对离散量列进行one-hot编码onehot_encoder = OneHotEncoder(sparse_output=False)one_hot_data = onehot_encoder.fit_transform(data[:, onehot_cols])# 对连续量列进行标准化scaler = StandardScaler()continuous_data = scaler.fit_transform(data[:, continuous_cols])# 将one-hot编码结果和标准化后的连续量列拼接起来final_data = np.hstack((one_hot_data, continuous_data))return final_datacsv_data = read_file('./成人收入预测数据集.csv')
label, data = split_data(csv_data)# 对数据进行切分
onehot_cols = [1, 3, 5, 6, 7, 8, 9, 13]
continuous_cols = [0, 2, 4, 10, 11, 12]# 排除列增加最后一列
exclude_cols = [2, 13]
vectorized_data = vectorize_data_with_sklearn(data, onehot_cols, continuous_cols, exclude_cols)
vectorized_data

运行结果:

处理标签列

因为标签列的内容只有两种情况:‘<=50K’ 和’>50K’,所以只需要将这一列中’<=50K’替换为0,'>50K’替换为1即可。

import numpy as np
from sklearn.preprocessing import LabelBinarizerdef binarize_labels(labels):"""将标签二值化。参数:labels (numpy.ndarray): 原始标签数组。返回:numpy.ndarray: 二值化后的标签数组。"""lb = LabelBinarizer()binarized_labels = lb.fit_transform(labels)return binarized_labelsvectorized_label = binarize_labels(label)
vectorized_label
试验算法

为了能够将整个流程跑通,我们仍然选择决策树算法跑通流程。


from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifierdef decision_tree(label, data, test_size=0.2):"""决策树模型的训练和评估。参数:train_data_file_path (str): 向量化数据的文件路径。test_size (float): 测试集的比例,默认为0.2。"""print('开始加载训练数据...')# 训练集和测试集切分X_train, X_test, y_train, y_test = train_test_split(data, label, test_size=test_size)print('开始训练决策树模型...')# 数据预测clf = DecisionTreeClassifier()clf.fit(X_train, y_train)y_pred = clf.predict(X_test)# 评估print('开始决策树预测...')accuracy = np.mean(y_pred == y_test)print(f'预测准确率:{accuracy}')# 读取文件
listdata = read_file('./成人收入预测数据集.csv')
# 对数据进行切分
label, data = split_data(listdata)# 对数据进行切分
onehot_cols = [1, 3, 5, 6, 7, 8, 9, 13]
continuous_cols = [0, 2, 4, 10, 11, 12]# 排除列增加最后一列
exclude_cols = [2, 13]    
vectorized_data = vectorize_data_with_sklearn(data, onehot_cols, continuous_cols, exclude_cols)
vectorized_label = binarize_labels(label)decision_tree(vectorized_label, vectorized_data)

运行结果:

工程优化

通过以上的工作,整体构建数据集→训练模型→预测模型流程已经跑通,接下来进行代码重构优化。

1、将整体代码使用面向对象封装为类实现

2、在模型预测部分加入KNN、贝叶斯、线性回归、随机森林、SVC向量机的方式

3、将预测结果使用matplotlib绘制出来

4、给关键代码处增加带有时间戳的日志

以上工作就交给GPT来完成了,最后重构的代码请见Github仓库

遴选算法

通过运行上述工程优化后的代码,执行结果如下:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/347029.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MEGALODON:突破传统,实现高效无限上下文长度的大规模语言模型预训练和推理

在人工智能领域&#xff0c;尤其是在自然语言处理&#xff08;NLP&#xff09;中&#xff0c;大模型&#xff08;LLMs&#xff09;的预训练和推理效率一直是研究的热点。最近&#xff0c;一项突破性的研究提出了一种新型神经网络架构——MEGALODON&#xff0c;旨在解决传统Tran…

2024/06/11--代码随想录算法1/17|理论基础、509. 斐波那契数、70. 爬楼梯、746. 使用最小花费爬楼梯

理论基础 动态规划&#xff1a;当前状态由前面的状态推导而来 贪心&#xff1a;局部选最优 动态规划5步曲 确定dp数组&#xff08;dp table&#xff09;以及下标的含义确定递推公式dp数组如何初始化确定遍历顺序举例推导dp数组 509. 斐波那契数 力扣链接 动态规划5步曲 确定d…

33.星号三角阵(二)

上海市计算机学会竞赛平台 | YACSYACS 是由上海市计算机学会于2019年发起的活动,旨在激发青少年对学习人工智能与算法设计的热情与兴趣,提升青少年科学素养,引导青少年投身创新发现和科研实践活动。https://www.iai.sh.cn/problem/742 题目描述 给定一个整数 𝑛,输出一个…

Linux用户,用户组,所有者权限分配,sftp用户权限分配

注意以下命令执行需要在root用户下执行 tenant命令切换至root命令 sudo -do root 删除用户信息 1.不删除用户主目录 userdel user_name 2.删除用户主目录 userdel -r user_name usermod命令修改用户账户权限 更改用户名 sudo usermod -l newusername oldusername 更…

QNX 7.0.0开发总结

1 QNX编译 1.1 基本概念 QNX可以直接使用Linux Makefile编译库和二进制&#xff0c;在Makefile文件中指定CCaarch64-unknown-nto-qnx7.0.0-g&#xff0c;或者CCx86_64-pc-nto-qnx7.0.0-g&#xff0c;保存退出后&#xff0c;运行source /qnx_sdk_path/qnxsdp-env.sh&#xff0c;…

React+TS前台项目实战(四)-- layout整体布局搭建

文章目录 前言一、Layout组件代码注释说明二、Content全局组件注释说明三、Header基础布局组件1. Header父级组件注释说明2. NavMenu导航子组件详细说明 四、效果展示总结 前言 本文主要讲Layout整体布局的构建以及全局内容盒子Content组件的使用。还包括了导航栏组件的基本封…

实现开源可商用的 ChatPDF RAG:密集向量检索(R)+上下文学习(AG)

实现 ChatPDF & RAG&#xff1a;密集向量检索&#xff08;R&#xff09;上下文学习&#xff08;AG&#xff09; RAG 是啥&#xff1f;实现 ChatPDF怎么优化 RAG&#xff1f; RAG 是啥&#xff1f; RAG 是检索增强生成的缩写&#xff0c;是一种结合了信息检索技术与语言生成…

python之点云数据读取与可视化

1、前言 将文件中点云数据进行读取进来&#xff0c;并进行数据处理&#xff0c;将处理后的点云数据进行可视化显示&#xff0c;是非常常见的操作。本博客介绍如何将文本形式的点云数据读取进来&#xff0c;并进行可视化展示。 2、点云可视化 点云可视化即将点云数据在三维空间…

亚马逊竞品分析之如何查找竞品

初选之后,要对产品进行竞品分析,查找竞品的方法: 1.Best Seller榜单查找 进入到该类目的BS榜单去找跟你选中的产品的竞品 看完BS榜单会找出一部分竞品 这个找相似也可以点击,是插件的一个以图搜图的功能,不过有的时候不太好使,某些同款产品可能搜不到。 Edge浏览器搭…

第7章 用户输入和 while 循环

第7章 用户输入和 while 循环 7.1 函数 input()的工作原理7.1.1 编写清晰的程序7.1.2 使用 int()来获取数值输入7.1.3 求模运算符 7.2 while 循环简介7.2.1 使用 while 循环7.2.2 让用户选择何时退出7.2.3 使用标志7.2.4 使用 break 退出循环7.2.5 在循环中使用 continue7.2.6 …

【Vue】Vuex概述

文章目录 一、使用场景二、优势三、注意 官网&#xff1a;https://vuex.vuejs.org/zh/ Vuex 是一个 Vue 的 状态管理工具&#xff0c;状态就是数据。 工具可以直接理解成插件 大白话&#xff1a;Vuex 是一个插件&#xff0c;可以帮我们管理 Vue 通用的数据 (多组件共享的数据)…

【Affine / Perspective Transformation】

文章目录 仿射变换介绍仿射变换 python 实现——cv2.warpAffine透视变换透视变换 python 实现——cv2.warpPerspective牛刀小试各类变换的区别与联系仿射变换和单应性矩阵透视变换和单应性矩阵 仿射变换介绍 仿射变换&#xff08;Affine Transformation&#xff09;&#xff0…

适配器模式和装饰器模式

文章目录 适配器模式1.引出适配器模式1.多功能转换插头2.基本介绍3.工作原理 2.类适配器1.基本介绍2.类图3.代码实现1.Voltage220V.java2.Voltage5V.java3.VoltageAdapter.java4.Phone.java5.Client.java6.结果 4.类适配器的注意事项 3.对象适配器1.基本介绍2.使用对象适配器改…

C51单片机 串口打印printf重定向

uart.c文件 #include "uart.h"void UartInit(void) //4800bps11.0592MHz {PCON | 0x80; //使能波特率倍速位SMODSCON 0x50; //8位数据,可变波特率。使能接收TMOD & 0x0F; //清除定时器1模式位TMOD | 0x20; //设定定时器1为8位自动重装方式TL1 0xF4; //设…

明天15点!如何打好重保预防针:迎战HVV经验分享

在当今数字化时代&#xff0c;网络攻击日益猖獗&#xff0c;各行各业面临的网络安全威胁不断升级。从钓鱼邮件到复杂的APT攻击&#xff0c;网络犯罪分子的手法层出不穷&#xff0c;给各行各业的信息安全带来了前所未有的挑战。 在这样的背景下&#xff0c;"HVV行动"应…

那些年我看过的技术书(持续更新,大佬的成长之路)

作为一个技术人啊&#xff0c;要学会多看书&#xff0c;发展自己。哦也&#xff01;你可以不关注&#xff0c;就把文章点个收藏吧&#xff0c;万一以后想看书了呢&#xff1f; 网络安全 CTF篇 入门篇 《极限黑客攻防&#xff1a;CTF赛题揭秘》 Web篇 Reserve篇 《IDApro…

ON DUPLICATE KEY UPDATE 子句

ON DUPLICATE KEY UPDATE 是 MySQL 中的一个 SQL 语句中的子句&#xff0c;主要用于在执行 INSERT 操作时处理可能出现的重复键值冲突。当尝试插入的记录导致唯一索引或主键约束冲突时&#xff08;即试图插入的记录的键值已经存在于表中&#xff09;&#xff0c;此子句会触发一…

virtual box安装invalid installation directory

问题原因 看官方文档Chapter 2. Installation Details 第2.1.2所示&#xff0c;安装目录需要满足两个条件&#xff1a; 一是&#xff1a;需要安装目录的所有父目录都要满足以下访问控制条件 Users S-1-5-32-545:(OI)(CI)(RX) Users S-1-5-32-545…

【Python列表解锁】:掌握序列精髓,驾驭动态数据集合

文章目录 &#x1f680;一、列表&#x1f308;二、常规操作&#x1f4a5;增&#x1f4a5;删&#x1f4a5;改&#x1f4a5;查 ⭐三、补充操作 &#x1f680;一、列表 列表是一个能够存储多个同一或不同元素的序列 列表&#xff1a;list ---- [] 列表属于序列类型&#xff08;容器…

ES升级--05--快照生成 和备份

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 备份ES数据1.关闭集群自动均衡2.执行同步刷新3.停止集群节点的Elasticsearch服务4.修改Elasticsearch配置文件&#xff0c;开启快照功能&#xff0c;配置仓库目录为…