当前位置: 首页 > news >正文

python实战(一)——iris鸢尾花数据集分类

一、任务背景

        本文是python实战系列专栏的第一篇文章,我们将从分类开始由浅入深逐步学习如何使用python完成常规的机器学习/深度学习任务。iris数据集是经典的机器学习入门数据集,许多分类任务教程都会以这个数据集作为示例,它的数据量是150条,由三种不同品种的鸢尾花数据构成,每种鸢尾花各50条数据。显然,这是一个多分类(三分类)任务,我们将从头开始进行探索性数据分析及机器学习建模。

二、机器学习建模流程

1、探索性数据分析

        探索性数据分析是建模的第一步,尤其是机器学习任务。尽管这是一个很标准、很干净的数据集,我们还是按照惯例对它进行基础的分析(特征列、空值、各列取值范围等),以对该数据集有个初步的了解和认知。

(1)数据集读取

        由于iris数据集实在太经典,所以很多python库都内置了该数据集的调用代码,例如在scikit-learn中可以这样调用:

from sklearn import datasets# 加载iris数据集
iris = datasets.load_iris()
# 获取特征数据
iris_X = iris.data
# 获取目标(类别)数据
iris_y = iris.target

        但是实际应用中,我们更多的是读取本地文件,所以这里笔者从Kaggle下载了iris数据文件并本地读取:

# 读取csv文件数据
path = './data/iris.csv'
df = pd.read_csv(path)
print('数据量:', len(df))
print(df.head())

        结果如下,可见该数据集总共有150行,6列,其中一列是Id,在我们这次任务中作用不大,后面会去掉:

        根据官方的介绍,各列的含义如下:

  • SepalLengthCm:花萼长度,即花萼的最长部分,单位是厘米。
  • SepalWidthCm:花萼宽度,即花萼的最宽部分,单位是厘米。
  • PetalLengthCm:花瓣长度,即花瓣的最长部分,单位是厘米。
  • PetalWidth Cm:花瓣宽度,即花瓣的最宽部分,单位是厘米。

        而标签列Species中的类别有:

  • Iris setosa:山鸢尾
  • Iris virginica:变色鸢尾
  • Iris versicolor:维吉尼亚鸢尾

(2)查看各列中是否有空值

        去空值是数据处理阶段的重要步骤,存在空值的数据会导致后面的特征工程或者建模报错。下面的代码逐列统计是否有空值:

print('空值数量统计:')
print(df.isnull().sum())

        结果如下,每一列都很干净:

(3)简要统计各列的数据数值分布

        统计各列的数据分布主要目的是看看每一列各自以及相互之间的数据差异。如果某一列的数据取值之间非常接近(例如一个极端情况是整一列的取值都是1),那么可能这一列对于建模来说是没有意义的,可以去掉。同时,分位数也能帮我们判断当前列数据中是否存在离群点,可以考虑去掉离群点。此外,如果列和列之间取值范围差得较大(比如一列的取值范围是0-1,另一列是100-200)就需要进行归一化/标准化操作,量纲差异太大会导致模型学习过程中对特征重要性的判别出现误差。这里我们选择不对原始数据进行归一化或者标准化,一是各列之间的量纲接近,二是我们后面用的是决策树模型建模,决策树不需要归一化/标准化操作。

print(df.describe())

(4)检查标签列是否符合建模要求

        从上面的图中我们可以看到,标签列是文本类型,无法进行建模。因此需要将标签转换成模型可理解的数值类型(转为数值类型才可以计算损失)。

# 定义各类别对应的索引号
label_index = {'Iris-setosa':0, 'Iris-versicolor':1, 'Iris-virginica':2}
# apply方法应用到标签列中的每一个标签
df['Species'] = df['Species'].apply(lambda x: label_index[x])

2、数据可视化

        我们可以使用sklearn提供的PCA降维方法将原始数据降维成2维(也可以进行3维可视化),并且可视化出来。

# 分出特征列和标签列
X = df[['SepalLengthCm', 'SepalWidthCm', 'PetalLengthCm', 'PetalWidthCm']].values.tolist()
y = df['Species'].tolist()
# 降维
pca = PCA(n_components=2)
pca_data = pca.fit_transform(X)
# 可视化
plt.scatter(pca_data[:, 0], pca_data[:, 1], c=y)
plt.show()

        可视化结果如下图,虽然可视化的过程没有标出来哪个颜色对应哪一类的鸢尾花,但我们可以看到某一类鸢尾花很轻易就可以与另外两类区分开来,而距离较近的两类似乎数据也是线性可分的,那么我们可以考虑用一个简单的模型完成这个任务。

3、数据划分

        了解了数据分布之后,我们可以开始进行数据的划分了,即划分训练集和测试集。其中,训练集用于训练模型,测试集用于测试模型的效果(测试集数据应当是在模型的训练阶段是未出现过的,否则就存在模型作弊的问题了)。

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, stratify=y, random_state=2024)
print('训练集数据量:', len(X_train))
print('测试集数据量:', len(X_test))

        这里讲一下几个比较重要的参数:

  • stratify:控制训练集和测试集的标签类别比例,默认是无,但是我们一般会根据y进行划分。假如我们有100个数据,70个属于A类,30个属于B类,如果不指定该参数且test_size恰好是0.3,那么就有可能出现我们训练集中的70个都是A类数据,这样子模型只学了A的数据规律,使用测试集的30个数据进行测试的时候效果就很糟糕了。而如果指定了该参数,那么算法会确保训练集中各类别的比例和测试集中的各类别比例一致(如果算出来的数量不是整数会自动取整),假设这个例子我们指定的stratify是y,那么训练集中A和B类别的比例和测试集一致,都是7:3,则训练集中A类有49个,B类有21个,测试集中A类有21个,B类有9个,保持了数据集划分的公平性。
  • test_size:指定训练集和测试集划分过程中的比例,用0-1开区间之间的小数就可以了。
  • random_state:指定随机数,以保证模型结果可复现。

        打印数据划分结果如下:

4、模型训练

        这里我们使用一个决策树分类器作为模型,使用训练数据迭代训练决策树模型并输出模型的各项性能指标。

dt = DecisionTreeClassifier(criterion='gini', splitter='best', max_depth=5, class_weight='balanced', random_state=2024)
dt.fit(X_train, y_train)
y_pred = dt.predict(X_test)
# 多分类问题需要指定average,其中:
# micro计算全局精确度:通过将所有类别的真正例和假正例汇总,然后计算整体的精确度。
# macro计算未加权平均精确度:简单地计算每个类别的精确度,然后求平均值,不考虑每个类别的样本数量。
# weighted计算加权平均精确度:计算每个类别的精确度,然后根据每个类别的样本数量进行加权平均。
print('Precision:', precision_score(y_test, y_pred, average='macro'))
print('Recall:', recall_score(y_test, y_pred, average='macro'))
print('F1:', f1_score(y_test, y_pred, average='macro'))

        这里有几个模型参数需要注意:

  • criterion:可选的有“gini”、“entropy”、“log_loss”,用于指定构建树时用于分裂节点的准则,默认是”gini”,即基尼不纯度。当使用gini作为参数的值时,决策树在每个节点的分裂都旨在最小化基尼不纯度;而使用entropy时,决策树在每个节点的分裂都旨在最大化信息增益,这意味着最小化熵。
  • splitter:可选的有“best”、“random”,用于指定如何选择分裂节点的方法,默认是”best”。当设置为best时,决策树会考虑所有可能的特征和所有可能的分割点,并选择能够最好地减少criterion取值的最佳分裂点。
  • max_depth:指定树的深度,默认是不限制,也就是树可以无限生长直到满足损失要求,但是对于一些模型规模有限制的场景建议限制树的深度在一定范围,否则模型可能非常大。
  • class_weight:默认为无,可以输入字典(键为类别,值为当前类别的样本数)也可以直接写“balanced”。建议直接指定“balanced”,这样模型会自动为不同类别的样本赋予权重。这个参数在样本类别不平衡的时候非常重要,假设一个二分类任务中样本A有98个,B有2个,不设置权重模型可能只学A的特征,从而忽略B类(因为即便B类预测错误,总体数据上仍然能够有一个很好的指标结果),但设置class_weight后,模型会认为A和B同样重要,从而避免样本类别不平衡造成的模型问题。
  • random_state:指定随机数以便复现模型结果。

        以下是训练后的模型在测试集上的表现,由于数据集较为简单,模型的指标效果不错。当然,如果进行更细致的参数调优,模型可以取得更好的效果,这里就不演示了。

三、完整代码

import pandas as pd
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import precision_score, recall_score, f1_scorepath = './data/iris.csv'
df = pd.read_csv(path)
print('数据量:', len(df))
print(df.head())
print('空值数量统计:')
print(df.isnull().sum())
print(df.describe())
df.drop(['Id'], axis=1)
label_index = {'Iris-setosa':0, 'Iris-versicolor':1, 'Iris-virginica':2}
df['Species'] = df['Species'].apply(lambda x: label_index[x])X = df[['SepalLengthCm', 'SepalWidthCm', 'PetalLengthCm', 'PetalWidthCm']].values.tolist()
y = df['Species'].tolist()
pca = PCA(n_components=2)
pca_data = pca.fit_transform(X)
plt.scatter(pca_data[:, 0], pca_data[:, 1], c=y)
plt.show()X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, stratify=y, random_state=2024)
print('训练集数据量:', len(X_train))
print('测试集数据量:', len(X_test))
dt = DecisionTreeClassifier(criterion='gini', splitter='best', max_depth=5, class_weight='balanced', random_state=2024)
dt.fit(X_train, y_train)
y_pred = dt.predict(X_test)
print('Precision:', precision_score(y_test, y_pred, average='macro'))
print('Recall:', recall_score(y_test, y_pred, average='macro'))
print('F1:', f1_score(y_test, y_pred, average='macro'))

四、总结

        本文使用决策树模型对iris鸢尾花数据集进行了分类建模,由于数据量小、数据集简单且各特征含义明确,本文直接使用所有特征进行建模。实际的建模任务中,特征选择也是重要的一步,我们需要选择对建模真正有用的特征(特征选择),而不是所有特征都用于建模(比如一份数据可能有100多个特征列,但实际对建模有用的可能只有5、6个特征)。后面的博文将会陆续介绍这些技巧,并展示如何在更复杂的生产数据中使用这些技巧进行建模。

相关文章:

python实战(一)——iris鸢尾花数据集分类

一、任务背景 本文是python实战系列专栏的第一篇文章,我们将从分类开始由浅入深逐步学习如何使用python完成常规的机器学习/深度学习任务。iris数据集是经典的机器学习入门数据集,许多分类任务教程都会以这个数据集作为示例,它的数据量是150条…...

k8s-对命名空间资源配额

对k8s命名空间限制的方法有很多种,今天来演示一下很常用的一种 用的k8s对象就是ResourceQuota 一:创建命名空间 kubectl create ns test #namespace命名空间可以简写成ns 二: 对命名空间进行限制 创建resourcequota vim resourcequ…...

Failed to connect to github.com port 443

git push无法连接443端口 **问题1****方法一:取消代理设置**git命令 其他解决方案1. **设置 Git 使用 HTTP 而不是 HTTPS**2. **检查证书**3. **配置 Git 忽略 SSL 验证(不推荐)**4. **检查代理设置** 问题1 Failed to connect to github.com…...

【设计模式系列】简单工厂模式

一、什么是简单工厂模式 简单工厂模式(Simple Factory Pattern)是一种设计模式,其中包含一个工厂类,根据传入的参数不同,返回不同类的实例。这个工厂类封装了对象的创建逻辑,使得客户端代码可以从直接创建…...

给定一个正整数n随机生成n个字节即生成2n个十六进制数将其组成字符串返回secrets.token_hex(n)

【小白从小学Python、C、Java】 【考研初试复试毕业设计】 【Python基础AI数据分析】 给定一个正整数n 随机生成n个字节 即生成2n个十六进制数 将其组成字符串返回 secrets.token_hex(n) [太阳]选择题 根据题目代码,执行的结果错误的是? import secrets …...

[Gtk] 工程

MediaPlayer 可执行文件工程 结构 . ├── BUILD ├── ButtonHelper.cpp ├── ButtonHelper.h ├── CMakeLists.txt ├── DrawingAreaHelper.cpp ├── DrawingAreaHelper.h ├── layout.ui └── main.cpp CMakeLists.txt # 1) cmake basic cmake_minimum_r…...

基于Multisim的汽车尾灯控制电路设计与仿真

假设汽车尾部左右量测各有3个指示灯(用发光二极管模拟)1. 汽车正常运行时指示灯全灭;2.右转弯时,右侧3个指示灯按右循环顺序点亮;.3. 左转弯时,左侧3个指示灯按左循环顺序点亮;4.临时刹车时所有…...

Leetcode 3326. Minimum Division Operations to Make Array Non Decreasing

Leetcode 3326. Minimum Division Operations to Make Array Non Decreasing 1. 解题思路2. 代码实现 题目链接:3326. Minimum Division Operations to Make Array Non Decreasing 1. 解题思路 这一题的话就是要看出来题中给出的operation的本质事实上就是将任意…...

redo文件误删除后通过逻辑备份进行恢复

问题描述 开发同事让在一个服务器上查找下先前库的备份文件是否存在,如果存在进行下恢复。翻了服务器发现备份文件存在,多愁了一眼竟翻到了该备份文件于2024.6.17日恢复过的日志,赶紧和开发沟通说2024.6.17号已经恢复过了为啥还要恢复&#x…...

7805的输出电压如何调整?

7805稳压集成电路的输出电压通常是固定的,标称为5V。然而,在实际应用中,可以通过一些方法调整其输出电压,尽管这些调整方法可能会使电路变得更加复杂或需要额外的元件。以下是几种可能的调整方法: 1. 使用不同型号的稳…...

git命令使用一览【自用】

git常见操作: git initgit remote add master【分支名字】 gitgits.xxxxx【仓库中获取的ssh链接或者http协议的链接】检查远程仓库是否链接成功。 git remote -v出现以下画面就可以git pull,git push了...

MES系列-报表和分析

MES系列-报表和分析 MES系列文章目录 ISA-95制造业中企业和控制系统的集成的国际标准-(1) ISA-95制造业中企业和控制系统的集成的国际标准-(2) ISA-95制造业中企业和控制系统的集成的国际标准-(3) ISA-95制造业中企业和控制系统的集成的国际标准-(4) ISA-95制造业中企业和控制…...

如何在分布式环境中实现高可靠性分布式锁

目录 一、简单了解分布式锁 (一)分布式锁:应对分布式环境的同步挑战 (二)分布式锁的实现方式 (三)分布式锁的使用场景 (四)分布式锁需满足的特点 二、Redis 实现分…...

Vue基础(4)

自定义指令 除了默认设置的核心指令( v-model 和 v-show ), Vue 也允许注册自定义指令。在vue中使用directive来创建自定义指令 钩子函数 指令定义函数提供了几个钩子函数(可选): bind: 只调用一次,指令第一次绑定到元素时调用&…...

Redis高阶篇之Redis单线程与多线程

文章目录 0 前言1. 为什么Redis是单线程?1.1 Redis单线程1.2 为什么Redis3时代单线程快的原因1.3 使用单线程原因 2.为什么逐渐加入多线程呢?2.1 如何解决 3.redis6/7的多线程特性和IO多路复用入门3.1主线程和IO线程怎么协作完成请求处理的3.2 Unix网络编…...

【C++】STL——priority_queue优先级队列

目录 前言priority_queue的使用简单使用在OJ中的使用 priority_queue的模拟实现基本功能仿函数在这里插入图片描述 前言 上一节我们说了stack和queue这两种容器适配器,而priority_queue(优先级队列)同样也是属于容器适配器,它会优…...

大数据新视界 --大数据大厂之大数据在智慧城市建设中的应用:打造智能生活的基石

💖💖💖亲爱的朋友们,热烈欢迎你们来到 青云交的博客!能与你们在此邂逅,我满心欢喜,深感无比荣幸。在这个瞬息万变的时代,我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…...

使用枚举来实现策略模式

使用很多if else的场景 public void save(String type,Object data){if("db".equals(type)){saveInDb(data);}else if("file".equals(type)){saveInFile(data);}else if("oss".equals(type)){saveInOss(data);}}使用枚举来解决 public enum Save…...

区块链技术原理

1. 引言 区块链的定义 区块链是一种分布式账本技术(Distributed Ledger Technology,DLT),其核心特征是通过密码学的方式将数据打包成一个个区块,按时间顺序依次相连,形成一个不可篡改、公开透明的链式数据…...

Spring Boot 接口数据加解密

今天聊下接口安全问题,涉及到接口的加密和解密 经常和外部单位接口调用梳理了相关技术方案,主要的需求点如下: 1,尽量少改动,不影响之前的业务逻辑 2,考虑到时间紧迫性,可采用对称性加密方式&…...

利用ngx_stream_return_module构建简易 TCP/UDP 响应网关

一、模块概述 ngx_stream_return_module 提供了一个极简的指令&#xff1a; return <value>;在收到客户端连接后&#xff0c;立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量&#xff08;如 $time_iso8601、$remote_addr 等&#xff09;&a…...

MVC 数据库

MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...

Nginx server_name 配置说明

Nginx 是一个高性能的反向代理和负载均衡服务器&#xff0c;其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机&#xff08;Virtual Host&#xff09;。 1. 简介 Nginx 使用 server_name 指令来确定…...

三体问题详解

从物理学角度&#xff0c;三体问题之所以不稳定&#xff0c;是因为三个天体在万有引力作用下相互作用&#xff0c;形成一个非线性耦合系统。我们可以从牛顿经典力学出发&#xff0c;列出具体的运动方程&#xff0c;并说明为何这个系统本质上是混沌的&#xff0c;无法得到一般解…...

爬虫基础学习day2

# 爬虫设计领域 工商&#xff1a;企查查、天眼查短视频&#xff1a;抖音、快手、西瓜 ---> 飞瓜电商&#xff1a;京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空&#xff1a;抓取所有航空公司价格 ---> 去哪儿自媒体&#xff1a;采集自媒体数据进…...

Android第十三次面试总结(四大 组件基础)

Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成&#xff0c;用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机&#xff1a; ​onCreate()​​ ​调用时机​&#xff1a;Activity 首次创建时调用。​…...

安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)

船舶制造装配管理现状&#xff1a;装配工作依赖人工经验&#xff0c;装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书&#xff0c;但在实际执行中&#xff0c;工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...

PAN/FPN

import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...

GitFlow 工作模式(详解)

今天再学项目的过程中遇到使用gitflow模式管理代码&#xff0c;因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存&#xff0c;无论是github还是gittee&#xff0c;都是一种基于git去保存代码的形式&#xff0c;这样保存代码…...

解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用

在工业制造领域&#xff0c;无损检测&#xff08;NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统&#xff0c;以非接触式光学麦克风技术为核心&#xff0c;打破传统检测瓶颈&#xff0c;为半导体、航空航天、汽车制造等行业提供了高灵敏…...