一、项目简介

1.鸢尾花数据集:

   150朵

   4个特征:花萼长度,花萼宽度,花瓣长度,花瓣宽度(cm)

   3个类别:Setosa,Versicolor,Virginica

2.实验流程

   加载数据集

   划分数据集

   选择3分类模型,进行训练

   输出测试集上的精度,对比不同分类模型的结果

   要求:多次划分数据集,得到多个精度

3.个人建议

   数据集分析和结果分析在报告中要讲述清楚

二、实验前的基础知识

1.数据集

   data= load_iris():获取鸢尾花数据集对象,此对象类似字典的特殊对象(Bunch),包含了数据集的所有信息(特征的数据,特征的名子,标签,对数据集的描述)

   datas = data.data:从鸢尾花数据集中提取特征数据(具体值),提取结果为二维数组。形状为 (150, 4)),意思是有 150 个样本,每个样本有 4 个特征值。比如 datas[0] 就是第一个鸢尾花样本的 4 个特征值:[5.1, 3.5, 1.4, 0.2]

   labels = data.target:从鸢尾花数据集中提取标签的数据。0(山鸢尾)、1(变色鸢尾)、2(维吉尼亚鸢尾)。labels 是一个一维数组(形状为 (150,)),每个元素对应 datas 中相同位置样本的品种。比如 labels[0] = 0,表示第一个样本是山鸢尾。

   描述性说明:

属性名 具体说明什么
target_names 标签(target)的实际含义名称(而非数字 0/1/2)。比如:['setosa', 'versicolor', 'virginica'],对应标签 0 = 山鸢尾,1 = 变色鸢尾,2 = 维吉尼亚鸢尾。
feature_names 特征(data)的实际含义名称(而非单纯的第 1/2/3/4 列)。比如:['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)'],即花萼长度、花萼宽度、花瓣长度、花瓣宽度(单位厘米)。
DESCR 数据集的详细描述文档(最核心的 “说明”)。包含:1. 数据集来源、作者、发表背景;2. 样本数量、特征数量、标签类别;3. 数据集的用途、经典应用场景;4. 相关参考文献等。
filename 数据集文件在你本地 Python 环境中的存储路径(方便定位原始数据文件)。
frame 数据集是否基于 DataFrame 存储(iris 数据集为 None,代表是纯数组形式)。
data_module 数据集加载的模块路径(内部实现相关,对新手无实际使用价值)。

2.X和y

   Xy 是约定俗成的变量命名,分别代表特征标签(也叫目标变量)。

   X(特征 / 输入):通常是一个二维数组 / 矩阵,决定y的因素。

   y(标签 / 输出 / 目标):你最终要预测的结果

变量 含义
X_train 训练集的特征(80% 样本的特征数据)
X_test 测试集的特征(20% 样本的特征数据)
y_train 训练集的标签(80% 样本的目标结果)
y_test 测试集的标签(20% 样本的目标结果)

   用 X_train 训练模型,让模型学习 “特征→标签” 的规律,用 X_test 喂给训练好的模型,得到预测结果,再和 y_test 对比,验证模型准不准。

变量 作用 阶段
y_train 给模型当 “标准答案”,教模型学习 训练阶段
y_test 验证模型学的好不好,不参与学习 测试阶段

  简而言之:y_train用于训练模型,y_test用于检验模型性能。

3.随机种子

test_size 只规定了划分的 “比例”,但 “哪些样本进训练集 / 测试集” 是由随机种子控制的。

4.K 折交叉验证

   数据分为K块,每一块都当一次测试集

   kf = KFold(n_splits=5, shuffle=True, random_state=40)

部分 通俗解释(用 “切蛋糕” 类比)
KFold(...) 调用 sklearn 的 “切分工具”,专门用来做 K 折划分
n_splits=5 把数据集(150 个鸢尾花样本)平均切成 5 块,每块 30 个样本(150÷5=30)
shuffle=True 切蛋糕前先把 150 个样本 “打乱顺序”(避免样本按类别排序,比如前 50 个全是 setosa)
random_state=40 固定 “打乱的规则”—— 每次都按同一顺序打乱,保证切分结果不变(可复现)
kf = ... 把这个 “切分工具” 保存到变量kf里,后续直接用这个工具切分数据

5.cv_scores = []

这行是创建一个空列表,作用是 “记录每一次折的测试精度”。

6.分类模型

   逻辑回归模型:画多条直线分类

迭代(max_iter):迭代是逻辑回归模型的核心。每一次迭代都是机器在学习如何分类鸢尾花,并且获取经验,调整学习参数,得到最优的参数来接受最终的分类检验任务。

核心循环代码:

    for fold, (train_idx, test_idx) in enumerate(kf.split(X)):

    X_train_cv, X_test_cv = X[train_idx], X[test_idx]

    y_train_cv, y_test_cv = y[train_idx], y[test_idx]

英文部分 中文翻译 通俗解释
for 循环 / 遍历 就是 “重复做某件事”,比如循环 5 次就做 5 次
fold 折 / 轮次 表示 “第几次验证”,比如 5 折交叉验证,fold 就是 0、1、2、3、4(从 0 开始数)
train_idx 训练集索引 “idx” 是 index(索引 / 行号)的缩写,train_idx 就是 “训练数据的行号列表”
test_idx 测试集索引 test_idx 就是 “测试数据的行号列表”
in 在... 里面 固定语法,比如 “在苹果堆里挑苹果”
enumerate() 枚举 / 给序号 给每一次循环的内容加一个 “编号”,比如第 1 次循环编号 0,第 2 次编号 1
kf K 折交叉验证对象 提前定义好的 “K 折拆分工具”(比如分成 5 份)
kf.split(X) 拆分 X 数据 split 是 “拆分”,kf.split (X) 就是 “用 K 折工具把 X 数据的行号拆分成训练 / 测试两组”
循环轮次(fold) train_idx(训练行号) test_idx(测试行号) X_train_cv(取 X 的哪些行) X_test_cv(取 X 的哪些行)
0 [1,2,3,4] [0] X 的 1、2、3、4 行 X 的 0 行
1 [0,2,3,4] [1] X 的 0、2、3、4 行 X 的 1 行
2 [0,1,3,4] [2] X 的 0、1、3、4 行 X 的 2 行

SVM模型(可以非线性分类)

    model = SVC(random_state=40, kernel='rbf', gamma='scale')

参数 中文解释 核心作用(结合鸢尾花)
SVC 支持向量分类器 Scikit-learn 中专门用于分类的 SVM 模型(区别于用于回归的 SVR)
random_state=40 随机种子 固定模型的随机初始化过程,保证每次运行结果完全一致(比如你跑 10 次,精度都是 1.0);如果不设,每次运行结果可能略有差异(比如一次 0.99,一次 1.0)
kernel='rbf' 核函数为高斯核(径向基函数) 让 SVM 从 “只能画直线” 变成 “能画任意曲线”,适配鸢尾花中 1 类和 2 类的轻微非线性重叠;(如果设kernel='linear',SVM 就退化成线性模型,和逻辑回归效果接近)
gamma='scale' 高斯核的带宽参数(自动缩放) 控制 “曲线的弯曲程度”:✅ gamma='scale'(默认):自动根据特征尺度计算 gamma(1/(特征数×特征方差)),适配鸢尾花的 4 个 cm 级特征,不用手动调;❌ 如果 gamma 太小:曲线太平缓,和线性模型没区别;❌ 如果 gamma 太大:曲线太弯曲,会过拟合(把噪声当规律)

   

随机森林模型

model_cv = RandomForestClassifier(random_state=40, n_estimators=100, max_depth=5)

参数 中文解释 核心作用(结合鸢尾花)
RandomForestClassifier 随机森林分类器 基于 “多棵决策树投票” 的集成模型,不是单棵 “随机树” 哦~
random_state=40 随机种子 固定模型的随机过程(比如树的生成、特征采样),保证 5 折交叉验证中每一轮的结果可复现;如果不设,不同轮次的精度可能忽高忽低,对比无意义
n_estimators=100 决策树数量 随机森林里包含 100 棵独立的决策树,最终分类结果由 100 棵树 “投票” 决定;✅ 100 是行业默认值:树太少(比如 10 棵)→ 结果不稳定;树太多(比如 500 棵)→ 训练变慢,精度提升微乎其微;对鸢尾花来说,100 棵树足够覆盖所有特征组合
max_depth=5 每棵树的最大深度 限制单棵决策树最多长 5 层(比如 “花瓣长度> 5cm→花瓣宽度 > 1.8cm→判定为 2 类”,最多 5 个判断步骤);✅ 核心作用:防止过拟合!鸢尾花数据简单,若不限制深度,单棵树会 “死抠” 个别样本的噪声(比如异常的花瓣长度),导致泛化能力下降;5 层对鸢尾花来说 “刚好够用”—— 既能捕捉核心特征规律,又不会过度拟合

三、代码

逻辑回归

#coding:utf-8
from sklearn.datasets import load_iris
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split, KFold
from sklearn.metrics import accuracy_score

#1.加载数据集

#取出鸢尾花数据集
data=load_iris()
#取出鸢尾花的特征数据
X=data.data
#取出鸢尾花的类别标签
y=data.target

#2.划分数据集
print("方法1,普通划分")
#分成训练集和测试集(0.7train,0.3test)
X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.3,random_state=40)
print("训练集样本数:",len(X_train),"测试集样本数:", len(X_test))
print("方法2,5折交叉实验")
kf=KFold(n_splits=5,shuffle=True,random_state=40)
#存储5次测试精度
cv_scores=[]

#3.选择分类模型
#3.1逻辑回归
model=LogisticRegression(random_state=40,max_iter=500)
# 训练模型
model.fit(X_train,y_train)
#用测试集预测
y_pred=model.predict(X_test)
#4输出测试集精度
accuracy=accuracy_score(y_test,y_pred)
print(f"普通划分 - 测试集精度:{accuracy:.4f}")

#3.25折交叉实验
for fold, (train_index, test_index) in enumerate(kf.split(X)):
    X_train_cv, X_test_cv = X[train_index], X[test_index]
    y_train_cv, y_test_cv = y[train_index], y[test_index]
#初始化模型
    model_cv = LogisticRegression(random_state=40, max_iter=200)
# 训练模型
    model_cv.fit(X_train_cv, y_train_cv)
#用测试集预测
    y_pred_cv = model_cv.predict(X_test_cv)
    fold_accuracy = accuracy_score(y_test_cv, y_pred_cv)
    cv_scores.append(fold_accuracy)
    print(f"第{fold + 1}折 测试精度:{fold_accuracy:.4f}")
avg_accuracy = sum(cv_scores) / len(cv_scores)
print(f"5折交叉验证 - 平均测试精度:{avg_accuracy:.4f}")

SVM

#coding:utf-8
from sklearn.datasets import load_iris
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split, KFold
from sklearn.metrics import accuracy_score

#1.加载数据集

#取出鸢尾花数据集
data=load_iris()
#取出鸢尾花的特征数据
X=data.data
#取出鸢尾花的类别标签
y=data.target

#2.划分数据集

print("方法1,普通划分")
#分成训练集和测试集(0.7train,0.3test)
X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.3,random_state=40)
print("训练集样本数:",len(X_train),"测试集样本数:", len(X_test))

print("方法2,5折交叉实验")
kf=KFold(n_splits=5,shuffle=True,random_state=40)
#存储5次测试精度
cv_scores=[]

#3.选择分类模型
#3.1逻辑回归
model=SVC(random_state=40, kernel='rbf', gamma='scale')
# 训练模型
model.fit(X_train,y_train)
#用测试集预测
y_pred=model.predict(X_test)
#4输出测试集精度
accuracy=accuracy_score(y_test,y_pred)
print(f"普通划分 - 测试集精度:{accuracy:.4f}")

#3.25折交叉实验
for fold, (train_index, test_index) in enumerate(kf.split(X)):
    X_train_cv, X_test_cv = X[train_index], X[test_index]
    y_train_cv, y_test_cv = y[train_index], y[test_index]
#初始化模型
    model_cv = SVC(random_state=40, kernel='rbf', gamma='scale')
# 训练模型
    model_cv.fit(X_train_cv, y_train_cv)
#用测试集预测
    y_pred_cv = model_cv.predict(X_test_cv)
    fold_accuracy = accuracy_score(y_test_cv, y_pred_cv)
    cv_scores.append(fold_accuracy)
    print(f"第{fold + 1}折 测试精度:{fold_accuracy:.4f}")
avg_accuracy = sum(cv_scores) / len(cv_scores)
print(f"5折交叉验证 - 平均测试精度:{avg_accuracy:.4f}")

随机森林

#coding:utf-8
from sklearn.datasets import load_iris
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split, KFold
from sklearn.metrics import accuracy_score

#1.加载数据集

#取出鸢尾花数据集
data=load_iris()
#取出鸢尾花的特征数据
X=data.data
#取出鸢尾花的类别标签
y=data.target

#2.划分数据集

print("方法1,普通划分")
#分成训练集和测试集(0.7train,0.3test)
X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.3,random_state=60)
print("训练集样本数:",len(X_train),"测试集样本数:", len(X_test))

print("方法2,5折交叉实验")
kf=KFold(n_splits=5,shuffle=True,random_state=60)
#存储5次测试精度
cv_scores=[]

#3.选择分类模型
#3.1逻辑回归
model = RandomForestClassifier(random_state=40, n_estimators=100, max_depth=5, min_samples_split=2)
# 训练模型
model.fit(X_train,y_train)
#用测试集预测
y_pred=model.predict(X_test)
#4输出测试集精度
accuracy=accuracy_score(y_test,y_pred)
print(f"普通划分 - 测试集精度:{accuracy:.4f}")

#3.25折交叉实验
for fold, (train_index, test_index) in enumerate(kf.split(X)):
    X_train_cv, X_test_cv = X[train_index], X[test_index]
    y_train_cv, y_test_cv = y[train_index], y[test_index]
#初始化模型
    model_cv = RandomForestClassifier(random_state=40, n_estimators=100, max_depth=5)
# 训练模型
    model_cv.fit(X_train_cv, y_train_cv)
#用测试集预测
    y_pred_cv = model_cv.predict(X_test_cv)
    fold_accuracy = accuracy_score(y_test_cv, y_pred_cv)
    cv_scores.append(fold_accuracy)
    print(f"第{fold + 1}折 测试精度:{fold_accuracy:.4f}")
avg_accuracy = sum(cv_scores) / len(cv_scores)
print(f"5折交叉验证 - 平均测试精度:{avg_accuracy:.4f}")

数据集分析

from sklearn.datasets import load_iris
data=load_iris()
print(data.DESCR)
import numpy as np
print("\n===== 特征描述性统计 =====")
stats = {
    "均值": np.mean(data.data, axis=0),
    "标准差": np.std(data.data, axis=0),
    "最小值": np.min(data.data, axis=0),
    "最大值": np.max(data.data, axis=0)
}
for key, value in stats.items():
    print(f"{key}:", value.round(2))

四、实验总结

逻辑回归适用:因为鸢尾花近似线性可分,数据简单,线性模型足够高效准确。

SVM 适用:因为数据存在少量非线性重叠,高斯核 SVM 能更好地分割边界。

随机森林适用:因为数据特征区分度高、干扰的没用的数据少,集成树模型能稳定学习分类规则且不易过拟合

五、致谢

感谢豆包,感谢小红书老师们

机器学习项目一:鸢尾花⚜️分类 - 小红书

Python机器学习的hello world 鸢尾花分类 - 小红书

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐